Commit e3ee6d371937c883478bcdc5e3ebb60f41335222

Authored by Leandro Santos
Committed by Antonio Terceiro
1 parent fb5e9d89

Implmenting some improvement on profile activity:

  * The users member of a community shoudl be notified with the information of where that noficication is.
  * The friendship relationship should be notified to the both users
  * If the article is created automaticaly according its template this article should not be notified
  * The article approval should not notify the article with the user who aproved it as the user that made the article

(ActionItem1303)
app/models/article.rb
... ... @@ -2,10 +2,9 @@ require 'hpricot'
2 2  
3 3 class Article < ActiveRecord::Base
4 4  
5   - track_actions :create_article, :after_create, :keep_params => [:name, :url], :if => Proc.new { |a| a.published? && !a.profile.is_a?(Community) && !a.image? && a.notifiable? }
6   - track_actions :update_article, :before_update, :keep_params => [:name, :url], :if => Proc.new { |a| a.published? && (a.body_changed? || a.name_changed?) && a.notifiable? }
7   - track_actions :remove_article, :before_destroy, :keep_params => [:name], :if => Proc.new { |a| a.published? && a.notifiable? }
8   - track_actions :publish_article_in_community, :after_create, :keep_params => ["name", "url", "profile.url", "profile.name"], :if => Proc.new { |a| a.published? && a.profile.is_a?(Community) && !a.image? && a.notifiable? }
  5 + track_actions :create_article, :after_create, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && !a.image? }, :custom_target => :action_tracker_target
  6 + track_actions :update_article, :before_update, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && (a.body_changed? || a.name_changed?) }, :custom_target => :action_tracker_target
  7 + track_actions :remove_article, :before_destroy, :keep_params => [:name], :if => Proc.new { |a| a.is_trackable? }, :custom_target => :action_tracker_target
9 8  
10 9 # xss_terminate plugin can't sanitize array fields
11 10 before_save :sanitize_tag_list
... ... @@ -43,6 +42,10 @@ class Article &lt; ActiveRecord::Base
43 42  
44 43 validates_format_of :external_link, :with => URL_FORMAT, :if => lambda { |article| !article.external_link.blank? }
45 44  
  45 + def is_trackable?
  46 + self.published? && self.notifiable? && self.advertise?
  47 + end
  48 +
46 49 def external_link=(link)
47 50 if !link.blank? && link !~ /^[a-z]+:\/\//i
48 51 link = 'http://' + link
... ... @@ -50,6 +53,9 @@ class Article &lt; ActiveRecord::Base
50 53 self[:external_link] = link
51 54 end
52 55  
  56 + def action_tracker_target
  57 + self.profile
  58 + end
53 59  
54 60 def self.human_attribute_name(attrib)
55 61 case attrib.to_sym
... ...
app/models/comment.rb
1 1 class Comment < ActiveRecord::Base
2 2  
3   - track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"]
  3 + track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"], :custom_target => :action_tracker_target
4 4  
5 5 validates_presence_of :title, :body
6 6 belongs_to :article, :counter_cache => true
... ... @@ -21,6 +21,10 @@ class Comment &lt; ActiveRecord::Base
21 21  
22 22 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
23 23  
  24 + def action_tracker_target
  25 + self.article.profile
  26 + end
  27 +
24 28 def author_name
25 29 if author
26 30 author.short_name
... ...
app/models/friendship.rb
1 1 class Friendship < ActiveRecord::Base
2   - track_actions :new_friendship, :after_create, :keep_params => ["friend.name", "friend.url", "friend.profile_custom_icon"], :unless => Proc.new { |f| f.friend.is_a_friend?(f.person) }
  2 + track_actions :new_friendship, :after_create, :keep_params => ["friend.name", "friend.url", "friend.profile_custom_icon"], :custom_user => :person
3 3  
4 4 belongs_to :person, :foreign_key => :person_id
5 5 belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id'
... ...
app/models/person.rb
... ... @@ -327,12 +327,7 @@ class Person &lt; Profile
327 327 end
328 328  
329 329 def self.notify_activity(tracked_action)
330   - profile = tracked_action.dispatcher.profile if tracked_action.dispatcher.is_a?(Article)
331   - profile = tracked_action.dispatcher.resource if tracked_action.dispatcher.is_a?(RoleAssignment)
332   - profile = tracked_action.dispatcher.article.profile if tracked_action.dispatcher.is_a?(Comment)
333   - profile_id = profile.nil? ? nil : profile.id
334   - Delayed::Job.enqueue NotifyActivityToProfilesJob.new(tracked_action.id, profile_id)
335   - ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => tracked_action.user)
  330 + Delayed::Job.enqueue NotifyActivityToProfilesJob.new(tracked_action.id)
336 331 end
337 332  
338 333 def is_member_of?(profile)
... ...
app/models/published_article.rb
... ... @@ -37,4 +37,8 @@ class PublishedArticle &lt; Article
37 37 reference_article && reference_article.abstract
38 38 end
39 39  
  40 + def notifiable?
  41 + true
  42 + end
  43 +
40 44 end
... ...
app/views/profile/_profile_network_activities.rhtml
... ... @@ -9,6 +9,7 @@
9 9 <div class='profile-network-description'>
10 10 <p class='profile-network-time'><%= time_ago_as_sentence(activity.created_at) + ' ' + _('ago') %></p>
11 11 <p class='profile-network-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
  12 + <p class='profile-network-where'><%= _('In community %s') % link_to(activity.target.name, activity.target.url) if !profile.is_a?(Community) && activity.target.is_a?(Community) %></p>
12 13 </div>
13 14 <div id='profile-network-message-<%= activity.id%>' style='display:none;'>
14 15 <div id='profile-network-form-<%= activity.id%>' style='display:none;'>
... ...
config/initializers/action_tracker.rb
... ... @@ -19,11 +19,6 @@ ActionTrackerConfig.verbs = {
19 19 :type => :groupable
20 20 },
21 21  
22   - :publish_article_in_community => {
23   - :description => lambda { n_('published 1 article in communities: %{title}', 'published %{num} articles in communities: %{title}', get_name.size) % { :num => get_name.size, :title => '{{ta.collect_group_with_index(:name){ |n,i| link_to(truncate(n), ta.get_url[i]) + " (%s " + link_to(ta.get_profile_name[i], ta.get_profile_url[i]) + ")" }.to_sentence(:connector => "%s")}}' % [_("in"), _("and")] } },
24   - :type => :groupable
25   - },
26   -
27 22 :new_friendship => {
28 23 :description => lambda { n_('has made 1 new friend:<br />%{name}', 'has made %{num} new friends:<br />%{name}', get_friend_name.size) % { :num => get_friend_name.size, :name => '{{ta.collect_group_with_index(:friend_name){ |n,i| link_to(content_tag(:img, nil, :src => (ta.get_friend_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png"))), ta.get_friend_url[i], :title => n)}.join}}' } },
29 24 :type => :groupable
... ... @@ -34,6 +29,14 @@ ActionTrackerConfig.verbs = {
34 29 :type => :groupable
35 30 },
36 31  
  32 + :add_member_in_community => {
  33 + :description => lambda { _('has joined the community.') },
  34 + },
  35 +
  36 + :remove_member_in_community => {
  37 + :description => lambda { _('has left the community.') },
  38 + },
  39 +
37 40 :leave_community => {
38 41 :description => lambda { n_('has left 1 community:<br />%{name}', 'has left %{num} communities:<br />%{name}', get_resource_name.size) % { :num => get_resource_name.size, :name => '{{ta.collect_group_with_index(:resource_name){ |n,i| link_to(content_tag(:img, nil, :src => (ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png"))), ta.get_resource_url[i], :title => n)}.join}}' } },
39 42 :type => :groupable
... ...
db/migrate/20100920182433_change_action_tracker_record.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +class ChangeActionTrackerRecord < ActiveRecord::Migration
  2 + def self.up
  3 + rename_column(:action_tracker, :dispatcher_type, :target_type)
  4 + rename_column(:action_tracker, :dispatcher_id, :target_id)
  5 + ActionTracker::Record.update_all("verb='create_article'", {:verb => 'publish_article_in_community'})
  6 + end
  7 +
  8 + def self.down
  9 + raise "this migration can't be reverted"
  10 + rename_column(:action_tracker, :target_type, :dispatcher_type)
  11 + rename_column(:action_tracker, :target_id, :dispatcher_id)
  12 + end
  13 +end
... ...
lib/notify_activity_to_profiles_job.rb
1   -class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id, :target_profile_id)
  1 +class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id)
  2 + NOTIFY_ONLY_COMMUNITY = [
  3 + 'add_member_in_community',
  4 + 'remove_member_in_community',
  5 + ]
  6 +
  7 + NOT_NOTIFY_COMMUNITY = [
  8 + 'join_community',
  9 + 'leave_community',
  10 + ]
2 11 def perform
3   - profile = Profile.find(target_profile_id) unless target_profile_id.nil?
4 12 tracked_action = ActionTracker::Record.find(tracked_action_id)
  13 + target = tracked_action.target
  14 + if target.is_a?(Community) && NOTIFY_ONLY_COMMUNITY.include?(tracked_action.verb)
  15 + ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => target)
  16 + return
  17 + end
  18 +
  19 + ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => tracked_action.user)
5 20 tracked_action.user.each_friend do |friend|
6 21 ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => friend)
7 22 end
8   - if profile.is_a?(Community)
9   - profile.each_member do |member|
  23 +
  24 + if target.is_a?(Community)
  25 + target.each_member do |member|
