diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/stylesheets/main/entries.scss | 62 | ||||
-rw-r--r-- | app/assets/stylesheets/main/layout.scss | 4 | ||||
-rw-r--r-- | app/controllers/comments_controller.rb | 59 | ||||
-rw-r--r-- | app/helpers/application_helper.rb | 10 | ||||
-rw-r--r-- | app/helpers/comments_helper.rb | 5 | ||||
-rw-r--r-- | app/models/blog.rb | 2 | ||||
-rw-r--r-- | app/models/comment.rb | 36 | ||||
-rw-r--r-- | app/views/blogs/_blog.html.haml | 2 | ||||
-rw-r--r-- | app/views/blogs/show.html.haml | 5 | ||||
-rw-r--r-- | app/views/comments/_comment.html.haml | 13 | ||||
-rw-r--r-- | app/views/comments/_form.html.haml | 23 | ||||
-rw-r--r-- | app/views/comments/_layout.html.haml | 6 |
12 files changed, 220 insertions, 7 deletions
diff --git a/app/assets/stylesheets/main/entries.scss b/app/assets/stylesheets/main/entries.scss index 56cd221..5fbd4ef 100644 --- a/app/assets/stylesheets/main/entries.scss +++ b/app/assets/stylesheets/main/entries.scss | |||
@@ -219,3 +219,65 @@ | |||
219 | margin-left: 1.5em; | 219 | margin-left: 1.5em; |
220 | } | 220 | } |
221 | } | 221 | } |
222 | |||
223 | .blog-comment { | ||
224 | margin: 0 1em; | ||
225 | |||
226 | .comment-avatar { | ||
227 | float: right; | ||
228 | margin-top: 1em; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | #comment-form { | ||
233 | fieldset { | ||
234 | border: 0; | ||
235 | |||
236 | &#comment-body-field { | ||
237 | label { | ||
238 | display: none; | ||
239 | } | ||
240 | |||
241 | textarea { | ||
242 | margin-top: 1em; | ||
243 | width: 99%; | ||
244 | height: 6em; | ||
245 | resize: none; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | &#comment-other-fields { | ||
250 | display: table; | ||
251 | padding: 1em; | ||
252 | width: 75%; | ||
253 | margin: 0 auto; | ||
254 | |||
255 | .comment-field { | ||
256 | display: table-row; | ||
257 | |||
258 | .comment-field-label { | ||
259 | text-align: right; | ||
260 | display: table-cell; | ||
261 | padding-right: 1em; | ||
262 | padding-bottom: 1em; | ||
263 | width: 50%; | ||
264 | |||
265 | label:after { | ||
266 | content: ":"; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | .field_with_errors { | ||
271 | label { | ||
272 | color: red; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | .comment-field-input { | ||
277 | display: table-cell; | ||
278 | width: 50%; | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | } | ||
diff --git a/app/assets/stylesheets/main/layout.scss b/app/assets/stylesheets/main/layout.scss index 278113a..9283f36 100644 --- a/app/assets/stylesheets/main/layout.scss +++ b/app/assets/stylesheets/main/layout.scss | |||
@@ -199,3 +199,7 @@ blockquote.bubble.bottom::after { | |||
199 | text-decoration: underline; | 199 | text-decoration: underline; |
200 | } | 200 | } |
201 | } | 201 | } |
202 | |||
203 | .clear { | ||
204 | clear: both; | ||
205 | } | ||
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb new file mode 100644 index 0000000..60c8f6a --- /dev/null +++ b/app/controllers/comments_controller.rb | |||
@@ -0,0 +1,59 @@ | |||
1 | class CommentsController < ApplicationController | ||
2 | def create | ||
3 | @blog = Blog.find_by_slug(params[:slug]) | ||
4 | |||
5 | raise ActiveRecord::RecordNotFound unless @blog | ||
6 | raise ActiveRecord::RecordNotFound unless @blog.published | ||
7 | |||
8 | @comment = @blog.comments.new(comment_params) | ||
9 | |||
10 | unless @comment.valid? | ||
11 | flash.alert = "Error posting comment." | ||
12 | render "blogs/show" | ||
13 | return | ||
14 | end | ||
15 | |||
16 | akismet_vars = %w{ HTTP_ACCEPT HTTP_ACCEPT_ENCODING } | ||
17 | akismet_params = { | ||
18 | type: "comment", | ||
19 | text: @comment.body, | ||
20 | created_at: DateTime.now, | ||
21 | author: @comment.username, | ||
22 | author_email: @comment.email, | ||
23 | author_url: @comment.website, | ||
24 | post_url: url_for(@comment.blog), | ||
25 | post_modified_at: @comment.blog.updated_at, | ||
26 | referrer: request.referrer, | ||
27 | env: request.env.slice(*akismet_vars) | ||
28 | } | ||
29 | |||
30 | is_spam, is_blatant = Akismet.check(request.ip, request.user_agent, akismet_params) | ||
31 | |||
32 | if is_blatant | ||
33 | # I am lying. | ||
34 | flash.notice = "Comment submitted successfully! It will need to be moderated before it shows up on the blog." | ||
35 | else | ||
36 | if is_spam | ||
37 | @comment.status = :pending | ||
38 | flash_message = "Comment submitted successfully! It will need to be moderated before it shows up on the blog." | ||
39 | else | ||
40 | @comment.status = :published | ||
41 | flash_message = "Comment posted successfully!" | ||
42 | end | ||
43 | |||
44 | if @comment.save | ||
45 | flash.notice = flash_message | ||
46 | else | ||
47 | flash.alert = "Error posting comment." | ||
48 | end | ||
49 | end | ||
50 | |||
51 | redirect_to @comment.blog | ||
52 | end | ||
53 | |||
54 | private | ||
55 | |||
56 | def comment_params | ||
57 | params.require(:comment).permit(:username, :email, :website, :body) | ||
58 | end | ||
59 | end | ||
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 861dd11..14d56cf 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb | |||
@@ -19,9 +19,15 @@ module ApplicationHelper | |||
19 | link_to title, {:sort => col, :dir => direction}, {:class => css_class} | 19 | link_to title, {:sort => col, :dir => direction}, {:class => css_class} |
20 | end | 20 | end |
21 | 21 | ||
22 | def markdown(text) | 22 | def markdown(text, params = {}) |
23 | options = { fenced_code_blocks: true, highlight: true } | 23 | options = { fenced_code_blocks: true, highlight: true } |
24 | Redcarpet::Markdown.new(HTML.new(), options).render(text).html_safe | 24 | |
25 | html_options = {} | ||
26 | if params[:restricted] | ||
27 | html_options[:filter_html] = true | ||
28 | end | ||
29 | |||
30 | Redcarpet::Markdown.new(HTML.new(html_options), options).render(text).html_safe | ||
25 | end | 31 | end |
26 | 32 | ||
27 | end | 33 | end |
diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb new file mode 100644 index 0000000..5939adc --- /dev/null +++ b/app/helpers/comments_helper.rb | |||
@@ -0,0 +1,5 @@ | |||
1 | module CommentsHelper | ||
2 | def show_comments(blog) | ||
3 | render "comments/layout", blog: blog | ||
4 | end | ||
5 | end | ||
diff --git a/app/models/blog.rb b/app/models/blog.rb index 415167c..b677e2b 100644 --- a/app/models/blog.rb +++ b/app/models/blog.rb | |||
@@ -3,6 +3,8 @@ class Blog < ApplicationRecord | |||
3 | 3 | ||
4 | acts_as_taggable | 4 | acts_as_taggable |
5 | 5 | ||
6 | has_many :comments | ||
7 | |||
6 | validates :title, presence: true | 8 | validates :title, presence: true |
7 | validates :body, presence: true, if: :published | 9 | validates :body, presence: true, if: :published |
8 | validates :slug, presence: true, format: /\A[-a-z0-9]+\z/, if: :published | 10 | validates :slug, presence: true, format: /\A[-a-z0-9]+\z/, if: :published |
diff --git a/app/models/comment.rb b/app/models/comment.rb new file mode 100644 index 0000000..9697100 --- /dev/null +++ b/app/models/comment.rb | |||
@@ -0,0 +1,36 @@ | |||
1 | class Comment < ApplicationRecord | ||
2 | extend Enumerize | ||
3 | |||
4 | belongs_to :blog | ||
5 | |||
6 | validates :body, presence: true | ||
7 | validates :username, presence: true | ||
8 | validates :email, presence: true, format: URI::MailTo::EMAIL_REGEXP | ||
9 | |||
10 | scope :published_and_ordered, -> { where(status: :published).order(published_at: :asc) } | ||
11 | |||
12 | enumerize :status, | ||
13 | in: [:published, :pending, :rejected], | ||
14 | default: :published, | ||
15 | predicates: true | ||
16 | |||
17 | before_save :set_published_at | ||
18 | |||
19 | def gravatar_url | ||
20 | hash = Digest::MD5.hexdigest(email) | ||
21 | "https://www.gravatar.com/avatar/#{hash}?size=40&default=identicon&rating=g" | ||
22 | end | ||
23 | |||
24 | private | ||
25 | |||
26 | def set_published_at | ||
27 | if self.published? | ||
28 | if self.published_at.blank? | ||
29 | self.published_at = DateTime.now | ||
30 | end | ||
31 | else | ||
32 | self.published_at = nil | ||
33 | end | ||
34 | end | ||
35 | |||
36 | end | ||
diff --git a/app/views/blogs/_blog.html.haml b/app/views/blogs/_blog.html.haml index 26657e7..8972c2e 100644 --- a/app/views/blogs/_blog.html.haml +++ b/app/views/blogs/_blog.html.haml | |||
@@ -15,4 +15,4 @@ | |||
15 | %cite.bubble | 15 | %cite.bubble |
16 | %strong Hatkirby | 16 | %strong Hatkirby |
17 | on | 17 | on |
18 | = blog.published_at.strftime("%m-%d-%Y") | 18 | = blog.published_at.strftime("%B #{blog.published_at.day.ordinalize}, %Y at %-I:%M:%S%P") |
diff --git a/app/views/blogs/show.html.haml b/app/views/blogs/show.html.haml index 9bff12b..0c549ac 100644 --- a/app/views/blogs/show.html.haml +++ b/app/views/blogs/show.html.haml | |||
@@ -1,7 +1,4 @@ | |||
1 | - title @blog.title | 1 | - title @blog.title |
2 | .breadcrumb= link_to "← Back to home page", root_path | 2 | .breadcrumb= link_to "← Back to home page", root_path |
3 | = render @blog, short: false | 3 | = render @blog, short: false |
4 | %footer#blog-footer | 4 | = show_comments(@blog) |
5 | This entry was posted on | ||
6 | = succeed "." do | ||
7 | %time= @blog.published_at.strftime("%B #{@blog.published_at.day.ordinalize}, %Y at %-I:%M:%S%P") | ||
diff --git a/app/views/comments/_comment.html.haml b/app/views/comments/_comment.html.haml new file mode 100644 index 0000000..3e10759 --- /dev/null +++ b/app/views/comments/_comment.html.haml | |||
@@ -0,0 +1,13 @@ | |||
1 | .blog-comment | ||
2 | %blockquote.bubble.rounded.bottom | ||
3 | = image_tag comment.gravatar_url, class: "comment-avatar" | ||
4 | = markdown(comment.body, { restricted: true }) | ||
5 | .clear | ||
6 | %cite.bubble | ||
7 | %strong | ||
8 | - if comment.website.empty? | ||
9 | = comment.username | ||
10 | - else | ||
11 | = link_to comment.username, comment.website | ||
12 | on | ||
13 | = comment.published_at.strftime("%B #{comment.published_at.day.ordinalize}, %Y at %-I:%M:%S%P") | ||
diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml new file mode 100644 index 0000000..f6df807 --- /dev/null +++ b/app/views/comments/_form.html.haml | |||
@@ -0,0 +1,23 @@ | |||
1 | = form_for @comment || blog.comments.new, html: { id: "comment-form" } do |f| | ||
2 | %fieldset#comment-body-field | ||
3 | %blockquote.bubble.rounded.bottom | ||
4 | = f.label :body | ||
5 | = f.text_area :body | ||
6 | %cite.bubble Feel free to post a comment! You may use Markdown. | ||
7 | - if @comment and @comment.errors.any? | ||
8 | %ul#form-errors | ||
9 | - @comment.errors.full_messages.each do |msg| | ||
10 | %li= msg | ||
11 | %fieldset#comment-other-fields | ||
12 | .comment-name-field.comment-field | ||
13 | .comment-field-label= f.label :username | ||
14 | .comment-field-input= f.text_field :username | ||
15 | .comment-email-field.comment-field | ||
16 | .comment-field-label= f.label :email | ||
17 | .comment-field-input= f.text_field :email, type: :email | ||
18 | .comment-website-field.comment-field | ||
19 | .comment-field-label= f.label :website, "Website (Optional)" | ||
20 | .comment-field-input= f.text_field :website, type: :url | ||
21 | .comment-submit-button.comment-field | ||
22 | .comment-field-label | ||
23 | .comment-field-input= f.submit "Post" | ||
diff --git a/app/views/comments/_layout.html.haml b/app/views/comments/_layout.html.haml new file mode 100644 index 0000000..9acf6b0 --- /dev/null +++ b/app/views/comments/_layout.html.haml | |||
@@ -0,0 +1,6 @@ | |||
1 | %a{ name: "comments" } | ||
2 | #comments | ||
3 | %h2 Comments | ||
4 | - blog.comments.published_and_ordered.each do |comment| | ||
5 | = render comment | ||
6 | = render "comments/form", blog: blog | ||