git.fiddlerwoaroof.com
Browse code

working, basically

fiddlerwoaroof authored on 16/02/2015 06:47:25
Showing 7 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+config.rb
2
+*.swp
0 3
new file mode 100644
... ...
@@ -0,0 +1,107 @@
1
+-- Data model
2
+DROP TABLE reviews;
3
+DROP TABLE reviewers;
4
+DROP TABLE restaurants;
5
+CREATE TABLE restaurants (
6
+  id SERIAL UNIQUE NOT NULL,
7
+  restaurant_name TEXT NOT NULL,
8
+  short_name TEXT NOT NULL UNIQUE,
9
+  PRIMARY KEY (id)
10
+);
11
+
12
+CREATE TABLE reviewers (
13
+  id SERIAL UNIQUE NOT NULL,
14
+  reviewer_name TEXT UNIQUE NOT NULL,
15
+  created_date TIMESTAMP,
16
+  last_seen TIMESTAMP,
17
+  PRIMARY KEY (id)
18
+);
19
+
20
+CREATE TABLE reviews (
21
+  id SERIAL UNIQUE NOT NULL,
22
+  reviewer_id INTEGER REFERENCES reviewers (id) NOT NULL,
23
+  restaurant_id INTEGER REFERENCES restaurants (id) NOT NULL,
24
+  review_posted TIMESTAMP DEFAULT current_timestamp,
25
+  review TEXT NOT NULL,
26
+  UNIQUE (reviewer_id, restaurant_id),
27
+  PRIMARY KEY (id)
28
+);
29
+
30
+-- Stored Procedures
31
+
32
+CREATE OR REPLACE FUNCTION get_reviews(sn text)
33
+  RETURNS TABLE(review text, reviewer text)  AS $$
34
+BEGIN
35
+  RETURN QUERY SELECT reviews.review, reviewers.reviewer_name
36
+                FROM reviews
37
+                  INNER JOIN reviewers ON reviews.reviewer_id=reviewers.id
38
+                  INNER JOIN restaurants ON reviews.restaurant_id=restaurants.id
39
+                  WHERE restaurants.short_name=sn
40
+                  ORDER BY review_posted DESC,
41
+                           reviewer_name ASC;
42
+END;
43
+$$ LANGUAGE plpgsql;
44
+
45
+CREATE OR REPLACE FUNCTION put_review(sn text, rn text, review text)
46
+  RETURNS VOID AS $$
47
+DECLARE
48
+  restaurant_id int;
49
+  reviewer_id int;
50
+  nowstamp timestamp;
51
+BEGIN
52
+  SELECT restaurants.id INTO restaurant_id FROM restaurants WHERE restaurants.short_name=sn;
53
+  SELECT reviewers.id INTO reviewer_id FROM reviewers WHERE reviewers.reviewer_name=rn;
54
+
55
+  WITH new_values (rest_id, rev_id, review, tm) as (values (restaurant_id, reviewer_id, review, current_timestamp)),
56
+  upsert as
57
+  ( 
58
+      UPDATE reviews m 
59
+          SET restaurant_id = nv.rest_id,
60
+              reviewer_id = nv.rev_id,
61
+              review = nv.review,
62
+              review_posted = tm
63
+      FROM new_values nv
64
+      WHERE m.restaurant_id = nv.rest_id AND m.reviewer_id = nv.rev_id
65
+      RETURNING m.*
66
+  )
67
+  INSERT INTO reviews (restaurant_id, reviewer_id, review)
68
+  SELECT rest_id, rev_id, new_values.review
69
+  FROM new_values
70
+  WHERE NOT EXISTS (SELECT 1 
71
+                    FROM upsert up 
72
+                    WHERE up.restaurant_id = new_values.rest_id AND up.reviewer_id = new_values.rev_id);
73
+END;
74
+$$ LANGUAGE plpgsql;
75
+
76
+-- Test Data
77
+INSERT INTO restaurants  (restaurant_name, short_name) VALUES
78
+  ('Vigilante Coffee', 'vigilante-coffee'),
79
+  ('The Coffee Bar', 'the-coffee-bar'),
80
+  ('Peregrine Espresso', 'peregrine-espresso'),
81
+  ('Graffiato', 'graffiato');
82
+
83
+INSERT INTO reviewers (reviewer_name) VALUES
84
+  ('the_tooth_fairy'),
85
+  ('fiddlerwoaroof'),
86
+  ('grandma_johnson');
87
+
88
+INSERT INTO reviews (reviewer_id, restaurant_id, review) VALUES
89
+  ((SELECT id FROM reviewers where reviewer_name='the_tooth_fairy'), (SELECT id FROM restaurants where short_name='vigilante-coffee'), 'Great Coffee!'),
90
+  ((SELECT id FROM reviewers where reviewer_name='fiddlerwoaroof'),  (SELECT id FROM restaurants where short_name='vigilante-coffee'), 'My coffee was cold :/'),
91
+  ((SELECT id FROM reviewers where reviewer_name='grandma_johnson'), (SELECT id FROM restaurants where short_name='vigilante-coffee'), 'Bad Customer service, will actively avoid!'),
92
+  ((SELECT id FROM reviewers where reviewer_name='the_tooth_fairy'), (SELECT id FROM restaurants where short_name='peregrine-espresso'), 'The owner looked at me funny,  do not return!'),
93
+  ((SELECT id FROM reviewers where reviewer_name='fiddlerwoaroof'),  (SELECT id FROM restaurants where short_name='peregrine-espresso'), 'Great Coffee!'),
94
+  ((SELECT id FROM reviewers where reviewer_name='grandma_johnson'), (SELECT id FROM restaurants where short_name='peregrine-espresso'), 'Cockroach in bottom of french press, disgusting!'),
95
+  ((SELECT id FROM reviewers where reviewer_name='the_tooth_fairy'), (SELECT id FROM restaurants where short_name='graffiato'), 'Too Italian'),
96
+  ((SELECT id FROM reviewers where reviewer_name='fiddlerwoaroof'),  (SELECT id FROM restaurants where short_name='graffiato'), 'They dont have a peanut butter pizza!'),
97
+  ((SELECT id FROM reviewers where reviewer_name='grandma_johnson'), (SELECT id FROM restaurants where short_name='graffiato'), 'Whatever . . . '),
98
+  ((SELECT id FROM reviewers where reviewer_name='the_tooth_fairy'), (SELECT id FROM restaurants where short_name='the-coffee-bar'), 'Great Location! Good Coffee!'),
99
+  ((SELECT id FROM reviewers where reviewer_name='fiddlerwoaroof'),  (SELECT id FROM restaurants where short_name='the-coffee-bar'), 'Great Coffee! Good Location!'),
100
+  ((SELECT id FROM reviewers where reviewer_name='grandma_johnson'), (SELECT id FROM restaurants where short_name='the-coffee-bar'), 'This is too far from my knitting needles . . . ');
101
+
102
+SELECT * FROM reviews
103
+  RIGHT JOIN reviewers ON reviews.reviewer_id=reviewers.id
104
+  RIGHT JOIN restaurants ON reviews.restaurant_id=restaurants.id
105
+  WHERE short_name='vigilante-coffee';
106
+
107
+INSERT INTO reviewers (reviewer_name) VALUES ('the_great_one'); 
0 108
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+$appsettings = {
2
+  :dbname => 'howitis',
3
+  :dbuser => 'howitis',
4
+  :dbpassword => '<PW>',
5
+  :dbhost => '<HOST>'
6
+}
7
+
8
+
9
+
... ...
@@ -1,9 +1,82 @@
1 1
 # myapp.rb