10 26 next if member == tracked_action.user
11 27 ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => member)
12 28 end
13   - ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => profile)
  29 + ActionTrackerNotification.create(:action_tracker => tracked_action, :profile => target) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb)
14 30 end
15 31 end
16 32 end
... ...
test/factories.rb
... ... @@ -224,7 +224,7 @@ module Noosfero::Factory
224 224 alias :defaults_for_textile_article :defaults_for_article
225 225 alias :defaults_for_tiny_mce_article :defaults_for_article
226 226 alias :defaults_for_rss_feed :defaults_for_article
227   - alias :defaults_for_textile_article :defaults_for_article
  227 + alias :defaults_for_published_article :defaults_for_article
228 228 alias :defaults_for_folder :defaults_for_article
229 229  
230 230 ###############################################
... ... @@ -381,7 +381,7 @@ module Noosfero::Factory
381 381 ###############################################
382 382  
383 383 def defaults_for_action_tracker_record(params = {})
384   - { :created_at => DateTime.now, :verb => :leave_comment, :user_type => 'Profile', :user_id => 1 }.merge(params)
  384 + { :created_at => DateTime.now, :verb => 'add_member_in_community', :user_type => 'Profile', :user_id => 1 }.merge(params)
385 385 end
386 386  
387 387 ###############################################
... ...
test/functional/profile_controller_test.rb
... ... @@ -769,7 +769,8 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
769 769  
770 770 should 'the network activity be paginated' do
771 771 p1= Person.first
772   - 40.times{Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))}
  772 + at = fast_create(ActionTracker::Record)
  773 + 40.times{fast_create(ActionTrackerNotification, :action_tracker_id => at.id, :profile_id => p1.id)}
773 774  
774 775 @controller.stubs(:logged_in?).returns(true)
775 776 user = mock()
... ...
test/unit/article_test.rb
... ... @@ -1020,4 +1020,40 @@ class ArticleTest &lt; Test::Unit::TestCase
1020 1020 assert_equal 0, ActionTracker::Record.count
1021 1021 end
1022 1022  
  1023 + should "the action_tracker_target method be defined" do
  1024 + assert Article.method_defined?(:action_tracker_target)
  1025 + end
  1026 +
  1027 + should "the action_tracker_target method return the article profile" do
  1028 + profile = fast_create(Person)
  1029 + article = fast_create(Article, :profile_id => profile.id)
  1030 + assert_equal profile, article.action_tracker_target
  1031 +
  1032 + profile = fast_create(Community)
  1033 + article = fast_create(Article, :profile_id => profile.id)
  1034 + assert_equal profile, article.action_tracker_target
  1035 + end
  1036 +
  1037 + should "have defined the is_trackable method defined" do
  1038 + assert Article.method_defined?(:is_trackable?)
  1039 + end
  1040 +
  1041 + should "the common trackable conditions return the correct value" do
  1042 + a = Article.new
  1043 + a.published = a.advertise = true
  1044 + assert_equal true, a.published?
  1045 + assert_equal false, a.notifiable?
  1046 + assert_equal true, a.advertise?
  1047 + assert_equal false, a.is_trackable?
  1048 +
  1049 + a.published=false
  1050 + assert_equal false, a.published?
  1051 + assert_equal false, a.is_trackable?
  1052 +
  1053 + a.published=true
  1054 + a.advertise=false
  1055 + assert_equal false, a.advertise?
  1056 + assert_equal false, a.is_trackable?
  1057 + end
  1058 +
1023 1059 end
... ...
test/unit/comment_test.rb
... ... @@ -226,4 +226,16 @@ class CommentTest &lt; Test::Unit::TestCase
226 226 assert_equal comment.url, ta.get_url
227 227 end
228 228  
  229 + should 'have the action_tracker_target defined' do
  230 + assert Comment.method_defined?(:action_tracker_target)
  231 + end
  232 +
  233 + should "have the action_tracker_target be the articles's profile" do
  234 + owner = create_user('testuser').person
  235 + article = owner.articles.create!(:name => 'test', :body => '...')
  236 + comment = article.comments.create!(:article => article, :name => 'foo', :title => 'bar', :body => 'my comment', :email => 'cracker@test.org')
  237 + ta = ActionTracker::Record.last
  238 + assert_equal owner, ta.target
  239 + end
  240 +
229 241 end
... ...
test/unit/community_test.rb
... ... @@ -242,9 +242,9 @@ class CommunityTest &lt; Test::Unit::TestCase
242 242  
243 243 RoleAssignment.delete_all
244 244 ActionTrackerNotification.delete_all
245   - RoleAssignment.any_instance.stubs(:role_id).returns(3)
246   - assert_difference(ActionTrackerNotification, :count, 3) do
  245 + assert_difference(ActionTrackerNotification, :count, 5) do
247 246 community.add_member(p1)
  247 + process_delayed_job_queue
248 248 community.add_member(p3)
249 249 assert p1.is_member_of?(community)
250 250 assert !p2.is_member_of?(community)
... ...
test/unit/friendship_test.rb
... ... @@ -23,23 +23,27 @@ class FriendshipTest &lt; Test::Unit::TestCase
23 23 end
24 24  
25 25 should 'create tracked action' do
26   - f = Friendship.create! :person => create_user('a').person, :friend => create_user('b').person
  26 + a, b, c = create_user('a').person, create_user('b').person, create_user('c').person
  27 + f = Friendship.create! :person => a, :friend => b
27 28 ta = ActionTracker::Record.last
28   - person = Person.first
29   - assert_equal person.name, ta.user.name
  29 + assert_equal a, ta.user
30 30 assert_equal 'b', ta.get_friend_name[0]
31   - f = Friendship.create! :person => create_user('a').person, :friend => create_user('c').person
  31 + f = Friendship.create! :person => a, :friend => c
32 32 ta = ActionTracker::Record.last
33   - assert_equal person.name, ta.user.name
  33 + assert_equal a, ta.user
34 34 assert_equal 'c', ta.get_friend_name[1]
35 35 end
36 36  
37   - should 'create tracked action only if they are not friends yet' do
  37 + should 'create tracked action for both people' do
38 38 a, b = create_user('a').person, create_user('b').person
39 39 f = Friendship.create! :person => a, :friend => b
40   - assert_equal ['b'], ActionTracker::Record.last.get_friend_name
  40 + ta = ActionTracker::Record.last
  41 + assert_equal a, ta.user
  42 + assert_equal ['b'], ta.get_friend_name
41 43 f = Friendship.create! :person => b, :friend => a
42   - assert_equal ['b'], ActionTracker::Record.last.get_friend_name
  44 + ta = ActionTracker::Record.last
  45 + assert_equal b, ta.user
  46 + assert_equal ['a'], ta.get_friend_name
43 47 end
44 48  
45 49 end
... ...
test/unit/notify_activity_to_profiles_job_test.rb
... ... @@ -2,24 +2,168 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
2 2  
3 3 class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase
4 4  
5   - should 'create the ActionTrackerNotification' do
  5 + should 'notify just the community in tracker with add_member_in_community verb' do
6 6 person = fast_create(Person)
7 7 community = fast_create(Community)
8   - action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id)
  8 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'add_member_in_community')
  9 + assert NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
9 10 p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
10 11 fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
11 12 fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
12 13 fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
13 14 fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
14 15 ActionTrackerNotification.delete_all
15   - job = NotifyActivityToProfilesJob.new(action_tracker.id, community.id)
  16 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
16 17 job.perform
17 18 process_delayed_job_queue
18 19  
19   - [community, p1, p2, m1, m2].each do |profile|
  20 + assert_equal 1, ActionTrackerNotification.count
  21 + [community].each do |profile|
