Commit a68225423123e7dc8ee6ed1ea8277dff75319fd0
Committed by
Antonio Terceiro
1 parent
d3ed5d29
Exists in
staging
and in
42 other branches
ActionItem870: notify article owner about new comments by e-mail
Showing
8 changed files
with
136 additions
and
7 deletions
Show diff stats
app/helpers/article_helper.rb
| ... | ... | @@ -7,8 +7,10 @@ module ArticleHelper |
| 7 | 7 | check_box(:article, :published) + |
| 8 | 8 | content_tag('label', _('Published'), :for => 'article_published') + |
| 9 | 9 | check_box(:article, :accept_comments) + |
| 10 | - content_tag('label', _('Accept Comments'), :for => 'article_accept_comments') | |
| 11 | - ) | |
| 10 | + content_tag('label', _('Accept Comments'), :for => 'article_accept_comments') + | |
| 11 | + check_box(:article, :notify_comments) + | |
| 12 | + content_tag('label', _('Notify Comments'), :for => 'article_notify_comments') | |
| 13 | + ) + observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked") | |
| 12 | 14 | end |
| 13 | 15 | |
| 14 | 16 | def cms_label_for_new_children | ... | ... |
app/models/comment.rb
| ... | ... | @@ -45,4 +45,26 @@ class Comment < ActiveRecord::Base |
| 45 | 45 | article.comments_updated |
| 46 | 46 | end |
| 47 | 47 | |
| 48 | + after_create do |comment| | |
| 49 | + if comment.article.notify_comments? | |
| 50 | + Comment::Notifier.deliver_mail(comment) | |
| 51 | + end | |
| 52 | + end | |
| 53 | + | |
| 54 | + class Notifier < ActionMailer::Base | |
| 55 | + def mail(comment) | |
| 56 | + profile = comment.article.profile | |
| 57 | + recipients profile.email | |
| 58 | + from "#{profile.environment.name} <#{profile.environment.contact_email}>" | |
| 59 | + subject _("%s - New comment in '%s'") % [profile.environment.name, comment.article.title] | |
| 60 | + body :name => (comment.author.nil? ? comment.name : comment.author.name), | |
| 61 | + :email => (comment.author.nil? ? comment.email : comment.author.email), | |
| 62 | + :title => comment.title, | |
| 63 | + :body => comment.body, | |
| 64 | + :article_url => comment.article.url, | |
| 65 | + :environment => profile.environment.name, | |
| 66 | + :url => url_for(:host => profile.environment.default_hostname, :controller => 'home') | |
| 67 | + end | |
| 68 | + end | |
| 69 | + | |
| 48 | 70 | end | ... | ... |
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | +class AddNotifyCommentsToArticles < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + add_column :articles, :notify_comments, :boolean, :default => false | |
| 4 | + add_column :article_versions, :notify_comments, :boolean, :default => false | |
| 5 | + end | |
| 6 | + | |
| 7 | + def self.down | |
| 8 | + remove_column :articles, :notify_comments | |
| 9 | + remove_column :article_versions, :notify_comments | |
| 10 | + end | |
| 11 | +end | ... | ... |
db/schema.rb
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # |
| 10 | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | |
| 12 | -ActiveRecord::Schema.define(:version => 56) do | |
| 12 | +ActiveRecord::Schema.define(:version => 57) do | |
| 13 | 13 | |
| 14 | 14 | create_table "article_versions", :force => true do |t| |
| 15 | 15 | t.integer "article_id" |
| ... | ... | @@ -40,6 +40,7 @@ ActiveRecord::Schema.define(:version => 56) do |
| 40 | 40 | t.boolean "accept_comments", :default => true |
| 41 | 41 | t.integer "reference_article_id" |
| 42 | 42 | t.text "setting" |
| 43 | + t.boolean "notify_comments", :default => false | |
| 43 | 44 | end |
| 44 | 45 | |
| 45 | 46 | create_table "articles", :force => true do |t| |
| ... | ... | @@ -71,6 +72,7 @@ ActiveRecord::Schema.define(:version => 56) do |
| 71 | 72 | t.boolean "accept_comments", :default => true |
| 72 | 73 | t.integer "reference_article_id" |
| 73 | 74 | t.text "setting" |
| 75 | + t.boolean "notify_comments", :default => false | |
| 74 | 76 | end |
| 75 | 77 | |
| 76 | 78 | create_table "articles_categories", :id => false, :force => true do |t| |
| ... | ... | @@ -79,8 +81,8 @@ ActiveRecord::Schema.define(:version => 56) do |
| 79 | 81 | t.boolean "virtual", :default => false |
| 80 | 82 | end |
| 81 | 83 | |
| 82 | - add_index "articles_categories", ["article_id"], :name => "index_articles_categories_on_article_id" | |
| 83 | 84 | add_index "articles_categories", ["category_id"], :name => "index_articles_categories_on_category_id" |
| 85 | + add_index "articles_categories", ["article_id"], :name => "index_articles_categories_on_article_id" | |
| 84 | 86 | |
| 85 | 87 | create_table "blocks", :force => true do |t| |
| 86 | 88 | t.string "title" |
| ... | ... | @@ -120,8 +122,8 @@ ActiveRecord::Schema.define(:version => 56) do |
| 120 | 122 | t.boolean "virtual", :default => false |
| 121 | 123 | end |
| 122 | 124 | |
| 123 | - add_index "categories_profiles", ["profile_id"], :name => "index_categories_profiles_on_profile_id" | |
| 124 | 125 | add_index "categories_profiles", ["category_id"], :name => "index_categories_profiles_on_category_id" |
| 126 | + add_index "categories_profiles", ["profile_id"], :name => "index_categories_profiles_on_profile_id" | |
| 125 | 127 | |
| 126 | 128 | create_table "comments", :force => true do |t| |
| 127 | 129 | t.string "title" |
| ... | ... | @@ -188,8 +190,8 @@ ActiveRecord::Schema.define(:version => 56) do |
| 188 | 190 | t.datetime "updated_at" |
| 189 | 191 | end |
| 190 | 192 | |
| 191 | - add_index "product_categorizations", ["product_id"], :name => "index_product_categorizations_on_product_id" | |
| 192 | 193 | add_index "product_categorizations", ["category_id"], :name => "index_product_categorizations_on_category_id" |
| 194 | + add_index "product_categorizations", ["product_id"], :name => "index_product_categorizations_on_product_id" | |
| 193 | 195 | |
| 194 | 196 | create_table "products", :force => true do |t| |
| 195 | 197 | t.integer "enterprise_id" |
| ... | ... | @@ -260,8 +262,8 @@ ActiveRecord::Schema.define(:version => 56) do |
| 260 | 262 | t.datetime "created_at" |
| 261 | 263 | end |
| 262 | 264 | |
| 263 | - add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" | |
| 264 | 265 | add_index "taggings", ["taggable_id", "taggable_type"], :name => "index_taggings_on_taggable_id_and_taggable_type" |
| 266 | + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" | |
| 265 | 267 | |
| 266 | 268 | create_table "tags", :force => true do |t| |
| 267 | 269 | t.string "name" | ... | ... |
test/functional/cms_controller_test.rb
| ... | ... | @@ -746,4 +746,10 @@ class CmsControllerTest < Test::Unit::TestCase |
| 746 | 746 | assert_tag :tag => 'input', :attributes => {:type => 'submit', :value => 'Yes, I want.' } |
| 747 | 747 | end |
| 748 | 748 | |
| 749 | + should 'display notify comments option' do | |
| 750 | + a = profile.articles.create!(:name => 'test') | |
| 751 | + get :edit, :profile => profile.identifier, :id => a.id | |
| 752 | + assert :tag => 'input', :attributes => {:name => 'article[notify_comments]', :value => 1} | |
| 753 | + end | |
| 754 | + | |
| 749 | 755 | end | ... | ... |
test/unit/article_test.rb
| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class CommentNotifierTest < Test::Unit::TestCase | |
| 4 | + FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures' | |
| 5 | + CHARSET = "utf-8" | |
| 6 | + | |
| 7 | + def setup | |
| 8 | + ActionMailer::Base.delivery_method = :test | |
| 9 | + ActionMailer::Base.perform_deliveries = true | |
| 10 | + ActionMailer::Base.deliveries = [] | |
| 11 | + | |
| 12 | + @expected = TMail::Mail.new | |
| 13 | + @expected.set_content_type "text", "plain", { "charset" => CHARSET } | |
| 14 | + end | |
| 15 | + | |
| 16 | + should 'deliver mail after make aarticle commment' do | |
| 17 | + p = create_user('user_comment_test').person | |
| 18 | + a = Article.create!(:name => 'Article test', :profile => p, :notify_comments => true) | |
| 19 | + assert_difference ActionMailer::Base.deliveries, :count do | |
| 20 | + a.comments << Comment.new(:author => p, :title => 'test comment', :body => 'you suck!') | |
| 21 | + end | |
| 22 | + end | |
| 23 | + | |
| 24 | + should 'deliver mail to owner of article' do | |
| 25 | + p = create_user('user_comment_test').person | |
| 26 | + a = Article.create!(:name => 'Article test', :profile => p, :notify_comments => true) | |
| 27 | + a.comments << Comment.new(:author => p, :title => 'test comment', :body => 'you suck!') | |
| 28 | + sent = ActionMailer::Base.deliveries.first | |
| 29 | + assert_equal [p.email], sent.to | |
| 30 | + end | |
| 31 | + | |
| 32 | + should 'display author name in delivered mail' do | |
| 33 | + p = create_user('user_comment_test').person | |
| 34 | + a = Article.create!(:name => 'Article test', :profile => p, :notify_comments => true) | |
| 35 | + a.comments << Comment.new(:author => p, :title => 'test comment', :body => 'you suck!') | |
| 36 | + sent = ActionMailer::Base.deliveries.first | |
| 37 | + assert_match /user_comment_test/, sent.body | |
| 38 | + end | |
| 39 | + | |
| 40 | + should 'display unauthenticated author name and email in delivered mail' do | |
| 41 | + p = create_user('user_comment_test').person | |
| 42 | + a = Article.create!(:name => 'Article test', :profile => p, :notify_comments => true) | |
| 43 | + a.comments << Comment.new(:name => 'flatline', :email => 'flatline@invalid.com', :title => 'test comment', :body => 'you suck!') | |
| 44 | + sent = ActionMailer::Base.deliveries.first | |
| 45 | + assert_match /flatline/, sent.body | |
| 46 | + assert_match /flatline@invalid.com/, sent.body | |
| 47 | + end | |
| 48 | + | |
| 49 | + should 'not deliver mail if notify comments is false' do | |
| 50 | + p = create_user('user_comment_test').person | |
| 51 | + a = Article.create!(:name => 'Article test', :profile => p, :notify_comments => false) | |
| 52 | + assert_no_difference ActionMailer::Base.deliveries, :count do | |
| 53 | + a.comments << Comment.new(:author => p, :title => 'test comment', :body => 'you suck!') | |
| 54 | + end | |
| 55 | + end | |
| 56 | + | |
| 57 | + private | |
| 58 | + | |
| 59 | + def read_fixture(action) | |
| 60 | + IO.readlines("#{FIXTURES_PATH}/mail_sender/#{action}") | |
| 61 | + end | |
| 62 | + | |
| 63 | + def encode(subject) | |
| 64 | + quoted_printable(subject, CHARSET) | |
| 65 | + end | |
| 66 | + | |
| 67 | +end | ... | ... |