From 1c1fba63e7391b377a464a156680690bff0b39f2 Mon Sep 17 00:00:00 2001 From: Raphael Sofaer <raphael@joindiaspora.com> Date: Tue, 1 Mar 2011 10:20:23 -0800 Subject: [PATCH] Refactor notification to have subclasses, just a start --- app/helpers/notifications_helper.rb | 12 +++++------ app/models/comment.rb | 4 ++-- app/models/mention.rb | 2 +- app/models/notification.rb | 21 ++++++++++--------- app/models/request.rb | 4 ++-- .../20110228180709_notification_subclasses.rb | 9 ++++---- db/schema.rb | 2 +- spec/factories.rb | 2 +- spec/models/comment_spec.rb | 4 ++-- spec/models/mention_spec.rb | 6 +++--- spec/models/notification_spec.rb | 10 ++++----- spec/models/request_spec.rb | 4 ++-- spec/models/user/connecting_spec.rb | 4 ++-- spec/support/no_id_on_object.rb | 5 +++++ 14 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 spec/support/no_id_on_object.rb diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index c48b32af48..b98db63beb 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -1,26 +1,26 @@ module NotificationsHelper def object_link(note) - target_type = note.action + target_type = note.class case target_type - when 'mentioned' + when Notifications::Mentioned post = Mention.find(note.target_id).post if post "#{translation(target_type)} #{link_to t('notifications.post'), object_path(post)}".html_safe else "#{translation(target_type)} #{t('notifications.deleted')} #{t('notifications.post')}" end - when 'request_accepted' + when Notifications::RequestAccepted translation(target_type) - when 'new_request' + when Notifications::NewRequest translation(target_type) - when 'comment_on_post' + when Notifications::CommentOnPost post = Post.where(:id => note.target_id).first if post "#{translation(target_type)} #{link_to t('notifications.post'), object_path(post)}".html_safe else "#{translation(target_type)} #{t('notifications.deleted')} #{t('notifications.post')}" end - when 'also_commented' + when Notifications::AlsoCommented post = Post.where(:id => note.target_id).first if post "#{translation(target_type, post.person.name)} #{link_to t('notifications.post'), object_path(post)}".html_safe diff --git a/app/models/comment.rb b/app/models/comment.rb index 275acffba2..3348906323 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -44,9 +44,9 @@ class Comment < ActiveRecord::Base def notification_type(user, person) if self.post.person == user.person - return "comment_on_post" + return Notifications::CommentOnPost elsif self.post.comments.where(:person_id => user.person.id) != [] && self.person_id != user.person.id - return "also_commented" + return Notifications::AlsoCommented else return false end diff --git a/app/models/mention.rb b/app/models/mention.rb index 22dae4a026..86759d08b0 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -19,7 +19,7 @@ class Mention < ActiveRecord::Base def notification_type(*args) - 'mentioned' + Notifications::Mentioned end def delete_notification diff --git a/app/models/notification.rb b/app/models/notification.rb index 14bc6bb7ab..6af9d9b4bc 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -17,11 +17,11 @@ class Notification < ActiveRecord::Base def self.notify(recipient, target, actor) if target.respond_to? :notification_type - if action = target.notification_type(recipient, actor) + if note_type = target.notification_type(recipient, actor) if target.is_a? Comment - n = concatenate_or_create(recipient, target.post, actor, action) + n = concatenate_or_create(recipient, target.post, actor, note_type) else - n = make_notification(recipient, target, actor, action) + n = make_notification(recipient, target, actor, note_type) end n.email_the_user(target, actor) if n n.socket_to_user(recipient, :actor => actor) if n @@ -33,12 +33,14 @@ class Notification < ActiveRecord::Base def email_the_user(target, actor) self.recipient.mail(self.mail_job, self.recipient_id, actor.id, target.id) end + def mail_job + raise NotImplementedError.new('Subclass this.') + end private - def self.concatenate_or_create(recipient, target, actor, action) - if n = Notification.where(:target_id => target.id, + def self.concatenate_or_create(recipient, target, actor, notification_type) + if n = notification_type.where(:target_id => target.id, :target_type => target.class.base_class, - :action => action, :recipient_id => recipient.id).first unless n.actors.include?(actor) n.actors << actor @@ -48,13 +50,12 @@ private n.save! n else - make_notification(recipient, target, actor, action) + make_notification(recipient, target, actor, notification_type) end end - def self.make_notification(recipient, target, actor, action) - n = Notification.new(:target => target, - :action => action, + def self.make_notification(recipient, target, actor, notification_type) + n = notification_type.new(:target => target, :recipient_id => recipient.id) n.actors << actor n.unread = false if target.is_a? Request diff --git a/app/models/request.rb b/app/models/request.rb index 6f8c58a855..90c17b8864 100644 --- a/app/models/request.rb +++ b/app/models/request.rb @@ -56,9 +56,9 @@ class Request < ActiveRecord::Base def notification_type(user, person) if Contact.where(:user_id => user.id, :person_id => person.id).first - "request_accepted" + Notifications::RequestAccepted else - "new_request" + Notifications::NewRequest end end diff --git a/db/migrate/20110228180709_notification_subclasses.rb b/db/migrate/20110228180709_notification_subclasses.rb index 96f2d04fcf..18d210ac1c 100644 --- a/db/migrate/20110228180709_notification_subclasses.rb +++ b/db/migrate/20110228180709_notification_subclasses.rb @@ -8,8 +8,8 @@ class NotificationSubclasses < ActiveRecord::Migration :mentioned => 'Notifications::Mentioned' }.each_pair do |key, value| execute("UPDATE notifications - set type = #{value} - where action = #{key.to_s}") + set type = '#{value}' + where action = '#{key.to_s}'") end remove_column :notifications, :action end @@ -23,8 +23,9 @@ class NotificationSubclasses < ActiveRecord::Migration :mentioned => 'Notifications::Mentioned' }.each_pair do |key, value| execute("UPDATE notifications - set action = #{key.to_s} - where type = #{value}") + set action = '#{key.to_s}' + where type = '#{value}'") + end remove_column :notifications, :type end end diff --git a/db/schema.rb b/db/schema.rb index f3c65a25f9..2dfe5390c1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -318,10 +318,10 @@ ActiveRecord::Schema.define(:version => 20110228201109) do t.string "target_type" t.integer "target_id" t.integer "recipient_id", :null => false - t.string "action", :null => false t.boolean "unread", :default => true, :null => false t.datetime "created_at" t.datetime "updated_at" + t.string "type" end add_index "notifications", ["recipient_id"], :name => "index_notifications_on_recipient_id" diff --git a/spec/factories.rb b/spec/factories.rb index 798077740e..1e784e7618 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -92,10 +92,10 @@ end Factory.define(:notification) do |n| n.association :recipient, :factory => :user n.association :target, :factory => :comment + n.type 'Notifications::AlsoCommented' n.after_build do |note| note.actors << Factory.build( :person ) - note.action = note.target.notification_type(note.recipient, note.actors.first) end end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 708574ae94..e80cfcf3d4 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -20,7 +20,7 @@ describe Comment do it "returns 'comment_on_post' if the comment is on a post you own" do comment = bob.comment("why so formal?", :on => @alices_post) - comment.notification_type(alice, bob.person).should == 'comment_on_post' + comment.notification_type(alice, bob.person).should == Notifications::CommentOnPost end it 'returns false if the comment is not on a post you own and no one "also_commented"' do @@ -39,7 +39,7 @@ describe Comment do end it "returns 'also_commented' if another person commented on a post you commented on" do - @comment.notification_type(bob, alice.person).should == 'also_commented' + @comment.notification_type(bob, alice.person).should == Notifications::AlsoCommented end end end diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb index e16f68eff7..8f08abcc47 100644 --- a/spec/models/mention_spec.rb +++ b/spec/models/mention_spec.rb @@ -21,7 +21,7 @@ describe Mention do @m.save end - it 'should only notify if the person is local' do + it 'should only notify if the person is local' do m = Mention.new(:person => Factory(:person), :post => @sm) Notification.should_not_receive(:notify) m.save @@ -44,10 +44,10 @@ describe Mention do describe '#notification_type' do it "returns 'mentioned'" do - Mention.new.notification_type.should == 'mentioned' + Mention.new.notification_type.should == Notifications::Mentioned end end - + describe 'after destroy' do it 'destroys a notification' do @user = alice diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 56ed2269a2..21b3ceaf42 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -13,7 +13,7 @@ describe Notification do @aspect = @user.aspects.create(:name => "dudes") @opts = {:target_id => @sm.id, :target_type => @sm.class.name, - :action => "comment_on_post", + :type => 'Notifications::CommentOnPost', :actors => [@person], :recipient_id => @user.id} @note = Notification.new(@opts) @@ -61,11 +61,10 @@ describe Notification do it 'sockets to the recipient' do opts = {:target_id => @request.id, :target_type => "Request", - :action => @request.notification_type(@user, @person), :actors => [@person], :recipient_id => @user.id} - n = Notification.create(opts) + n = @request.notification_type(@user, @person).create(opts) Notification.stub!(:make_notification).and_return n n.should_receive(:socket_to_user).once @@ -75,15 +74,14 @@ describe Notification do describe '#emails_the_user' do it 'calls mail' do opts = { - :action => "new_request", :actors => [@person], :recipient_id => @user.id} - n = Notification.new(opts) + n = Notifications::NewRequest.new(opts) n.stub!(:recipient).and_return @user @user.should_receive(:mail) - n.email_the_user("mock", @person) + n.email_the_user(@request, @person) end end diff --git a/spec/models/request_spec.rb b/spec/models/request_spec.rb index ffa1ce6f35..fd6fb20746 100644 --- a/spec/models/request_spec.rb +++ b/spec/models/request_spec.rb @@ -56,11 +56,11 @@ describe Request do end it "returns 'request_accepted' if there is a pending contact" do Contact.create(:user_id => @user.id, :person_id => @person.id) - @request.notification_type(@user, @person).should == "request_accepted" + @request.notification_type(@user, @person).should == Notifications::RequestAccepted end it 'returns new_request if there is not a pending contact' do - @request.notification_type(@user, @person).should == "new_request" + @request.notification_type(@user, @person).should == Notifications::NewRequest end end diff --git a/spec/models/user/connecting_spec.rb b/spec/models/user/connecting_spec.rb index 0d650766bb..8cc5d3c908 100644 --- a/spec/models/user/connecting_spec.rb +++ b/spec/models/user/connecting_spec.rb @@ -67,7 +67,7 @@ describe Diaspora::UserModules::Connecting do end it 'enqueues a mail job' do - Resque.should_receive(:enqueue).with(Job::MailRequestReceived, user.id, person.id) + Resque.should_receive(:enqueue).with(Job::MailRequestReceived, user.id, person.id, anything) zord = Postzord::Receiver.new(user, :object => @r, :person => person) zord.receive_object end @@ -87,7 +87,7 @@ describe Diaspora::UserModules::Connecting do Request.where(:sender_id => user2.person.id, :recipient_id => user.person.id).should be_empty end it 'enqueues a mail job' do - Resque.should_receive(:enqueue).with(Job::MailRequestAcceptance, user.id, user2.person.id).once + Resque.should_receive(:enqueue).with(Job::MailRequestAcceptance, user.id, user2.person.id, nil).once zord = Postzord::Receiver.new(user, :object => @acceptance, :person => user2.person) zord.receive_object end diff --git a/spec/support/no_id_on_object.rb b/spec/support/no_id_on_object.rb new file mode 100644 index 0000000000..16f8621a79 --- /dev/null +++ b/spec/support/no_id_on_object.rb @@ -0,0 +1,5 @@ +class Object + def id + raise "You have called id on a non-ActiveRecord object." + end +end -- GitLab