20 22 notification = ActionTrackerNotification.find_by_profile_id profile.id
21 23 assert_equal action_tracker, notification.action_tracker
22 24 end
23 25 end
24 26  
  27 + should 'notify just the community in tracker with remove_member_in_community verb' do
  28 + person = fast_create(Person)
  29 + community = fast_create(Community)
  30 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'remove_member_in_community')
  31 + assert NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
  32 + p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
  33 + fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
  34 + fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
  35 + fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
  36 + fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
  37 + ActionTrackerNotification.delete_all
  38 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
  39 + job.perform
  40 + process_delayed_job_queue
  41 +
  42 + assert_equal 1, ActionTrackerNotification.count
  43 + [community].each do |profile|
  44 + notification = ActionTrackerNotification.find_by_profile_id profile.id
  45 + assert_equal action_tracker, notification.action_tracker
  46 + end
  47 + end
  48 +
  49 + should 'notify just the users and his friends tracking user actions' do
  50 + person = fast_create(Person)
  51 + community = fast_create(Community)
  52 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :verb => 'create_article')
  53 + assert !NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
  54 + p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
  55 + fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
  56 + fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
  57 + fast_create(Friendship, :person_id => p1.id, :friend_id => m1.id)
  58 + fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
  59 + ActionTrackerNotification.delete_all
  60 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
  61 + job.perform
  62 + process_delayed_job_queue
  63 +
  64 + assert_equal 3, ActionTrackerNotification.count
  65 + [person, p1, p2].each do |profile|
  66 + notification = ActionTrackerNotification.find_by_profile_id profile.id
  67 + assert_equal action_tracker, notification.action_tracker
  68 + end
  69 + end
  70 +
  71 + should 'not notify the communities members' do
  72 + person = fast_create(Person)
  73 + community = fast_create(Community)
  74 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'create_article')
  75 + assert !NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
  76 + m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
  77 + fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
  78 + fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
  79 + ActionTrackerNotification.delete_all
  80 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
  81 + job.perform
  82 + process_delayed_job_queue
  83 +
  84 + assert_equal 4, ActionTrackerNotification.count
  85 + [person, community, m1, m2].each do |profile|
  86 + notification = ActionTrackerNotification.find_by_profile_id profile.id
  87 + assert_equal action_tracker, notification.action_tracker
  88 + end
  89 + end
  90 +
  91 + should 'notify users its friends, the community and its members' do
  92 + person = fast_create(Person)
  93 + community = fast_create(Community)
  94 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'create_article')
  95 + assert !NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
  96 + p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
  97 + fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
  98 + fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
  99 + fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
  100 + fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
  101 + ActionTrackerNotification.delete_all
  102 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
  103 + job.perform
  104 + process_delayed_job_queue
  105 +
  106 + assert_equal 6, ActionTrackerNotification.count
  107 + [person, community, p1, p2, m1, m2].each do |profile|
  108 + notification = ActionTrackerNotification.find_by_profile_id profile.id
  109 + assert_equal action_tracker, notification.action_tracker
  110 + end
  111 + end
  112 +
  113 + should 'not notify the community tracking join_community verb' do
  114 + person = fast_create(Person)
  115 + community = fast_create(Community)
  116 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'join_community')
  117 + assert !NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
  118 + p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
  119 + fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
  120 + fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
  121 + fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
  122 + fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
  123 + ActionTrackerNotification.delete_all
  124 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
  125 + job.perform
  126 + process_delayed_job_queue
  127 +
  128 + assert_equal 5, ActionTrackerNotification.count
  129 + [person, p1, p2, m1, m2].each do |profile|
  130 + notification = ActionTrackerNotification.find_by_profile_id profile.id
  131 + assert_equal action_tracker, notification.action_tracker
  132 + end
  133 + end
  134 +
  135 + should 'not notify the community tracking leave_community verb' do
  136 + person = fast_create(Person)
  137 + community = fast_create(Community)
  138 + action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'leave_community')
  139 + assert !NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
  140 + p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
  141 + fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
  142 + fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
  143 + fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
  144 + fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
  145 + ActionTrackerNotification.delete_all
  146 + job = NotifyActivityToProfilesJob.new(action_tracker.id)
  147 + job.perform
  148 + process_delayed_job_queue
  149 +
  150 + assert_equal 5, ActionTrackerNotification.count
  151 + [person, p1, p2, m1, m2].each do |profile|
  152 + notification = ActionTrackerNotification.find_by_profile_id profile.id
  153 + assert_equal action_tracker, notification.action_tracker
  154 + end
  155 + end
  156 +
  157 + should "the NOTIFY_ONLY_COMMUNITY constant has all the verbs tested" do
  158 + notify_community_verbs = ['add_member_in_community', 'remove_member_in_community']
  159 + assert_equal [], notify_community_verbs - NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY
  160 + assert_equal [], NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY - notify_community_verbs
  161 + end
  162 +
  163 + should "the NOT_NOTIFY_COMMUNITY constant has all the verbs tested" do
  164 + not_notify_community_verbs = ['join_community', 'leave_community']
  165 + assert_equal [], not_notify_community_verbs - NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY
  166 + assert_equal [], NotifyActivityToProfilesJob::NOT_NOTIFY_COMMUNITY - not_notify_community_verbs
  167 + end
  168 +
25 169 end
... ...
test/unit/person_test.rb
... ... @@ -829,7 +829,7 @@ class PersonTest &lt; Test::Unit::TestCase
829 829 end
830 830 end
831 831  
832   - should "the tracked action notify friends with one delayed job process followed by others jobs created after run the firt job" do
  832 + should "the tracked action notify friends with one delayed job process" do
833 833 p1 = Person.first
834 834 p2 = fast_create(Person)
835 835 p3 = fast_create(Person)
... ... @@ -847,8 +847,7 @@ class PersonTest &lt; Test::Unit::TestCase
847 847 assert_difference(Delayed::Job, :count, 1) do
848 848 Person.notify_activity(action_tracker)
849 849 end
850   -
851   - assert_difference(ActionTrackerNotification, :count, 2) do
  850 + assert_difference(ActionTrackerNotification, :count, 3) do
852 851 process_delayed_job_queue
853 852 end
854 853 end
... ... @@ -866,13 +865,9 @@ class PersonTest &lt; Test::Unit::TestCase
866 865 assert !p2.is_member_of?(community)
867 866 process_delayed_job_queue
868 867  
869   - action_tracker = fast_create(ActionTracker::Record)
870   - article = mock()
871   - action_tracker.stubs(:dispatcher).returns(article)
872   - article.stubs(:is_a?).with(Article).returns(true)
873   - article.stubs(:is_a?).with(RoleAssignment).returns(false)
874   - article.stubs(:is_a?).with(Comment).returns(false)
875   - article.stubs(:profile).returns(community)
  868 + action_tracker = fast_create(ActionTracker::Record, :verb => 'create_article')
  869 + action_tracker.target = community
  870 + action_tracker.save!
876 871 ActionTrackerNotification.delete_all
877 872 assert_difference(ActionTrackerNotification, :count, 3) do
878 873 Person.notify_activity(action_tracker)
... ... @@ -900,7 +895,7 @@ class PersonTest &lt; Test::Unit::TestCase
900 895  
901 896 action_tracker = fast_create(ActionTracker::Record)
902 897 article = mock()
903   - action_tracker.stubs(:dispatcher).returns(article)
  898 + action_tracker.stubs(:target).returns(article)
904 899 article.stubs(:is_a?).with(Article).returns(true)
905 900 article.stubs(:is_a?).with(RoleAssignment).returns(false)
906 901 article.stubs(:is_a?).with(Comment).returns(false)
... ... @@ -960,9 +955,47 @@ class PersonTest &lt; Test::Unit::TestCase
960 955 p = create_user('test_user').person
961 956 c = fast_create(Community, :name => "Foo")
962 957 c.add_member(p)
963   - assert_equal ["Foo"], ActionTracker::Record.last.get_resource_name
  958 + assert_equal ["Foo"], ActionTracker::Record.last(:conditions => {:verb => 'join_community'}).get_resource_name
964 959 c.reload.add_moderator(p.reload)
965   - assert_equal ["Foo"], ActionTracker::Record.last.get_resource_name
  960 + assert_equal ["Foo"], ActionTracker::Record.last(:conditions => {:verb => 'join_community'}).get_resource_name
  961 + end
  962 +
  963 + should 'the tracker target be Community when a person joins a community' do
  964 + ActionTracker::Record.delete_all
  965 + p = create_user('test_user').person
  966 + c = fast_create(Community, :name => "Foo")
  967 + c.add_member(p)
  968 + assert_kind_of Community, ActionTracker::Record.last(:conditions => {:verb => 'join_community'}).target
  969 + end
  970 +
  971 + should 'the community be notified specifically when a person joins a community' do
  972 + ActionTracker::Record.delete_all
  973 + p = create_user('test_user').person
  974 + c = fast_create(Community, :name => "Foo")
  975 + c.add_member(p)
  976 + assert_not_nil ActionTracker::Record.last(:conditions => {:verb => 'add_member_in_community'})
  977 + end
  978 +
  979 + should 'the community specific notification created when a member joins community could not be propagated to members' do
  980 + ActionTracker::Record.delete_all
  981 + p1 = create_user('test_user').person
  982 + p2 = create_user('test_user').person
  983 + p3 = create_user('test_user').person
  984 + c = fast_create(Community, :name => "Foo")
  985 + c.add_member(p1)
  986 + process_delayed_job_queue
  987 + c.add_member(p3)
  988 + process_delayed_job_queue
  989 + assert_equal 4, ActionTracker::Record.count
  990 + assert_equal 5, ActionTrackerNotification.count
  991 + has_add_member_notification = false
  992 + ActionTrackerNotification.all.map do |notification|
  993 + if notification.action_tracker.verb == 'add_member_in_community'
  994 + has_add_member_notification = true
  995 + assert_equal c, notification.profile
  996 + end
  997 + end
  998 + assert has_add_member_notification
