diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/stylesheets/main/entries.scss | 10 | ||||
-rw-r--r-- | app/controllers/blogs_controller.rb | 48 | ||||
-rw-r--r-- | app/models/blog.rb | 1 | ||||
-rw-r--r-- | app/models/concerns/votable.rb | 43 | ||||
-rw-r--r-- | app/models/vote.rb | 6 | ||||
-rw-r--r-- | app/views/blogs/_blog.html.haml | 4 | ||||
-rw-r--r-- | app/views/blogs/voted.js.erb | 12 |
7 files changed, 124 insertions, 0 deletions
diff --git a/app/assets/stylesheets/main/entries.scss b/app/assets/stylesheets/main/entries.scss index edf1706..3b7215c 100644 --- a/app/assets/stylesheets/main/entries.scss +++ b/app/assets/stylesheets/main/entries.scss | |||
@@ -416,3 +416,13 @@ | |||
416 | font-weight: bold; | 416 | font-weight: bold; |
417 | } | 417 | } |
418 | } | 418 | } |
419 | |||
420 | .post-vote { | ||
421 | float: right; | ||
422 | position: relative; | ||
423 | right: 0.5em; | ||
424 | |||
425 | a { | ||
426 | text-decoration: none; | ||
427 | } | ||
428 | } | ||
diff --git a/app/controllers/blogs_controller.rb b/app/controllers/blogs_controller.rb index 0d218ae..2f9df49 100644 --- a/app/controllers/blogs_controller.rb +++ b/app/controllers/blogs_controller.rb | |||
@@ -38,4 +38,52 @@ class BlogsController < ApplicationController | |||
38 | }) | 38 | }) |
39 | end | 39 | end |
40 | 40 | ||
41 | def upvote | ||
42 | @blog = Blog.find_by_slug(params[:slug]) | ||
43 | |||
44 | raise ActiveRecord::RecordNotFound unless @blog | ||
45 | raise ActiveRecord::RecordNotFound unless @blog.published | ||
46 | |||
47 | respond_to do |format| | ||
48 | if @blog.upvote! request.remote_ip | ||
49 | format.html do | ||
50 | flash[:notice] = "You have upvoted the blog post \"#{@blog.title}\"." | ||
51 | redirect_to @blog | ||
52 | end | ||
53 | format.js { render "voted" } | ||
54 | format.xml { head :ok } | ||
55 | else | ||
56 | format.html do | ||
57 | flash[:notice] = "You have already voted on the blog post \"#{@blog.title}\"." | ||
58 | redirect_to @blog | ||
59 | end | ||
60 | format.xml { render :xml => { :error => "Someone from your IP address has already voted on this blog post."} } | ||
61 | end | ||
62 | end | ||
63 | end | ||
64 | |||
65 | def downvote | ||
66 | @blog = Blog.find_by_slug(params[:slug]) | ||
67 | |||
68 | raise ActiveRecord::RecordNotFound unless @blog | ||
69 | raise ActiveRecord::RecordNotFound unless @blog.published | ||
70 | |||
71 | respond_to do |format| | ||
72 | if @blog.downvote! request.remote_ip | ||
73 | format.html do | ||
74 | flash[:notice] = "You have downvoted the blog post \"#{@blog.title}\"." | ||
75 | redirect_to @blog | ||
76 | end | ||
77 | format.js { render "voted" } | ||
78 | format.xml { head :ok } | ||
79 | else | ||
80 | format.html do | ||
81 | flash[:notice] = "You have already voted on the blog post \"#{@blog.title}\"." | ||
82 | redirect_to @blog | ||
83 | end | ||
84 | format.xml { render :xml => { :error => "Someone from your IP address has already voted on this blog post."} } | ||
85 | end | ||
86 | end | ||
87 | end | ||
88 | |||
41 | end | 89 | end |
diff --git a/app/models/blog.rb b/app/models/blog.rb index 6db75ec..03643bf 100644 --- a/app/models/blog.rb +++ b/app/models/blog.rb | |||
@@ -1,5 +1,6 @@ | |||
1 | class Blog < ApplicationRecord | 1 | class Blog < ApplicationRecord |
2 | include Recordable | 2 | include Recordable |
3 | include Votable | ||
3 | 4 | ||
4 | acts_as_taggable | 5 | acts_as_taggable |
5 | 6 | ||
diff --git a/app/models/concerns/votable.rb b/app/models/concerns/votable.rb new file mode 100644 index 0000000..ba6e6d5 --- /dev/null +++ b/app/models/concerns/votable.rb | |||
@@ -0,0 +1,43 @@ | |||
1 | module Votable | ||
2 | extend ActiveSupport::Concern | ||
3 | |||
4 | included do | ||
5 | has_many :votes, as: :votable | ||
6 | |||
7 | def already_upvoted?(ip) | ||
8 | !votes.where(ip: ip, upvote: 1).empty? | ||
9 | end | ||
10 | |||
11 | def already_downvoted?(ip) | ||
12 | !votes.where(ip: ip, upvote: 0).empty? | ||
13 | end | ||
14 | |||
15 | def upvote!(ip) | ||
16 | return false if already_upvoted?(ip) | ||
17 | |||
18 | if already_downvoted?(ip) | ||
19 | votes.where(ip: ip, upvote: 0).first.delete | ||
20 | self.downvotes -= 1 | ||
21 | save! | ||
22 | else | ||
23 | votes.create(ip: ip, upvote: 1).save | ||
24 | self.upvotes += 1 | ||
25 | save! | ||
26 | end | ||
27 | end | ||
28 | |||
29 | def downvote!(ip) | ||
30 | return false if already_downvoted?(ip) | ||
31 | |||
32 | if already_upvoted?(ip) | ||
33 | votes.where(ip: ip, upvote: 1).first.delete | ||
34 | self.upvotes -= 1 | ||
35 | save! | ||
36 | else | ||
37 | votes.create(ip: ip, upvote: 0).save | ||
38 | self.downvotes += 1 | ||
39 | save! | ||
40 | end | ||
41 | end | ||
42 | end | ||
43 | end | ||
diff --git a/app/models/vote.rb b/app/models/vote.rb new file mode 100644 index 0000000..e2d8386 --- /dev/null +++ b/app/models/vote.rb | |||
@@ -0,0 +1,6 @@ | |||
1 | class Vote < ApplicationRecord | ||
2 | belongs_to :votable, polymorphic: true | ||
3 | |||
4 | validates :upvote, presence: true, inclusion: { in: [0, 1] } | ||
5 | validates :ip, presence: true | ||
6 | end | ||
diff --git a/app/views/blogs/_blog.html.haml b/app/views/blogs/_blog.html.haml index ec61bb5..1f86ae8 100644 --- a/app/views/blogs/_blog.html.haml +++ b/app/views/blogs/_blog.html.haml | |||
@@ -19,3 +19,7 @@ | |||
19 | %strong= blog.user.login.capitalize | 19 | %strong= blog.user.login.capitalize |
20 | on | 20 | on |
21 | = blog.visible_date.strftime("%B #{blog.visible_date.day.ordinalize}, %Y at %-I:%M:%S%P") | 21 | = blog.visible_date.strftime("%B #{blog.visible_date.day.ordinalize}, %Y at %-I:%M:%S%P") |
22 | .post-vote{ id: "blog-vote-section-#{blog.id}" } | ||
23 | %span.vote-link{ id: "blog-upvote-link-#{blog.id}" }= link_to_unless (not blog.published or blog.already_upvoted?(request.remote_ip)), "👍", upvote_blog_path(blog), remote: true, rel: "nofollow", class: "blog-upvote-link", method: :post | ||
24 | %span.post-rating{ id: "blog-rating-#{blog.id}" }= blog.upvotes - blog.downvotes | ||
25 | %span.vote-link{ id: "blog-downvote-link-#{blog.id}" }= link_to_unless (not blog.published or blog.already_downvoted?(request.remote_ip)), "👎", downvote_blog_path(blog), remote: true, rel: "nofollow", class: "blog-downvote-link", method: :post | ||
diff --git a/app/views/blogs/voted.js.erb b/app/views/blogs/voted.js.erb new file mode 100644 index 0000000..951c740 --- /dev/null +++ b/app/views/blogs/voted.js.erb | |||
@@ -0,0 +1,12 @@ | |||
1 | $("#blog-rating-<%= @blog.id %>").html('<%= escape_javascript("#{@blog.upvotes - @blog.downvotes}") %>'); | ||
2 | |||
3 | <% if @blog.already_upvoted? request.remote_ip %> | ||
4 | $("#blog-upvote-link-<%= @blog.id %>").html("👍"); | ||
5 | <% elsif @blog.already_downvoted? request.remote_ip %> | ||
6 | $("#blog-downvote-link-<%= @blog.id %>").html("👎"); | ||
7 | <% else %> | ||
8 | $("#blog-upvote-link-<%= @blog.id %>").html('<%= escape_javascript(link_to("👍", upvote_blog_path(@blog), remote: true, rel: "nofollow", class: "blog-upvote-link", method: :post)) %>'); | ||
9 | $("#blog-downvote-link-<%= @blog.id %>").html('<%= escape_javascript(link_to("👎", downvote_blog_path(@blog), remote: true, rel: "nofollow", class: "blog-downvote-link", method: :post)) %>'); | ||
10 | <% end %> | ||
11 | |||
12 | $("#blog-vote-section-<%= @blog.id %>").effect('highlight', {}, 2000); | ||