Initial commit

This commit is contained in:
Bart Akeley 2017-10-14 22:04:44 -05:00
commit a5ee819324
6 changed files with 253 additions and 0 deletions

10
.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
/target
/lib
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port

19
README.md Normal file
View file

@ -0,0 +1,19 @@
# aretherecookies-server
the server that knows where the cookies are
## Prerequisites
You will need [Leiningen][] 2.0.0 or above installed.
[leiningen]: https://github.com/technomancy/leiningen
## Running
To start a web server for the application, run:
lein ring server-headless
To test a request/response, run:
curl http://localhost:3000/fooditems

16
project.clj Normal file
View file

@ -0,0 +1,16 @@
(defproject aretherecookies-server "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.8.0"]
[compojure "1.5.1"]
[ring/ring-defaults "0.2.1"]
[org.clojure/java.jdbc "0.7.3"]
[org.postgresql/postgresql "42.1.4.jre6"]
[com.mchange/c3p0 "0.9.5.2"]
[ring-middleware-format "0.7.2"]]
:plugins [[lein-ring "0.9.7"]]
:ring {:handler aretherecookies-server.handler/app}
:profiles
{:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
[ring/ring-mock "0.3.0"]]}})

132
scripts/ddl.sql Normal file
View file

@ -0,0 +1,132 @@
CREATE EXTENSION IF NOT EXISTS "postgis";
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TYPE quantity AS ENUM ('none', 'few', 'many', 'lots');
CREATE TYPE category AS ENUM ('beverages', 'desserts', 'entrees', 'other');
create table food_items (
id uuid PRIMARY KEY,
name VARCHAR(100),
place_id VARCHAR(50),
category category,
images VARCHAR,
thumbImage VARCHAR,
loc geography(POINT,4326)
);
create table quantities (
food_item_id uuid,
date timestamp (1) with time zone,
quantity quantity,
PRIMARY KEY(food_item_id, date)
);
CREATE INDEX food_loc_index ON food_items USING GIST ( loc );
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Big John Cookies',
'ChIJf5QJFBK1RIYRjjfxZz9Z0O0',
'desserts',
'https://s-media-cache-ak0.pinimg.com/564x/e7/5f/08/e75f08b00c0bc7f2b01b3d1a636389f6.jpg,http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
'http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.7532464 30.270667599999996)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Jelly Filled Donuts',
'ChIJ72if-Qe1RIYRCzMucGEEdBA',
'desserts',
'https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg',
'https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Spelt Brownies',
'ChIJG44vBQi1RIYRvWGHdYUolZY',
'desserts',
'http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg',
'http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.7419085 30.265019100000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Oatmeal Raisin Cookies',
'ChIJf5QJFBK1RIYRjjfxZz9Z0O0',
'desserts',
'http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg',
'http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.7532464 30.270667599999996)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Donuts with Sprinkles',
'ChIJ72if-Qe1RIYRCzMucGEEdBA',
'desserts',
'https://dannivee.files.wordpress.com/2013/10/img_1950.jpg',
'https://dannivee.files.wordpress.com/2013/10/img_1950.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Powdered Donuts',
'ChIJ72if-Qe1RIYRCzMucGEEdBA',
'desserts',
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Snickerdoodles',
'ChIJr3szW6a1RIYRkM7LRpnBIO0',
'desserts',
'http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg',
'http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.73798459999999, 30.266898599999998)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
'Pizza',
'ChIJr3szW6a1RIYRkM7LRpnBIO0',
'desserts',
'http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg',
'http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.73798459999999 30.266898599999998)')
);
INSERT INTO quantities SELECT id, current_timestamp, 'many' FROM food_items;
SELECT
*,
ST_AsGeoJSON(loc) as location,
ST_Distance(
loc,
ST_GeogFromText('SRID=4326;POINT(-97.7286718 30.3033267)')
) / 1609 as distance
FROM food_items
WHERE
ST_DWithin(
loc,
ST_GeogFromText('SRID=4326;POINT(-97.7286718 30.3033267)'),
10 * 1609
)
ORDER BY distance ASC;

View file

@ -0,0 +1,62 @@
(ns aretherecookies-server.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[clojure.java.jdbc :as jdbc])
(:import com.mchange.v2.c3p0.ComboPooledDataSource))
(def db-spec {:dbtype "postgresql"
:subprotocol "postgresql"
:subname "//localhost:5432/test1"
:user "bartronx7"
:password "abc123"})
(defn pool
[spec]
(let [cpds (doto (ComboPooledDataSource.)
(.setDriverClass (:classname spec))
(.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
(.setUser (:user spec))
(.setPassword (:password spec))
;; expire excess connections after 30 minutes of inactivity:
(.setMaxIdleTimeExcessConnections (* 30 60))
;; expire connections after 3 hours of inactivity:
(.setMaxIdleTime (* 3 60 60)))]
{:datasource cpds}))
(def pooled-db (delay (pool db-spec)))
(def location-query "
SELECT
id,
name,
place_id,
category,
images,
thumbImage,
ST_AsGeoJSON(loc) as location,
ST_Distance(
loc,
ST_GeogFromText('SRID=4326;POINT(-97.7286718 30.3033267)')
) / 1609 as distance
FROM food_items
WHERE
ST_DWithin(
loc,
ST_GeogFromText('SRID=4326;POINT(-97.7286718 30.3033267)'),
10 * 1609
)
ORDER BY distance ASC;")
(jdbc/query @pooled-db
[location-query])
(defn food-items-handler [request]
(jdbc/query @pooled-db
[location-query]))
(defroutes app-routes
(GET "/fooditems" request (food-items-handler request)))
(def app
(wrap-defaults app-routes site-defaults))

View file

@ -0,0 +1,14 @@
(ns aretherecookies-server.handler-test
(:require [clojure.test :refer :all]
[ring.mock.request :as mock]
[aretherecookies-server.handler :refer :all]))
(deftest test-app
(testing "main route"
(let [response (app (mock/request :get "/"))]
(is (= (:status response) 200))
(is (= (:body response) "Hello World"))))
(testing "not-found route"
(let [response (app (mock/request :get "/invalid"))]
(is (= (:status response) 404)))))