2 2
 require 'sinatra'
3
+require 'sinatra/partial'
3 4
 require 'haml'
5
+require 'pg'
6
+require './config'
7
+
8
+def connect_db
9
+  return PG::Connection.open(:dbname=>$appsettings[:dbname],
10
+                             :host=>$appsettings[:dbhost],
11
+                             :user=>$appsettings[:dbuser],
12
+                             :password=>$appsettings[:dbpassword])
13
+end
14
+
15
+def check_user(db, user)
16
+  result = nil
17
+  db.prepare 'check_user', 'SELECT exists(SELECT 1 FROM reviewers WHERE reviewer_name=$1)'
18
+  if not user.nil?
19
+    v = db.exec_prepared('check_user', [user])
20
+    if v.first()['exists'] == 't'
21
+      result = user
22
+    end
23
+  end
24
+  return result
25
+end
26
+
27
+use Rack::Session::Pool, :expire_after => 2592000
4 28
 
5 29
 get '/' do
6
-  'Hello world!'
30
+  if params[:cur_user]
31
+    session[:cur_user] = params[:cur_user]
32
+  end
33
+
34
+  short_name = params.find do |x| x[1] == nil end
35
+  db = connect_db()
36
+  cur_user = check_user(db, session[:cur_user])
37
+  if short_name.nil?
38
+    restaurants = db.exec 'SELECT restaurant_name,short_name FROM restaurants ORDER BY restaurant_name ASC'
39
+    haml :index, :locals => {:restaurants => restaurants, :cur_user => cur_user}
40
+  else
41
+    short_name = short_name[0]
42
+    db.prepare 'get_restaurant_name', 'SELECT restaurant_name FROM restaurants WHERE short_name=$1'
43
+    db.prepare 'get_reviews', 'SELECT * FROM get_reviews($1)'
44
+
45
+    name = db.exec_prepared('get_restaurant_name', [short_name]).first['restaurant_name']
46
+    results = db.exec_prepared 'get_reviews', [short_name]
47
+    haml :restaurant, :locals => {:reviews => results,
48
+                             :name => name,
49
+                             :short_name => short_name,
50
+                             :cur_user => cur_user}
51
+  end
7 52
 end