966 999 end
967 1000  
968 1001 should 'track only one action when a person leaves a community' do
... ... @@ -972,7 +1005,58 @@ class PersonTest &lt; Test::Unit::TestCase
972 1005 c.add_moderator(p)
973 1006 ActionTracker::Record.delete_all
974 1007 c.remove_member(p)
975   - assert_equal ["Foo"], ActionTracker::Record.last.get_resource_name
  1008 + assert_equal ["Foo"], ActionTracker::Record.last(:conditions => {:verb => 'leave_community'}).get_resource_name
  1009 + end
  1010 +
  1011 + should 'the tracker target be Community when a person leaves a community' do
  1012 + ActionTracker::Record.delete_all
  1013 + p = create_user('test_user').person
  1014 + c = fast_create(Community, :name => "Foo")
  1015 + c.add_member(p)
  1016 + c.add_moderator(p)
  1017 + ActionTracker::Record.delete_all
  1018 + c.remove_member(p)
  1019 + assert_kind_of Community, ActionTracker::Record.last(:conditions => {:verb => 'leave_community'}).target
  1020 + end
  1021 +
  1022 + should 'the community be notified specifically when a person leaves a community' do
  1023 + ActionTracker::Record.delete_all
  1024 + p = create_user('test_user').person
  1025 + c = fast_create(Community, :name => "Foo")
  1026 + c.add_member(p)
  1027 + c.add_moderator(p)
  1028 + ActionTracker::Record.delete_all
  1029 + c.remove_member(p)
  1030 + assert_not_nil ActionTracker::Record.last(:conditions => {:verb => 'remove_member_in_community'})
  1031 + end
  1032 +
  1033 + should 'the community specific notification created when a member leaves community could not be propagated to members' do
  1034 + ActionTracker::Record.delete_all
  1035 + p1 = Person.first
  1036 + p2 = create_user('test_user').person
  1037 + p3 = create_user('test_user').person
  1038 + c = fast_create(Community, :name => "Foo")
  1039 + process_delayed_job_queue
  1040 + Delayed::Job.delete_all
  1041 + c.add_member(p1)
  1042 + c.add_member(p3)
  1043 + c.add_moderator(p1)
  1044 + c.add_moderator(p3)
  1045 + ActionTracker::Record.delete_all
  1046 + c.remove_member(p1)
  1047 + process_delayed_job_queue
  1048 + c.remove_member(p3)
  1049 + process_delayed_job_queue
  1050 + assert_equal 4, ActionTracker::Record.count
  1051 + assert_equal 5, ActionTrackerNotification.count
  1052 + has_remove_member_notification = false
  1053 + ActionTrackerNotification.all.map do |notification|
  1054 + if notification.action_tracker.verb == 'remove_member_in_community'
  1055 + has_remove_member_notification = true
  1056 + assert_equal c, notification.profile
  1057 + end
  1058 + end
  1059 + assert has_remove_member_notification
976 1060 end
977 1061  
978 1062 end
... ...
test/unit/published_article_test.rb
... ... @@ -137,4 +137,136 @@ class PublishedArticleTest &lt; ActiveSupport::TestCase
137 137 assert_equal p.parent, new_parent
138 138 end
139 139  
  140 + should 'notifiable be true' do
  141 + a = fast_create(PublishedArticle)
  142 + assert a.notifiable?
  143 + end
  144 +
  145 + should 'notify activity on create' do
  146 + ActionTracker::Record.delete_all
  147 + a = fast_create(Article)
  148 + PublishedArticle.create! :reference_article => a, :name => 'test', :profile_id => fast_create(Profile).id, :published => true
  149 + assert_equal 1, ActionTracker::Record.count
  150 + end
  151 +
  152 + should 'notify with different trackers activity create with different targets' do
  153 + ActionTracker::Record.delete_all
  154 + profile = fast_create(Profile)
  155 + a = fast_create(Article)
  156 + PublishedArticle.create! :reference_article => a, :name => 'bar', :profile_id => profile.id, :published => true
  157 + a = fast_create(Article)
  158 + PublishedArticle.create! :reference_article => a, :name => 'another bar', :profile_id => profile.id, :published => true
  159 + assert_equal 1, ActionTracker::Record.count
  160 + a = fast_create(Article)
  161 + PublishedArticle.create! :reference_article => a, :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  162 + assert_equal 2, ActionTracker::Record.count
  163 + end
  164 +
  165 + should 'notify activity on update' do
  166 + ActionTracker::Record.delete_all
  167 + a = fast_create(Article)
  168 + a = PublishedArticle.create! :reference_article => a, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  169 + assert_equal 1, ActionTracker::Record.count
  170 + a.name = 'foo'
  171 + a.save!
  172 + assert_equal 2, ActionTracker::Record.count
  173 + end
  174 +
  175 + should 'notify with different trackers activity update with different targets' do
  176 + ActionTracker::Record.delete_all
  177 + a = fast_create(Article)
  178 + a1 = PublishedArticle.create! :reference_article => a, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  179 + a = fast_create(Article)
  180 + a2 = PublishedArticle.create! :reference_article => a, :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  181 + assert_equal 2, ActionTracker::Record.count
  182 + a1.name = 'foo'
  183 + a1.save!
  184 + assert_equal 3, ActionTracker::Record.count
  185 + a2.name = 'another foo'
  186 + a2.save!
  187 + assert_equal 4, ActionTracker::Record.count
  188 + end
  189 +
  190 + should 'notify activity on destroy' do
  191 + ActionTracker::Record.delete_all
  192 + a = fast_create(Article)
  193 + a = PublishedArticle.create! :reference_article => a, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  194 + assert_equal 1, ActionTracker::Record.count
  195 + a.destroy
  196 + assert_equal 2, ActionTracker::Record.count
  197 + end
  198 +
  199 + should 'notify different activities when destroy articles with diferrents targets' do
  200 + ActionTracker::Record.delete_all
  201 + a = fast_create(Article)
  202 + a1 = PublishedArticle.create! :reference_article => a, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  203 + a = fast_create(Article)
  204 + a2 = PublishedArticle.create! :reference_article => a, :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  205 + assert_equal 2, ActionTracker::Record.count
  206 + a1.destroy
  207 + assert_equal 3, ActionTracker::Record.count
  208 + a2.destroy
  209 + assert_equal 4, ActionTracker::Record.count
  210 + end
  211 +
  212 + should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do
  213 + ActionTracker::Record.delete_all
  214 + community = fast_create(Community)
  215 + p1 = Person.first
  216 + community.add_member(p1)
  217 + assert p1.is_member_of?(community)
  218 + a = fast_create(Article)
  219 + article = PublishedArticle.create! :reference_article => a, :name => 'test', :profile_id => community.id
  220 + assert_equal true, article.published?
  221 + assert_equal true, article.notifiable?
  222 + assert_equal false, article.image?
  223 + assert_equal Community, article.profile.class
  224 + assert_equal Community, ActionTracker::Record.last.target.class
  225 + end
  226 +
  227 + should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do
  228 + ActionTracker::Record.delete_all
  229 + person = Person.first
  230 + a = fast_create(Article)
  231 + article = PublishedArticle.create! :reference_article => a, :name => 'test', :profile_id => person.id
  232 + assert_equal true, article.published?
  233 + assert_equal true, article.notifiable?
  234 + assert_equal false, article.image?
  235 + assert_equal Person, article.profile.class
  236 + assert_equal person, ActionTracker::Record.last.target
  237 + end
  238 +
  239 + should 'not notify activity if the article is not advertise' do
  240 + ActionTracker::Record.delete_all
  241 + article = fast_create(Article)
  242 + a = PublishedArticle.create! :reference_article => article, :name => 'bar', :profile_id => fast_create(Profile).id, :published => true, :advertise => false
  243 + assert_equal true, a.published?
  244 + assert_equal true, a.notifiable?
  245 + assert_equal false, a.image?
  246 + assert_equal false, a.profile.is_a?(Community)
  247 + assert_equal 0, ActionTracker::Record.count
  248 + end
  249 +
  250 + should "have defined the is_trackable method defined" do
  251 + assert PublishedArticle.method_defined?(:is_trackable?)
  252 + end
  253 +
  254 + should "the common trackable conditions return the correct value" do
  255 + a = PublishedArticle.new
  256 + a.published = a.advertise = true
  257 + assert_equal true, a.published?
  258 + assert_equal true, a.notifiable?
  259 + assert_equal true, a.advertise?
  260 + assert_equal true, a.is_trackable?
  261 +
  262 + a.published=false
  263 + assert_equal false, a.published?
  264 + assert_equal false, a.is_trackable?
  265 +
  266 + a.published=true
  267 + a.advertise=false
  268 + assert_equal false, a.advertise?
  269 + assert_equal false, a.is_trackable?
  270 + end
  271 +
140 272 end
... ...
test/unit/textile_article_test.rb
... ... @@ -38,6 +38,16 @@ class TextileArticleTest &lt; Test::Unit::TestCase
38 38 assert_equal 1, ActionTracker::Record.count
39 39 end
40 40  
  41 + should 'notify with different trackers activity create with different targets' do
  42 + ActionTracker::Record.delete_all
  43 + profile = fast_create(Profile)
  44 + TextileArticle.create! :name => 'bar', :profile_id => profile.id, :published => true
  45 + TextileArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true
  46 + assert_equal 1, ActionTracker::Record.count
  47 + TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  48 + assert_equal 2, ActionTracker::Record.count
  49 + end
  50 +
41 51 should 'notify activity on update' do
42 52 ActionTracker::Record.delete_all
43 53 a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
... ... @@ -47,6 +57,19 @@ class TextileArticleTest &lt; Test::Unit::TestCase
47 57 assert_equal 2, ActionTracker::Record.count
48 58 end
49 59  
  60 + should 'notify with different trackers activity update with different targets' do
  61 + ActionTracker::Record.delete_all
  62 + a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  63 + a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  64 + assert_equal 2, ActionTracker::Record.count
  65 + a1.name = 'foo'
  66 + a1.save!
  67 + assert_equal 3, ActionTracker::Record.count
  68 + a2.name = 'another foo'
  69 + a2.save!
  70 + assert_equal 4, ActionTracker::Record.count
  71 + end
  72 +
50 73 should 'notify activity on destroy' do
51 74 ActionTracker::Record.delete_all
52 75 a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
... ... @@ -55,4 +78,72 @@ class TextileArticleTest &lt; Test::Unit::TestCase
55 78 assert_equal 2, ActionTracker::Record.count
56 79 end
57 80  
  81 + should 'notify different activities when destroy articles with diferrents targets' do
  82 + ActionTracker::Record.delete_all
  83 + a1 = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  84 + a2 = TextileArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  85 + assert_equal 2, ActionTracker::Record.count
  86 + a1.destroy
  87 + assert_equal 3, ActionTracker::Record.count
  88 + a2.destroy
  89 + assert_equal 4, ActionTracker::Record.count
  90 + end
  91 +
  92 + should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do
  93 + ActionTracker::Record.delete_all
  94 + community = fast_create(Community)
  95 + p1 = Person.first
  96 + community.add_member(p1)
  97 + assert p1.is_member_of?(community)
  98 + article = TextileArticle.create! :name => 'test', :profile_id => community.id
  99 + assert_equal true, article.published?
  100 + assert_equal true, article.notifiable?
  101 + assert_equal false, article.image?
  102 + assert_equal Community, article.profile.class
  103 + assert_equal Community, ActionTracker::Record.last.target.class
  104 + end
  105 +
  106 + should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do
  107 + ActionTracker::Record.delete_all
  108 + person = Person.first
  109 + article = TextileArticle.create! :name => 'test', :profile_id => person.id
  110 + assert_equal true, article.published?
  111 + assert_equal true, article.notifiable?
  112 + assert_equal false, article.image?
  113 + assert_equal Person, article.profile.class
  114 + assert_equal person, ActionTracker::Record.last.target
  115 + end
  116 +
  117 + should 'not notify activity if the article is not advertise' do
  118 + ActionTracker::Record.delete_all
  119 + a = TextileArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true, :advertise => false
  120 + assert_equal true, a.published?
  121 + assert_equal true, a.notifiable?
  122 + assert_equal false, a.image?
  123 + assert_equal false, a.profile.is_a?(Community)
  124 + assert_equal 0, ActionTracker::Record.count
  125 + end
  126 +
  127 + should "have defined the is_trackable method defined" do
  128 + assert TextileArticle.method_defined?(:is_trackable?)
  129 + end
  130 +
  131 + should "the common trackable conditions return the correct value" do
  132 + a = TextileArticle.new
  133 + a.published = a.advertise = true
  134 + assert_equal true, a.published?
  135 + assert_equal true, a.notifiable?
  136 + assert_equal true, a.advertise?
  137 + assert_equal true, a.is_trackable?
  138 +
  139 + a.published=false
  140 + assert_equal false, a.published?
  141 + assert_equal false, a.is_trackable?
  142 +
  143 + a.published=true
  144 + a.advertise=false
  145 + assert_equal false, a.advertise?
  146 + assert_equal false, a.is_trackable?
  147 + end
  148 +
58 149 end
... ...
test/unit/tiny_mce_article_test.rb
... ... @@ -129,6 +129,16 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
129 129 assert_equal 1, ActionTracker::Record.count
130 130 end
131 131  
  132 + should 'notify with different trackers activity create with different targets' do
  133 + ActionTracker::Record.delete_all
  134 + profile = fast_create(Profile)
  135 + TinyMceArticle.create! :name => 'bar', :profile_id => profile.id, :published => true
  136 + TinyMceArticle.create! :name => 'another bar', :profile_id => profile.id, :published => true
  137 + assert_equal 1, ActionTracker::Record.count
  138 + TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  139 + assert_equal 2, ActionTracker::Record.count
  140 + end
  141 +
132 142 should 'notify activity on update' do
133 143 ActionTracker::Record.delete_all
134 144 a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
... ... @@ -138,6 +148,19 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
138 148 assert_equal 2, ActionTracker::Record.count
139 149 end
140 150  
  151 + should 'notify with different trackers activity update with different targets' do
  152 + ActionTracker::Record.delete_all
  153 + a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  154 + a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  155 + assert_equal 2, ActionTracker::Record.count
  156 + a1.name = 'foo'
  157 + a1.save!
  158 + assert_equal 3, ActionTracker::Record.count
  159 + a2.name = 'another foo'
  160 + a2.save!
  161 + assert_equal 4, ActionTracker::Record.count
  162 + end
  163 +
141 164 should 'notify activity on destroy' do
142 165 ActionTracker::Record.delete_all
143 166 a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
... ... @@ -146,4 +169,73 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
146 169 assert_equal 2, ActionTracker::Record.count
147 170 end
148 171  
  172 + should 'notify different activities when destroy articles with diferrents targets' do
  173 + ActionTracker::Record.delete_all
  174 + a1 = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true
  175 + a2 = TinyMceArticle.create! :name => 'another bar', :profile_id => fast_create(Profile).id, :published => true
  176 + assert_equal 2, ActionTracker::Record.count
  177 + a1.destroy
  178 + assert_equal 3, ActionTracker::Record.count
  179 + a2.destroy
  180 + assert_equal 4, ActionTracker::Record.count
  181 + end
  182 +
  183 + should "the tracker action target be defined as Community by custom_target method on articles'creation in communities" do
  184 + ActionTracker::Record.delete_all
  185 + community = fast_create(Community)
  186 + p1 = Person.first
  187 + community.add_member(p1)
  188 + assert p1.is_member_of?(community)
  189 + article = TinyMceArticle.create! :name => 'test', :profile_id => community.id
  190 + assert_equal true, article.published?
  191 + assert_equal true, article.notifiable?
  192 + assert_equal false, article.image?
  193 + assert_equal Community, article.profile.class
  194 + assert_equal Community, ActionTracker::Record.last.target.class
  195 + end
  196 +
  197 + should "the tracker action target be defined as person by custom_target method on articles'creation in profile" do
  198 + ActionTracker::Record.delete_all
  199 + person = Person.first
  200 + article = TinyMceArticle.create! :name => 'test', :profile_id => person.id
  201 + assert_equal true, article.published?
  202 + assert_equal true, article.notifiable?
  203 + assert_equal false, article.image?
  204 + assert_equal Person, article.profile.class
  205 + assert_equal person, ActionTracker::Record.last.target
  206 + end
  207 +
  208 + should 'not notify activity if the article is not advertise' do
  209 + ActionTracker::Record.delete_all
  210 + a = TinyMceArticle.create! :name => 'bar', :profile_id => fast_create(Profile).id, :published => true, :advertise => false
  211 + assert_equal true, a.published?
  212 + assert_equal true, a.notifiable?
  213 + assert_equal false, a.image?
  214 + assert_equal false, a.profile.is_a?(Community)
  215 + assert_equal 0, ActionTracker::Record.count
  216 + end
  217 +
  218 + should "have defined the is_trackable method defined" do
  219 + assert TinyMceArticle.method_defined?(:is_trackable?)
  220 + end
  221 +
  222 + should "the common trackable conditions return the correct value" do
  223 + a = TinyMceArticle.new
  224 + a.published = a.advertise = true
  225 + assert_equal true, a.published?
  226 + assert_equal true, a.notifiable?
  227 + assert_equal true, a.advertise?
  228 + assert_equal true, a.is_trackable?
  229 +
  230 + a.published=false
  231 + assert_equal false, a.published?
  232 + assert_equal false, a.is_trackable?
  233 +
  234 + a.published=true
  235 + a.advertise=false
  236 + assert_equal false, a.advertise?
  237 + assert_equal false, a.is_trackable?
  238 + end
  239 +
  240 +
149 241 end
... ...
vendor/plugins/access_control/lib/role_assignment.rb
... ... @@ -5,10 +5,14 @@ class RoleAssignment &lt; ActiveRecord::Base
5 5  
6 6 validates_presence_of :role, :accessor
7 7  
8   - track_actions :join_community, :after_create, :keep_params => ["resource.name", "resource.url", "resource.profile_custom_icon"], :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }
  8 + track_actions :join_community, :after_create, :keep_params => ["resource.name", "resource.url", "resource.profile_custom_icon"], :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_user => :accessor, :custom_target => :resource
9 9  
10   - track_actions :leave_community, :before_destroy, :keep_params => ["resource.name", "resource.url", "resource.profile_custom_icon"], :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }
  10 + track_actions :add_member_in_community, :after_create, :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_user => :accessor, :custom_target => :resource
11 11  
  12 + track_actions :leave_community, :before_destroy, :keep_params => ["resource.name", "resource.url", "resource.profile_custom_icon"], :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_user => :accessor, :custom_target => :resource
  13 +
  14 + track_actions :remove_member_in_community, :before_destroy, :if => Proc.new { |x| x.resource.is_a?(Community) && x.accessor.role_assignments.count(:conditions => { :resource_id => x.resource.id, :resource_type => 'Profile' }) == 1 }, :custom_target => :resource, :custom_user => :accessor
  15 +
12 16 def has_permission?(perm, res)
13 17 return false unless role.has_permission?(perm.to_s) && (resource || is_global)
14 18 return true if is_global
... ...
vendor/plugins/action_tracker/generators/action_tracker/templates/migration.rb
... ... @@ -2,7 +2,7 @@ class CreateActionTracker &lt; ActiveRecord::Migration
2 2 def self.up
3 3 create_table :action_tracker do |t|
4 4 t.belongs_to :user, :polymorphic => true
5   - t.belongs_to :dispatcher, :polymorphic => true
  5 + t.belongs_to :target, :polymorphic => true