8 53
 
54
+def short_name(name)
55
+  name.downcase().gsub(/[^a-zA-Z0-9]/, '-')
56
+end
57
+
58
+post '/add/restaurant' do
59
+  db = connect_db()
60
+  if check_user(db, session[:cur_user]).nil?
61
+    redirect to("/")
62
+  else
63
+    db.prepare 'add_restaurant', 'INSERT INTO restaurants (restaurant_name, short_name) VALUES ($1,$2)'
64
+    name = params[:restaurant_name]
65
+    sn = short_name(name)
66
+    db.exec_prepared 'add_restaurant', [name, sn]
67
+    redirect to("/?#{sn}")
68
+  end
69
+end
70
+
71
+
72
+post '/add/review' do
73
+  db = connect_db()
74
+  if check_user(db, session[:cur_user]).nil?
75
+    redirect to("/?#{params[:short_name]}")
76
+  else
77
+    db.prepare 'put_review',  'SELECT * FROM put_review($1, $2, $3)'
78
+    db.exec_prepared 'put_review', [ params[:short_name], session[:cur_user], params[:review] ]
79
+    redirect to("/?#{params[:short_name]}")
80
+  end
81
+end
9 82
 
10 83
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+%form{:action => "/add/review", :method => "post"}
2
+  %textarea{:name => "review"}
3
+    - if defined? review
4
+      = review['review']
5
+  %input{:type => "hidden", :value => short_name, :name => "short_name"}
6
+  %input{:type => "hidden", :value => cur_user, :name => "reviewer"}
7
+  %input{:type => "submit"}
8
+
9
+
... ...
@@ -1 +1,11 @@
1
-Hello World
1
+%article
2
+  %h1 How is
3
+  %ul.restaurants
4
+    - restaurants.each do |restaurant|
5
+      %a{:href => "/?#{restaurant['short_name']}"}
6
+        %li= "#{restaurant['restaurant_name']}?"
7
+    - if not cur_user.nil?
8
+      %li
9
+        %form{:action => "/add/restaurant", :method => "post"}
10
+          %input{:type => "text", :name => "restaurant_name"}
11
+          %input{:type => "submit"}
2 12
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+- comment_form_shown = false
2
+%article
3
+  %h1= name
4
+  %a{:href => "/"} Go Back>
5
+  %section#reviews
6
+    %h2 how it is:
7
+    %ul.reviews
8
+      - reviews.each do |review|
9
+        - if review['reviewer'] != cur_user
10
+          %li= "#{review['review']} &mdash;#{review['reviewer']}"
11
+        - else
12
+          %li= partial :comment_form,
13
+            :locals => {:review => review, :cur_user => cur_user, :short_name => short_name} 
14
+          - comment_form_shown = true
15
+      - if not comment_form_shown and not cur_user.nil?
16
+        %li= partial :comment_form,
17
+          :locals => {:cur_user => cur_user, :short_name => short_name}