6 6 t.text :params
7 7 t.string :verb
8 8 t.timestamps
... ... @@ -10,7 +10,7 @@ class CreateActionTracker &lt; ActiveRecord::Migration
10 10  
11 11 change_table :action_tracker do |t|
12 12 t.index [:user_id, :user_type]
13   - t.index [:dispatcher_id, :dispatcher_type]
  13 + t.index [:target_id, :target_type]
14 14 t.index :verb
15 15 end
16 16 end
... ...
vendor/plugins/action_tracker/lib/action_tracker.rb
... ... @@ -67,7 +67,9 @@ module ActionTracker
67 67 def track_actions(verb, callback, options = {}, &block)
68 68 keep_params = options.delete(:keep_params) || options.delete('keep_params') || :all
69 69 post_proc = options.delete(:post_processing) || options.delete('post_processing') || Proc.new{}
70   - send(callback, Proc.new { |tracked| tracked.save_action_for_verb(verb.to_s, keep_params, post_proc) }, options)
  70 + custom_user = options.delete(:custom_user) || options.delete('custom_user') || nil
  71 + custom_target = options.delete(:custom_target) || options.delete('custom_target') || nil
  72 + send(callback, Proc.new { |tracked| tracked.save_action_for_verb(verb.to_s, keep_params, post_proc, custom_user, custom_target) }, options)
71 73 send :include, InstanceMethods
72 74 end
73 75  
... ... @@ -86,8 +88,10 @@ module ActionTracker
86 88 time.to_f
87 89 end
88 90  
89   - def save_action_for_verb(verb, keep_params = :all, post_proc = Proc.new{})
90   - user = ActionTracker::Record.current_user_from_model
  91 + def save_action_for_verb(verb, keep_params = :all, post_proc = Proc.new{}, custom_user = nil, custom_target = nil)
  92 + user = self.send(custom_user) unless custom_user.blank?
  93 + user ||= ActionTracker::Record.current_user_from_model
  94 + target = self.send(custom_target) unless custom_target.blank?
91 95 return nil if user.nil?
92 96 if keep_params.is_a? Array
93 97 stored_params = {}
... ... @@ -103,13 +107,13 @@ module ActionTracker
103 107 end
104 108 tracked_action = case ActionTrackerConfig.verb_type(verb)
105 109 when :groupable
106   - Record.add_or_create :verb => verb, :params => stored_params
  110 + Record.add_or_create :verb => verb, :params => stored_params, :user => user, :target => target
107 111 when :updatable
108   - Record.update_or_create :verb => verb, :params => stored_params
  112 + Record.update_or_create :verb => verb, :params => stored_params, :user => user, :target => target
109 113 when :single
110   - Record.new :verb => verb, :params => stored_params
  114 + Record.new :verb => verb, :params => stored_params, :user => user
111 115 end
112   - tracked_action.dispatcher = self
  116 + tracked_action.target = target || self
113 117 user.tracked_actions << tracked_action
114 118 post_proc.call tracked_action.reload
115 119 end
... ...
vendor/plugins/action_tracker/lib/action_tracker_model.rb
... ... @@ -4,7 +4,7 @@ module ActionTracker
4 4 set_table_name 'action_tracker'
5 5  
6 6 belongs_to :user, :polymorphic => true
7   - belongs_to :dispatcher, :polymorphic => true
  7 + belongs_to :target, :polymorphic => true
8 8  
9 9 serialize :params, Hash
10 10  
... ... @@ -25,7 +25,9 @@ module ActionTracker
25 25 def self.update_or_create(params)
26 26 u = params[:user] || current_user_from_model
27 27 return if u.nil?
28   - l = last :conditions => { :user_id => u.id, :user_type => u.class.base_class.to_s, :verb => params[:verb].to_s }
  28 + target_hash = params[:target].nil? ? {} : {:target_type => params[:target].class.base_class.to_s, :target_id => params[:target].id}
  29 + conditions = { :user_id => u.id, :user_type => u.class.base_class.to_s, :verb => params[:verb].to_s }.merge(target_hash)
  30 + l = last :conditions => conditions
29 31 ( !l.nil? and Time.now - l.updated_at < ActionTrackerConfig.timeout ) ? l.update_attributes(params.merge({ :updated_at => Time.now })) : l = new(params)
30 32 l
31 33 end
... ... @@ -33,7 +35,8 @@ module ActionTracker
33 35 def self.add_or_create(params)
34 36 u = params[:user] || current_user_from_model
35 37 return if u.nil?
36   - l = last :conditions => { :user_id => u.id, :user_type => u.class.base_class.to_s, :verb => params[:verb].to_s }
  38 + target_hash = params[:target].nil? ? {} : {:target_type => params[:target].class.base_class.to_s, :target_id => params[:target].id}
  39 + l = last :conditions => { :user_id => u.id, :user_type => u.class.base_class.to_s, :verb => params[:verb].to_s }.merge(target_hash)
37 40 if !l.nil? and Time.now - l.updated_at < ActionTrackerConfig.timeout
38 41 params[:params].clone.each { |key, value| params[:params][key] = l.params[key].clone.push(value) }
39 42 l.update_attributes params
... ...
vendor/plugins/action_tracker/test/action_tracker_model_test.rb
... ... @@ -11,7 +11,7 @@ ActiveRecord::Schema.define do
11 11 end
12 12 create_table :action_tracker do |t|
13 13 t.belongs_to :user, :polymorphic => true
14   - t.belongs_to :dispatcher, :polymorphic => true
  14 + t.belongs_to :target, :polymorphic => true
15 15 t.text :params
16 16 t.string :verb
17 17 t.timestamps
... ... @@ -29,7 +29,7 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
29 29 ActionTrackerConfig.verbs = { :some_verb => { :description => "Did something" } }
30 30 @mymodel = SomeModel.create!
31 31 @othermodel = SomeModel.create!
32   - @tracked_action = ActionTracker::Record.create! :verb => :some_verb, :params => { :user => "foo" }, :user => @mymodel, :dispatcher => @othermodel
  32 + @tracked_action = ActionTracker::Record.create! :verb => :some_verb, :params => { :user => "foo" }, :user => @mymodel, :target => @othermodel
33 33 end
34 34  
35 35 def test_has_relationship
... ... @@ -47,10 +47,10 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
47 47 assert_equal [@tracked_action], @mymodel.tracked_actions
48 48 end
49 49  
50   - def test_has_a_polymorphic_relation_with_dispatcher
51   - assert_equal @othermodel.id, @tracked_action.dispatcher_id
52   - assert_equal "SomeModel", @tracked_action.dispatcher_type
53   - assert_equal @othermodel, @tracked_action.dispatcher
  50 + def test_has_a_polymorphic_relation_with_target
  51 + assert_equal @othermodel.id, @tracked_action.target_id
  52 + assert_equal "SomeModel", @tracked_action.target_type
  53 + assert_equal @othermodel, @tracked_action.target
54 54 end
55 55  
56 56 def test_should_stringify_verb_before_validation
... ... @@ -90,7 +90,7 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
90 90 assert_equal @mymodel, ActionTracker::Record.last.user
91 91 end
92 92  
93   - def test_update_or_create_create_if_no_timeout
  93 + def test_update_or_create_create_if_timeout
94 94 ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :updatable } }
95 95 ActionTrackerConfig.timeout = 5.minutes
96 96 ActionTracker::Record.delete_all
... ... @@ -111,7 +111,7 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
111 111 assert_equal t, ta.reload.updated_at
112 112 end
113 113  
114   - def test_update_or_create_update_if_timeout
  114 + def test_update_or_create_update_if_no_timeout
115 115 ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :updatable } }
116 116 ActionTrackerConfig.timeout = 7.minutes
117 117 ActionTracker::Record.delete_all
... ... @@ -134,7 +134,37 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
134 134 assert_equal 3, ta.reload.get_foo
135 135 end
136 136  
137   - def test_add_or_create_create_if_no_timeout
  137 + def test_should_update_or_create_method_create_a_new_tracker_with_different_dispacthers
  138 + ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :updatable } }
  139 + ActionTracker::Record.delete_all
  140 + ta = nil
  141 + assert_difference "ActionTracker::Record.count" do
  142 + ta = ActionTracker::Record.update_or_create :verb => :some, :user => @mymodel, :target => @mymodel, :params => { :foo => 2 }
  143 + ta.save; ta.reload
  144 + end
  145 + assert_kind_of ActionTracker::Record, ta
  146 + t = ta.reload.updated_at
  147 + sleep(1)
  148 + assert_no_difference "ActionTracker::Record.count" do
  149 + ta2 = ActionTracker::Record.update_or_create :verb => :some, :user => @mymodel, :target => @mymodel, :params => { :foo => 3 }
  150 + ta2.save; ta2.reload
  151 + assert_kind_of ActionTracker::Record, ta2
  152 + end
  153 + assert_equal 3, ta.reload.get_foo
  154 + assert_not_equal t, ta.reload.updated_at
  155 +
  156 + assert_kind_of ActionTracker::Record, ta
  157 + t = ta.reload.updated_at
  158 + assert_difference "ActionTracker::Record.count" do
  159 + ta2 = ActionTracker::Record.update_or_create :verb => :some, :user => @mymodel, :target => @othermodel, :params => { :foo => 4 }
  160 + ta2.save; ta2.reload
  161 + assert_kind_of ActionTracker::Record, ta2
  162 + end
  163 + assert_equal t, ta.reload.updated_at
  164 + assert_equal 3, ta.reload.get_foo
  165 + end
  166 +
  167 + def test_add_or_create_create_if_timeout
138 168 ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :groupable } }
139 169 ActionTrackerConfig.timeout = 5.minutes
140 170 ActionTracker::Record.delete_all
... ... @@ -157,7 +187,7 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
157 187 assert_equal ["test"], ActionTracker::Record.last.params[:foo]
158 188 end
159 189  
160   - def test_add_or_create_update_if_timeout
  190 + def test_add_or_create_update_if_no_timeout
161 191 ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :updatable } }
162 192 ActionTrackerConfig.timeout = 7.minutes
163 193 ActionTracker::Record.delete_all
... ... @@ -188,6 +218,30 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
188 218 assert_equal [2, 1, 1], ActionTracker::Record.last.params[:bar]
189 219 end
190 220  
  221 + def test_add_or_create_create_if_no_timeout_and_different_target
  222 + ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :updatable } }
  223 + ActionTrackerConfig.timeout = 7.minutes
  224 + ActionTracker::Record.delete_all
  225 + ta = nil
  226 + assert_difference "ActionTracker::Record.count" do
  227 + ta = ActionTracker::Record.add_or_create :verb => :some, :user => @mymodel, :target => @mymodel, :params => { :foo => "test 1", :bar => 2 }
  228 + ta.save; ta.reload
  229 + end
  230 + assert_kind_of ActionTracker::Record, ta
  231 + assert_equal ["test 1"], ta.params[:foo]
  232 + assert_equal [2], ta.params[:bar]
  233 + ta.updated_at = Time.now.ago(6.minutes)
  234 + ta.send :update_without_callbacks
  235 + t = ta.reload.updated_at
  236 + assert_difference "ActionTracker::Record.count" do
  237 + ta2 = ActionTracker::Record.add_or_create :verb => :some, :user => @mymodel, :target => @othermodel, :params => { :foo => "test 2", :bar => 1 }
  238 + ta2.save; ta2.reload
  239 + assert_kind_of ActionTracker::Record, ta2
  240 + end
  241 + assert_equal ["test 1"], ta.params[:foo]
  242 + assert_equal [2], ta.params[:bar]
  243 + end
  244 +
191 245 def test_time_spent
192 246 ActionTracker::Record.delete_all
193 247 ActionTrackerConfig.verbs = { :some => { :description => "Something", :type => :updatable } }
... ...
vendor/plugins/action_tracker/test/action_tracker_test.rb
... ... @@ -15,7 +15,7 @@ ActiveRecord::Schema.define do
15 15 end
16 16 create_table :action_tracker do |t|
17 17 t.belongs_to :user, :polymorphic => true
18   - t.belongs_to :dispatcher, :polymorphic => true
  18 + t.belongs_to :target, :polymorphic => true
19 19 t.text :params
20 20 t.string :verb
21 21 t.timestamps
... ... @@ -29,6 +29,7 @@ end
29 29  
30 30 class OtherModel < ActiveRecord::Base
31 31 set_table_name :other_table
  32 + acts_as_trackable
32 33 end
33 34  
34 35 class ThingsController < ActionController::Base
... ... @@ -38,7 +39,7 @@ class ThingsController &lt; ActionController::Base
38 39 render :text => "test"
39 40 end
40 41  
41   - def test
  42 + def test
42 43 render :text => "test"
43 44 end
44 45  
... ... @@ -490,7 +491,81 @@ class ActionTrackerTest &lt; ActiveSupport::TestCase
490 491 get :test
491 492 end
492 493 end
493   - assert_equal "test", OtherModel.last.other_column
  494 + assert_equal "test", OtherModel.last.other_column
  495 + end
  496 +
  497 + def test_track_actions_custom_user_as_symbol
  498 + ActionTrackerConfig.verbs = { :test => { :description => "Some" } }
  499 + model = create_model do
  500 + track_actions :test, :after_create, :custom_user => :test_custom_user
  501 + def current_user
  502 + SomeModel.create!
  503 + end
  504 + def test_custom_user
  505 + OtherModel.create!
  506 + end
  507 + end
  508 + @controller = create_controller_for_model(model, :another_column => 2)
  509 + assert_difference('ActionTracker::Record.count') { get :test }
  510 + assert_kind_of OtherModel, ActionTracker::Record.last.user
  511 + end
  512 +
  513 + def test_track_actions_custom_user_as_string
  514 + ActionTrackerConfig.verbs = { :test => { :description => "Some" } }
  515 + model = create_model do
  516 + track_actions :test, :after_create, "custom_user" => :test_custom_user
  517 + def current_user
  518 + SomeModel.create!
  519 + end
  520 + def test_custom_user
  521 + OtherModel.create!
  522 + end
  523 + end
  524 + @controller = create_controller_for_model(model, :another_column => 2)
  525 + assert_difference('ActionTracker::Record.count') { get :test }
  526 + assert_kind_of OtherModel, ActionTracker::Record.last.user
  527 + end
  528 +
  529 + def test_track_actions_custom_user_is_nil_by_default
  530 + ActionTrackerConfig.verbs = { :test => { :description => "Some" } }
  531 + model = create_model do
  532 + track_actions :test, :after_create
  533 + def current_user
  534 + SomeModel.create!
  535 + end
  536 + def test_custom_user
  537 + OtherModel.create!
  538 + end
  539 + end
  540 + @controller = create_controller_for_model(model, :another_column => 2)
  541 + assert_difference('ActionTracker::Record.count') { get :test }
  542 + assert_kind_of SomeModel, ActionTracker::Record.last.user
  543 + end
  544 +
  545 + def test_track_actions_custom_target_as_symbol
  546 + ActionTrackerConfig.verbs = { :test => { :description => "Some" } }
  547 + model = create_model do
  548 + track_actions :test, :after_create, :custom_target => :test_custom_target
  549 + def test_custom_target
  550 + SomeModel.create!
  551 + end
  552 + end
  553 + @controller = create_controller_for_model(model, :another_column => 2)
  554 + assert_difference('ActionTracker::Record.count') { get :test }
  555 + assert_kind_of SomeModel, ActionTracker::Record.last.target
  556 + end
  557 +
  558 + def test_track_actions_custom_target_as_string
  559 + ActionTrackerConfig.verbs = { :test => { :description => "Some" } }
  560 + model = create_model do
  561 + track_actions :test, :after_create, "custom_target" => :test_custom_target
  562 + def test_custom_target
  563 + SomeModel.create!
  564 + end
  565 + end
  566 + @controller = create_controller_for_model(model, :another_column => 2)
  567 + assert_difference('ActionTracker::Record.count') { get :test }
  568 + assert_kind_of SomeModel, ActionTracker::Record.last.target
494 569 end
495 570  
496 571 def test_acts_as_trackable_with_options
... ... @@ -515,7 +590,7 @@ class ActionTrackerTest &lt; ActiveSupport::TestCase
515 590 end
516 591 end
517 592  
518   - def test_track_actions_save_dispatcher
  593 + def test_track_actions_save_target
519 594 ActionTrackerConfig.verbs = { :test => { :description => "Some" } }
520 595 model = create_model do
521 596 track_actions :test, :after_create
... ... @@ -524,7 +599,7 @@ class ActionTrackerTest &lt; ActiveSupport::TestCase
524 599 assert_difference 'ActionTracker::Record.count' do
525 600 get :test
526 601 end
527   - assert_kind_of model.base_class, ActionTracker::Record.last.dispatcher
  602 + assert_kind_of model.base_class, ActionTracker::Record.last.target
528 603 end
529 604  
530 605 private
... ...
vendor/plugins/user_stamp/lib/user_stamp.rb
... ... @@ -30,12 +30,14 @@ class UserStampSweeper &lt; ActionController::Caching::Sweeper
30 30 def before_validation(record)
31 31 return unless current_user
32 32  
33   - if record.respond_to?(UserStamp.creator_assignment_method) && record.new_record?
34   - record.send(UserStamp.creator_assignment_method, current_user)
  33 + attribute, method = UserStamp.creator_attribute, UserStamp.creator_assignment_method
  34 + if record.respond_to?(method) && record.new_record?
  35 + record.send(method, current_user) unless record.send("#{attribute}_id_changed?") || record.send("#{attribute}_type_changed?")
35 36 end
36 37  
37   - if record.respond_to?(UserStamp.updater_assignment_method)
38   - record.send(UserStamp.updater_assignment_method, current_user)
  38 + attribute, method = UserStamp.updater_attribute, UserStamp.updater_assignment_method
  39 + if record.respond_to?(method)
  40 + record.send(method, current_user) if record.send(attribute).blank?
39 41 end
40 42 end
41 43  
... ...
vendor/plugins/user_stamp/spec/user_stamp_sweeper_spec.rb
... ... @@ -2,58 +2,59 @@ require File.dirname(__FILE__) + &#39;/spec_helper&#39;
2 2  
3 3 class PostsController
4 4 def self.current_user
5   - User.new(220)
  5 + @@user
6 6 end
7 7 end
8 8  
9 9 describe UserStampSweeper, "#before_validation" do
10 10 before do
11   - UserStamp.creator_attribute = :creator_id
12   - UserStamp.updater_attribute = :updater_id
  11 + @@user = User.new(220)
  12 + UserStamp.creator_attribute = :creator
  13 + UserStamp.updater_attribute = :updater
13 14 UserStamp.current_user_method = :current_user
14 15 @sweeper = UserStampSweeper.instance
15 16 @sweeper.stub!(:controller).and_return(PostsController)
16 17 end
17 18  
18 19 describe "(with new record)" do
19   - it "should set creator_id if attribute exists" do
20   - record = mock('Record', :creator_id= => nil, :updater_id= => nil, :new_record? => true)
21   - record.should_receive(:creator_id=).with(220).once
  20 + it "should set creator if attribute exists" do
  21 + record = mock('Record', :creator= => nil, :updater= => nil, :new_record? => true, :updater => nil, :creator_id_changed? => false, :creator_type_changed? => false, :updater_id_changed? => false, :updater_type_changed? => false)
  22 + record.should_receive(:creator=).with(@@user).once
22 23 @sweeper.before_validation(record)
23 24 end
24 25  
25   - it "should NOT set creator_id if attribute does not exist" do
26   - record = mock('Record', :new_record? => true, :updater_id= => nil, :respond_to? => false)
27   - record.should_receive(:respond_to?).with("creator_id=").and_return(false)
28   - record.should_not_receive(:creator_id=)
  26 + it "should NOT set creator if attribute does not exist" do
  27 + record = mock('Record', :new_record? => true, :updater= => nil, :respond_to? => false)
  28 + record.should_receive(:respond_to?).with("creator=").and_return(false)
  29 + record.should_not_receive(:creator=)
29 30 @sweeper.before_validation(record)
30 31 end
31 32 end
32 33  
33 34 describe "(with non new record)" do
34   - it "should NOT set creator_id if attribute exists" do
35   - record = mock('Record', :creator_id= => nil, :updater_id= => nil, :new_record? => false)
36   - record.should_not_receive(:creator_id=)
  35 + it "should NOT set creator if attribute exists" do
  36 + record = mock('Record', :creator= => nil, :updater= => nil, :updater => nil, :new_record? => false, :creator_id_changed? => false, :creator_type_changed? => false, :updater_id_changed? => false, :updater_type_changed? => false)
  37 + record.should_not_receive(:creator=)
37 38 @sweeper.before_validation(record)
38 39 end
39 40  
40   - it "should NOT set creator_id if attribute does not exist" do
41   - record = mock('Record', :updater_id= => nil, :new_record? => false)
42   - record.should_not_receive(:creator_id=)
  41 + it "should NOT set creator if attribute does not exist" do
  42 + record = mock('Record', :updater= => nil, :updater => nil, :new_record? => false, :creator_id_changed? => false, :creator_type_changed? => false, :updater_id_changed? => false, :updater_type_changed? => false)
  43 + record.should_not_receive(:creator=)
43 44 @sweeper.before_validation(record)
44 45 end
45 46 end
46 47  
47   - it "should set updater_id if attribute exists" do
48   - record = mock('Record', :creator_id= => nil, :updater_id= => nil, :new_record? => :false)
49   - record.should_receive(:updater_id=)
  48 + it "should set updater if attribute exists" do
  49 + record = mock('Record', :creator= => nil, :updater= => nil, :new_record? => false, :updater => nil)
  50 + record.should_receive(:updater=)
50 51 @sweeper.before_validation(record)
51 52 end
52 53  
53   - it "should NOT set updater_id if attribute does not exist" do
54   - record = mock('Record', :creator_id= => nil, :updater_id= => nil, :new_record? => :false, :respond_to? => false)
55   - record.should_receive(:respond_to?).with("updater_id=").and_return(false)
56   - record.should_not_receive(:updater_id=)
  54 + it "should NOT set updater if attribute does not exist" do
  55 + record = mock('Record', :creator= => nil, :updater= => nil, :new_record? => :false, :respond_to? => false)
  56 + record.should_receive(:respond_to?).with("updater=").and_return(false)
  57 + record.should_not_receive(:updater=)
57 58 @sweeper.before_validation(record)
58 59 end
59 60 end
... ... @@ -69,8 +70,8 @@ describe UserStampSweeper, &quot;#before_validation (with custom attribute names)&quot; do
69 70  
70 71 describe "(with new record)" do
71 72 it "should set created_by if attribute exists" do
72   - record = mock('Record', :created_by= => nil, :updated_by= => nil, :new_record? => true)
73   - record.should_receive(:created_by=).with(220).once
  73 + record = mock('Record', :created_by= => nil, :updated_by => nil, :updated_by= => nil, :new_record? => true, :created_by_id_changed? => false, :created_by_type_changed? => false, :updated_by_id_changed? => false, :updated_by_type_changed? => false)
  74 + record.should_receive(:created_by=).with(@@user).once
74 75 @sweeper.before_validation(record)
75 76 end
76 77  
... ... @@ -84,20 +85,20 @@ describe UserStampSweeper, &quot;#before_validation (with custom attribute names)&quot; do
84 85  
85 86 describe "(with non new record)" do
86 87 it "should NOT set created_by if attribute exists" do
87   - record = mock('Record', :created_by= => nil, :updated_by= => nil, :new_record? => false)
  88 + record = mock('Record', :created_by= => nil, :updated_by => nil, :updated_by= => nil, :new_record? => false, :updated_by_id_changed? => false, :updated_by_type_changed? => false)
88 89 record.should_not_receive(:created_by=)
89 90 @sweeper.before_validation(record)
90 91 end
91 92  
92 93 it "should NOT set created_by if attribute does not exist" do
93   - record = mock('Record', :updated_by= => nil, :new_record? => false)
  94 + record = mock('Record', :updated_by= => nil, :updated_by => nil, :new_record? => false, :updated_by_id_changed? => false, :updated_by_type_changed? => false)
94 95 record.should_not_receive(:created_by=)
95 96 @sweeper.before_validation(record)
96 97 end
97 98 end
98 99  
99 100 it "should set updated_by if attribute exists" do
100   - record = mock('Record', :created_by= => nil, :updated_by= => nil, :new_record? => :false)
  101 + record = mock('Record', :created_by= => nil, :updated_by= => nil, :updated_by => nil, :new_record? => :false, :created_by_id_changed? => false, :created_by_type_changed? => false, :updated_by_id_changed? => false, :updated_by_type_changed? => false)
101 102 record.should_receive(:updated_by=)
102 103 @sweeper.before_validation(record)
103 104 end
... ... @@ -108,12 +109,44 @@ describe UserStampSweeper, &quot;#before_validation (with custom attribute names)&quot; do
108 109 record.should_not_receive(:updated_by=)
109 110 @sweeper.before_validation(record)
110 111 end
  112 +
  113 + it "should NOT set created_by if attribute changed" do
  114 + record = mock('Record', :created_by= => nil, :updated_by= => nil, :new_record? => true, :created_by_id_changed? => true, :created_by_type_changed? => true)
  115 + record.should_receive(:respond_to?).with("updated_by=").and_return(false)
  116 + record.should_receive(:respond_to?).with("created_by=").and_return(true)
  117 + record.should_not_receive(:created_by=)
  118 + @sweeper.before_validation(record)
  119 + end
  120 +
  121 + it "should NOT set updated_by if attribute is not nil" do
  122 + record = mock('Record', :created_by= => nil, :updated_by= => nil, :updated_by => 1, :new_record? => false)
  123 + record.should_receive(:respond_to?).with("updated_by=").and_return(true)
  124 + record.should_receive(:respond_to?).with("created_by=").and_return(false)
  125 + record.should_not_receive(:updated_by=)
  126 + @sweeper.before_validation(record)
  127 + end
  128 +
  129 + it "should set created_by if attribute has not changed" do
  130 + record = mock('Record', :created_by= => nil, :updated_by= => nil, :new_record? => true, :created_by_id_changed? => false, :created_by_type_changed? => false)
  131 + record.should_receive(:respond_to?).with("updated_by=").and_return(false)
  132 + record.should_receive(:respond_to?).with("created_by=").and_return(true)
  133 + record.should_receive(:created_by=)
  134 + @sweeper.before_validation(record)
  135 + end
  136 +
  137 + it "should set updated_by if attribute is nil" do
  138 + record = mock('Record', :created_by= => nil, :updated_by= => nil, :updated_by => nil, :new_record? => false)
  139 + record.should_receive(:respond_to?).with("updated_by=").and_return(true)
  140 + record.should_receive(:respond_to?).with("created_by=").and_return(false)
  141 + record.should_receive(:updated_by=)
  142 + @sweeper.before_validation(record)
  143 + end
111 144 end
112 145  
113 146 describe UserStampSweeper, "#current_user" do
114 147 before do
115   - UserStamp.creator_attribute = :creator_id
116   - UserStamp.updater_attribute = :updater_id
  148 + UserStamp.creator_attribute = :creator
  149 + UserStamp.updater_attribute = :updater
117 150 UserStamp.current_user_method = :current_user
118 151 @sweeper = UserStampSweeper.instance
119 152 end
... ... @@ -137,8 +170,8 @@ end
137 170  
138 171 describe UserStampSweeper, "#current_user (with custom current_user_method)" do
139 172 before do
140   - UserStamp.creator_attribute = :creator_id
141   - UserStamp.updater_attribute = :updater_id
  173 + UserStamp.creator_attribute = :creator
  174 + UserStamp.updater_attribute = :updater
142 175 UserStamp.current_user_method = :my_user
143 176 @sweeper = UserStampSweeper.instance
144 177 end
... ... @@ -158,4 +191,4 @@ describe UserStampSweeper, &quot;#current_user (with custom current_user_method)&quot; do
158 191 controller.should_not_receive(:my_user)
159 192 @sweeper.send(:current_user)
160 193 end
161   -end
162 194 \ No newline at end of file
  195 +end
... ...