Commit d5d9e7da9ac12964930897882ea047961855ae02

Authored by Rodrigo Souto
2 parents be1a989b 8bef50d2

Merge branch 'search-optimizations' into stable

Showing 35 changed files with 461 additions and 129 deletions   Show diff stats
app/helpers/cache_counter_helper.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +module CacheCounterHelper
  2 + def update_cache_counter(name, object, value)
  3 + if object.present?
  4 + object.class.update_counters(object.id, name => value)
  5 + end
  6 + end
  7 +end
... ...
app/models/friendship.rb
1 1 class Friendship < ActiveRecord::Base
2 2 track_actions :new_friendship, :after_create, :keep_params => ["friend.name", "friend.url", "friend.profile_custom_icon"], :custom_user => :person
3   -
  3 +
  4 + extend CacheCounterHelper
  5 +
4 6 belongs_to :person, :foreign_key => :person_id
5 7 belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id'
  8 +
  9 + after_create do |friendship|
  10 + update_cache_counter(:friends_count, friendship.person, 1)
  11 + update_cache_counter(:friends_count, friendship.friend, 1)
  12 + end
  13 +
  14 + after_destroy do |friendship|
  15 + update_cache_counter(:friends_count, friendship.person, -1)
  16 + update_cache_counter(:friends_count, friendship.friend, -1)
  17 + end
6 18 end
... ...
app/models/organization.rb
... ... @@ -26,18 +26,7 @@ class Organization &lt; Profile
26 26  
27 27 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source'
28 28  
29   - named_scope :more_popular,
30   - :select => "#{Profile.qualified_column_names}, count(resource_id) as total",
31   - :group => Profile.qualified_column_names,
32   - :joins => "LEFT OUTER JOIN role_assignments ON profiles.id = role_assignments.resource_id",
33   - :order => "total DESC"
34   -
35   - named_scope :more_active,
36   - :select => "#{Profile.qualified_column_names}, count(action_tracker.id) as total",
37   - :joins => "LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id",
38   - :group => Profile.qualified_column_names,
39   - :order => 'total DESC',
40   - :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago]
  29 + named_scope :more_popular, :order => 'members_count DESC'
41 30  
42 31 def validation_methodology
43 32 self.validation_info ? self.validation_info.validation_methodology : nil
... ...
app/models/person.rb
... ... @@ -66,18 +66,7 @@ class Person &lt; Profile
66 66 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
67 67 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
68 68  
69   - named_scope :more_popular,
70   - :select => "#{Profile.qualified_column_names}, count(friend_id) as total",
71   - :group => Profile.qualified_column_names,
72   - :joins => "LEFT OUTER JOIN friendships on profiles.id = friendships.person_id",
73   - :order => "total DESC"
74   -
75   - named_scope :more_active,
76   - :select => "#{Profile.qualified_column_names}, count(action_tracker.id) as total",
77   - :joins => "LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id",
78   - :group => Profile.qualified_column_names,
79   - :order => 'total DESC',
80   - :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago]
  69 + named_scope :more_popular, :order => 'friends_count DESC'
81 70  
82 71 named_scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*'
83 72 named_scope :non_abusers, :joins => "LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'", :conditions => ["tasks.status != 3 OR tasks.id is NULL"], :select => "DISTINCT profiles.*"
... ...
app/models/profile.rb
... ... @@ -87,10 +87,6 @@ class Profile &lt; ActiveRecord::Base
87 87 scopes.size == 1 ? scopes.first : Person.or_scope(scopes)
88 88 end
89 89  
90   - def members_count
91   - members.count
92   - end
93   -
94 90 class << self
95 91 def count_with_distinct(*args)
96 92 options = args.last || {}
... ... @@ -113,10 +109,11 @@ class Profile &lt; ActiveRecord::Base
113 109  
114 110 named_scope :visible, :conditions => { :visible => true }
115 111 named_scope :public, :conditions => { :visible => true, :public_profile => true }
116   - # Subclasses must override these methods
  112 +
  113 + # Subclasses must override this method
117 114 named_scope :more_popular
118   - named_scope :more_active
119 115  
  116 + named_scope :more_active, :order => 'activities_count DESC'
120 117 named_scope :more_recent, :order => "created_at DESC"
121 118  
122 119 acts_as_trackable :dependent => :destroy
... ... @@ -611,10 +608,10 @@ private :generate_url, :url_options
611 608 # Adds a person as member of this Profile.
612 609 def add_member(person)
613 610 if self.has_members?
614   - if self.closed? && members_count > 0
  611 + if self.closed? && members.count > 0
615 612 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person)
616 613 else
617   - self.affiliate(person, Profile::Roles.admin(environment.id)) if members_count == 0
  614 + self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0
618 615 self.affiliate(person, Profile::Roles.member(environment.id))
619 616 end
620 617 else
... ...
config/initializers/activities_counter_cache.rb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +job = Delayed::Backend::ActiveRecord::Job.all :conditions => ['handler LIKE ?', "%ActivitiesCounterCacheJob%"]
  2 +if job.blank?
  3 + Delayed::Backend::ActiveRecord::Job.enqueue(ActivitiesCounterCacheJob.new, -3)
  4 +end
... ...
config/initializers/delayed_job_config.rb
1 1 Delayed::Worker.backend = :active_record
2 2 Delayed::Worker.max_attempts = 2
3   -Delayed::Worker.max_run_time = 10.minutes
  3 +
  4 +class Delayed::Worker
  5 + def handle_failed_job_with_loggin(job, error)
  6 + handle_failed_job_without_loggin(job,error)
  7 + Delayed::Worker.logger.error(error.message)
  8 + Delayed::Worker.logger.error(error.backtrace.join("\n"))
  9 + end
  10 + alias_method_chain :handle_failed_job, :loggin
  11 +end
... ...
config/initializers/noosfero_extensions.rb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +require 'noosfero/role_assignment_ext'
  2 +require 'noosfero/action_tracker_ext'
... ...
db/migrate/20140312132212_add_indexes_for_article_search.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +class AddIndexesForArticleSearch < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :articles, :created_at
  4 + add_index :articles, :hits
  5 + add_index :articles, :comments_count
  6 + end
  7 +
  8 + def self.down
  9 + remove_index :articles, :created_at
  10 + remove_index :articles, :hits
  11 + remove_index :articles, :comments_count
  12 + end
  13 +end
... ...
db/migrate/20140312134218_add_indexes_for_profile_search.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class AddIndexesForProfileSearch < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :profiles, :created_at
  4 + end
  5 +
  6 + def self.down
  7 + remove_index :profiles, :created_at
  8 + end
  9 +end
... ...
db/migrate/20140312141805_create_cache_counts_for_profiles.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class CreateCacheCountsForProfiles < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :profiles, :friends_count, :integer, :null => false, :default => 0
  4 + add_column :profiles, :members_count, :integer, :null => false, :default => 0
  5 + add_column :profiles, :activities_count, :integer, :null => false, :default => 0
  6 + add_index :profiles, :friends_count
  7 + add_index :profiles, :members_count
  8 + add_index :profiles, :activities_count
  9 + end
  10 +
  11 + def self.down
  12 + remove_column :profiles, :friends_count
  13 + remove_column :profiles, :members_count
  14 + remove_column :profiles, :activities_count
  15 + remove_index :profiles, :friends_count
  16 + remove_index :profiles, :members_count
  17 + remove_index :profiles, :activities_count
  18 + end
  19 +end
... ...
db/migrate/20140312144156_define_initial_value_for_profiles_friends_count.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class DefineInitialValueForProfilesFriendsCount < ActiveRecord::Migration
  2 + def self.up
  3 + friends_counts = execute("SELECT profiles.id, count(profiles.id) FROM profiles INNER JOIN friendships ON ( profiles.id = friendships.friend_id AND profiles.type = E'Person') GROUP BY profiles.id;")
  4 + friends_counts.each do |count|
  5 + execute("UPDATE profiles SET friends_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + execute("UPDATE profiles SET friends_count=0;")
  11 + end
  12 +end
... ...
db/migrate/20140312151857_define_initial_value_for_profiles_activities_count.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +class DefineInitialValueForProfilesActivitiesCount < ActiveRecord::Migration
  2 + def self.up
  3 + person_activities_counts = execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= '#{30.days.ago.to_s(:db)}') AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;")
  4 + organization_activities_counts = execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= '#{30.days.ago.to_s(:db)}') AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;")
  5 + activities_counts = person_activities_counts.entries + organization_activities_counts.entries
  6 + activities_counts.each do |count|
  7 + execute("UPDATE profiles SET activities_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + execute("UPDATE profiles SET activities_count=0;")
  13 + end
  14 +end
... ...
db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class DefineInitialValueForProfilesMembersCount < ActiveRecord::Migration
  2 + def self.up
  3 + members_counts = execute("SELECT profiles.id, count(profiles.id) FROM profiles LEFT OUTER JOIN role_assignments ON profiles.id = role_assignments.resource_id WHERE (profiles.type = 'Organization' OR profiles.type = 'Community' OR profiles.type = 'Enterprise') GROUP BY profiles.id;")
  4 + members_counts.each do |count|
  5 + execute("UPDATE profiles SET members_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + execute("UPDATE profiles SET members_count=0;")
  11 + end
  12 +end
... ...
db/migrate/20140314200103_add_indexes_for_products_search.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class AddIndexesForProductsSearch < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :products, :created_at
  4 + end
  5 +
  6 + def self.down
  7 + remove_index :products, :created_at
  8 + end
  9 +end
... ...
db/schema.rb
... ... @@ -9,7 +9,7 @@
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11  
12   -ActiveRecord::Schema.define(:version => 20140108132730) do
  12 +ActiveRecord::Schema.define(:version => 20140314200103) do
13 13  
14 14 create_table "abuse_reports", :force => true do |t|
15 15 t.integer "reporter_id"
... ... @@ -140,6 +140,9 @@ ActiveRecord::Schema.define(:version =&gt; 20140108132730) do
140 140 t.integer "position"
141 141 end
142 142  
  143 + add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
  144 + add_index "articles", ["created_at"], :name => "index_articles_on_created_at"
  145 + add_index "articles", ["hits"], :name => "index_articles_on_hits"
143 146 add_index "articles", ["name"], :name => "index_articles_on_name"
144 147 add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id"
145 148 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id"
... ... @@ -429,6 +432,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140108132730) do
429 432 t.integer "image_id"
430 433 end
431 434  
  435 + add_index "products", ["created_at"], :name => "index_products_on_created_at"
432 436 add_index "products", ["enterprise_id"], :name => "index_products_on_enterprise_id"
433 437 add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id"
434 438  
... ... @@ -465,10 +469,17 @@ ActiveRecord::Schema.define(:version =&gt; 20140108132730) do
465 469 t.boolean "is_template", :default => false
466 470 t.integer "template_id"
467 471 t.string "redirection_after_login"
  472 + t.integer "friends_count", :default => 0, :null => false
  473 + t.integer "members_count", :default => 0, :null => false
  474 + t.integer "activities_count", :default => 0, :null => false
468 475 end
469 476  
  477 + add_index "profiles", ["activities_count"], :name => "index_profiles_on_activities_count"
  478 + add_index "profiles", ["created_at"], :name => "index_profiles_on_created_at"
470 479 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id"
  480 + add_index "profiles", ["friends_count"], :name => "index_profiles_on_friends_count"
471 481 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
  482 + add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count"
472 483 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id"
473 484  
474 485 create_table "qualifier_certifiers", :force => true do |t|
... ...
lib/activities_counter_cache_job.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +class ActivitiesCounterCacheJob
  2 + def perform
  3 + person_activities_counts = ActiveRecord::Base.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= '#{ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db)}') AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;")
  4 + organization_activities_counts = ActiveRecord::Base.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= '#{ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db)}') AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;")
  5 + activities_counts = person_activities_counts.entries + organization_activities_counts.entries
  6 + activities_counts.each do |count|
  7 + ActiveRecord::Base.connection.execute("UPDATE profiles SET activities_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  8 + end
  9 + Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, -3, 1.day.from_now)
  10 + end
  11 +end
... ...
lib/noosfero/action_tracker_ext.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +Rails.configuration.to_prepare do
  2 + ActionTracker::Record.module_eval do
  3 + extend CacheCounterHelper
  4 +
  5 + after_create do |record|
  6 + update_cache_counter(:activities_count, record.user, 1)
  7 + if record.target.kind_of?(Organization)
  8 + update_cache_counter(:activities_count, record.target, 1)
  9 + end
  10 + end
  11 +
  12 + after_destroy do |record|
  13 + if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago
  14 + update_cache_counter(:activities_count, record.user, -1)
  15 + if record.target.kind_of?(Organization)
  16 + update_cache_counter(:activities_count, record.target, -1)
  17 + end
  18 + end
  19 + end
  20 + end
  21 +end
... ...
lib/noosfero/role_assignment_ext.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +Rails.configuration.to_prepare do
  2 + RoleAssignment.module_eval do
  3 + extend CacheCounterHelper
  4 +
  5 + after_create do |role_assignment|
  6 + accessor = role_assignment.accessor
  7 + resource = role_assignment.resource
  8 + if resource.kind_of?(Organization)
  9 + #FIXME This will only work as long as the role_assignment associations
  10 + #happen only between profiles, due to the polymorphic column type.
  11 + if resource.role_assignments.where(:accessor_id => accessor.id).count == 1
  12 + update_cache_counter(:members_count, resource, 1)
  13 + end
  14 + end
  15 + end
  16 +
  17 + after_destroy do |role_assignment|
  18 + accessor = role_assignment.accessor
  19 + resource = role_assignment.resource
  20 + if resource.kind_of?(Organization)
  21 + #FIXME This will only work as long as the role_assignment associations
  22 + #happen only between profiles, due to the polymorphic column type.
  23 + if resource.role_assignments.where(:accessor_id => accessor.id).count == 0
  24 + update_cache_counter(:members_count, resource, -1)
  25 + end
  26 + end
  27 + end
  28 + end
  29 +end
... ...
test/functional/invite_controller_test.rb
... ... @@ -230,7 +230,8 @@ class InviteControllerTest &lt; ActionController::TestCase
230 230  
231 231 contact_list = ContactList.create
232 232 post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id
233   - assert_equal 'pt', Delayed::Job.first.payload_object.locale
  233 + job = Delayed::Job.where("handler LIKE '%InvitationJob%'").first
  234 + assert_equal 'pt', job.payload_object.locale
234 235 end
235 236  
236 237 private
... ...
test/functional/profile_controller_test.rb
... ... @@ -766,23 +766,28 @@ class ProfileControllerTest &lt; ActionController::TestCase
766 766 end
767 767  
768 768 should 'see all the activities in the current profile network' do
769   - p1= Person.first
  769 + p1= fast_create(Person)
770 770 p2= fast_create(Person)
771 771 assert !p1.is_a_friend?(p2)
  772 +
772 773 p3= fast_create(Person)
773 774 p3.add_friend(p1)
774 775 assert p3.is_a_friend?(p1)
775   - ActionTracker::Record.destroy_all
  776 +
  777 + ActionTracker::Record.delete_all
  778 +
  779 + UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
776 780 Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))
777 781 a1 = ActionTracker::Record.last
  782 +
778 783 UserStampSweeper.any_instance.stubs(:current_user).returns(p2)
779 784 Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => p3))
780 785 a2 = ActionTracker::Record.last
  786 +
781 787 UserStampSweeper.any_instance.stubs(:current_user).returns(p3)
782 788 Scrap.create!(defaults_for_scrap(:sender => p3, :receiver => p1))
783 789 a3 = ActionTracker::Record.last
784 790  
785   -
786 791 @controller.stubs(:logged_in?).returns(true)
787 792 user = mock()
788 793 user.stubs(:person).returns(p3)
... ... @@ -792,24 +797,29 @@ class ProfileControllerTest &lt; ActionController::TestCase
792 797  
793 798 process_delayed_job_queue
794 799 get :index, :profile => p1.identifier
795   - assert_not_nil assigns(:network_activities)
796   - assert_equal [], [a1,a3] - assigns(:network_activities)
797   - assert_equal assigns(:network_activities) - [a1, a3], []
  800 +
  801 + assert_equivalent [a1,a3].map(&:id), assigns(:network_activities).map(&:id)
798 802 end
799 803  
800 804 should 'the network activity be visible only to profile followers' do
801   - p1= Person.first
  805 + p1= fast_create(Person)
802 806 p2= fast_create(Person)
803 807 assert !p1.is_a_friend?(p2)
  808 +
804 809 p3= fast_create(Person)
805 810 p3.add_friend(p1)
806 811 assert p3.is_a_friend?(p1)
807   - ActionTracker::Record.destroy_all
  812 +
  813 + ActionTracker::Record.delete_all
  814 +
  815 + UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
808 816 Scrap.create!(defaults_for_scrap(:sender => p1, :receiver => p1))
809 817 a1 = ActionTracker::Record.last
  818 +
810 819 UserStampSweeper.any_instance.stubs(:current_user).returns(p2)
811 820 Scrap.create!(defaults_for_scrap(:sender => p2, :receiver => p3))
812 821 a2 = ActionTracker::Record.last
  822 +
813 823 UserStampSweeper.any_instance.stubs(:current_user).returns(p3)
814 824 Scrap.create!(defaults_for_scrap(:sender => p3, :receiver => p1))
815 825 a3 = ActionTracker::Record.last
... ... @@ -819,8 +829,9 @@ class ProfileControllerTest &lt; ActionController::TestCase
819 829 user.stubs(:person).returns(p2)
820 830 user.stubs(:login).returns('some')
821 831 @controller.stubs(:current_user).returns(user)
  832 +
822 833 get :index, :profile => p1.identifier
823   - assert_equal [], assigns(:network_activities)
  834 + assert assigns(:network_activities).blank?
824 835  
825 836 user = mock()
826 837 user.stubs(:person).returns(p3)
... ... @@ -828,9 +839,9 @@ class ProfileControllerTest &lt; ActionController::TestCase
828 839 @controller.stubs(:current_user).returns(user)
829 840 Person.any_instance.stubs(:follows?).returns(true)
830 841 process_delayed_job_queue
  842 +
831 843 get :index, :profile => p3.identifier
832   - assert_equal [], [a1,a3] - assigns(:network_activities)
833   - assert_equal assigns(:network_activities) - [a1, a3], []
  844 + assert_equivalent [a1,a3], assigns(:network_activities)
834 845 end
835 846  
836 847 should 'the network activity be paginated' do
... ...
test/functional/search_controller_test.rb
... ... @@ -549,9 +549,9 @@ class SearchControllerTest &lt; ActionController::TestCase
549 549 c2 = create(Community, :name => 'Testing community 2')
550 550 c3 = create(Community, :name => 'Testing community 3')
551 551 ActionTracker::Record.delete_all
552   - fast_create(ActionTracker::Record, :target_id => c1, :user_type => 'Profile', :user_id => person, :created_at => Time.now)
553   - fast_create(ActionTracker::Record, :target_id => c2, :user_type => 'Profile', :user_id => person, :created_at => Time.now)
554   - fast_create(ActionTracker::Record, :target_id => c2, :user_type => 'Profile', :user_id => person, :created_at => Time.now)
  552 + ActionTracker::Record.create!(:target => c1, :user => person, :created_at => Time.now, :verb => 'leave_scrap')
  553 + ActionTracker::Record.create!(:target => c2, :user => person, :created_at => Time.now, :verb => 'leave_scrap')
  554 + ActionTracker::Record.create!(:target => c2, :user => person, :created_at => Time.now, :verb => 'leave_scrap')
555 555 get :communities, :filter => 'more_active'
556 556 assert_equal [c2,c1,c3] , assigns(:searches)[:communities][:results]
557 557 end
... ...
test/test_helper.rb
... ... @@ -183,7 +183,7 @@ class ActiveSupport::TestCase
183 183 if reference.first == value
184 184 reference.shift
185 185 else
186   - assert false, "'#{value}' was found before it should be on: #{original.inspect}"
  186 + assert false, "'#{value.inspect}' was found before it should be on: #{original.inspect}"
187 187 end
188 188 end
189 189 end
... ...
test/unit/action_tracker_ext_test.rb 0 → 100644
... ... @@ -0,0 +1,64 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class ActionTrackerExtTest < ActiveSupport::TestCase
  4 + should 'increase person activities_count on new activity' do
  5 + person = fast_create(Person)
  6 + assert_difference person, :activities_count, 1 do
  7 + ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
  8 + person.reload
  9 + end
  10 + end
  11 +
  12 + should 'decrease person activities_count on activity removal' do
  13 + person = fast_create(Person)
  14 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
  15 + person.reload
  16 + assert_difference person, :activities_count, -1 do
  17 + record.destroy
  18 + person.reload
  19 + end
  20 + end
  21 +
  22 + should 'not decrease person activities_count on activity removal after the recent delay' do
  23 + person = fast_create(Person)
  24 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
  25 + record.created_at = record.created_at - ActionTracker::Record::RECENT_DELAY.days - 1.day
  26 + record.save!
  27 + person.reload
  28 + assert_no_difference person, :activities_count do
  29 + record.destroy
  30 + person.reload
  31 + end
  32 + end
  33 +
  34 + should 'increase organization activities_count on new activity' do
  35 + person = fast_create(Person)
  36 + organization = fast_create(Organization)
  37 + assert_difference organization, :activities_count, 1 do
  38 + ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization
  39 + organization.reload
  40 + end
  41 + end
  42 +
  43 + should 'decrease organization activities_count on activity removal' do
  44 + person = fast_create(Person)
  45 + organization = fast_create(Organization)
  46 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization
  47 + organization.reload
  48 + assert_difference organization, :activities_count, -1 do
  49 + record.destroy
  50 + organization.reload
  51 + end
  52 + end
  53 +
  54 + should 'not decrease organization activities_count on activity removal after the recent delay' do
  55 + person = fast_create(Person)
  56 + organization = fast_create(Organization)
  57 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization, :created_at => (ActionTracker::Record::RECENT_DELAY + 1).days.ago
  58 + organization.reload
  59 + assert_no_difference organization, :activities_count do
  60 + record.destroy
  61 + organization.reload
  62 + end
  63 + end
  64 +end
... ...
test/unit/activities_counter_cache_job_test.rb 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class ActivitiesCounterCacheJobTest < ActiveSupport::TestCase
  4 +
  5 + should 'correctly update the person activities counter cache' do
  6 + person = create_user('person').person
  7 + ActionTracker::Record.create!(:user => person, :verb => 'create_article')
  8 + ActionTracker::Record.create!(:user => person, :verb => 'create_article')
  9 + person.reload
  10 + assert_equal 2, person.activities_count
  11 +
  12 + person.activities_count = 0
  13 + person.save!
  14 + job = ActivitiesCounterCacheJob.new
  15 + job.perform
  16 + person.reload
  17 + assert_equal 2, person.activities_count
  18 + end
  19 +
  20 + should 'correctly update the organization activities counter cache' do
  21 + person = create_user('person').person
  22 + organization = Organization.create!(:name => 'Organization1', :identifier => 'organization1')
  23 + ActionTracker::Record.create!(:user => person, :verb => 'create_article', :target => organization)
  24 + ActionTracker::Record.create!(:user => person, :verb => 'create_article', :target => organization)
  25 + organization.reload
  26 + assert_equal 2, organization.activities_count
  27 +
  28 + organization.activities_count = 0
  29 + organization.save!
  30 + job = ActivitiesCounterCacheJob.new
  31 + job.perform
  32 + organization.reload
  33 + assert_equal 2, organization.activities_count
  34 + end
  35 +
  36 +end
... ...
test/unit/article_test.rb
... ... @@ -1625,10 +1625,10 @@ class ArticleTest &lt; ActiveSupport::TestCase
1625 1625  
1626 1626 should 'not allow all community members to edit by default' do
1627 1627 community = fast_create(Community)
1628   - admin = create_user('community-admin').person
1629   - member = create_user.person
1630   -
  1628 + admin = fast_create(Person)
  1629 + member = fast_create(Person)
1631 1630 community.add_admin(admin)
  1631 + community.reload
1632 1632 community.add_member(member)
1633 1633 a = Article.new(:profile => community)
1634 1634  
... ...
test/unit/community_test.rb
... ... @@ -213,8 +213,8 @@ class CommunityTest &lt; ActiveSupport::TestCase
213 213 community = fast_create(Community)
214 214 community.closed = true
215 215 community.save
216   -
217 216 community.add_member(fast_create(Person))
  217 + community.reload
218 218  
219 219 assert_difference AddMember, :count do
220 220 community.add_member(person)
... ...
test/unit/enterprise_test.rb
... ... @@ -99,6 +99,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
99 99 enterprise = fast_create(Enterprise)
100 100 member = fast_create(Person)
101 101 enterprise.add_member(member)
  102 + enterprise.reload
102 103  
103 104 person = fast_create(Person)
104 105 enterprise.add_member(person)
... ...
test/unit/organization_mailing_test.rb
... ... @@ -62,18 +62,21 @@ class OrganizationMailingTest &lt; ActiveSupport::TestCase
62 62  
63 63 should 'deliver mailing to each member after create' do
64 64 mailing = OrganizationMailing.create(:source => community, :subject => 'Hello', :body => 'We have some news', :person => person)
  65 + community.reload
65 66 process_delayed_job_queue
66 67 assert_equal 2, ActionMailer::Base.deliveries.count
67 68 end
68 69  
69 70 should 'deliver mailing when there are many mailings created' do
70 71 50.times { OrganizationMailing.create(:source => community, :subject => 'Hello', :body => 'We have some news', :person => person) }
  72 + community.reload
71 73 process_delayed_job_queue
72 74 assert_equal 50*community.members_count, ActionMailer::Base.deliveries.count
73 75 end
74 76  
75 77 should 'create mailing sent to each recipient after delivering mailing' do
76 78 mailing = OrganizationMailing.create(:source => community, :subject => 'Hello', :body => 'We have some news', :person => person)
  79 + community.reload
77 80 assert_difference MailingSent, :count, 2 do
78 81 process_delayed_job_queue
79 82 end
... ...
test/unit/organization_test.rb
... ... @@ -302,18 +302,17 @@ class OrganizationTest &lt; ActiveSupport::TestCase
302 302 end
303 303  
304 304 should 'find more popular organizations' do
305   - Organization.delete_all
306 305 o1 = fast_create(Organization)
307 306 o2 = fast_create(Organization)
308 307  
309 308 p1 = fast_create(Person)
310 309 p2 = fast_create(Person)
311 310 o1.add_member(p1)
312   - assert_equal [o1,o2] , Organization.more_popular
  311 + assert_order [o1,o2] , Organization.more_popular
313 312  
314 313 o2.add_member(p1)
315 314 o2.add_member(p2)
316   - assert_equal [o2,o1] , Organization.more_popular
  315 + assert_order [o2,o1] , Organization.more_popular
317 316 end
318 317  
319 318 should 'list organizations that have no members in more popular list' do
... ... @@ -331,6 +330,7 @@ class OrganizationTest &lt; ActiveSupport::TestCase
331 330 person = fast_create(Person)
332 331 organization = fast_create(Organization)
333 332 organization.add_member(person)
  333 + organization.reload
334 334  
335 335 assert_equal "one member", organization.more_popular_label
336 336 end
... ... @@ -342,47 +342,30 @@ class OrganizationTest &lt; ActiveSupport::TestCase
342 342  
343 343 organization.add_member(person1)
344 344 organization.add_member(person2)
  345 + organization.reload
345 346 assert_equal "2 members", organization.more_popular_label
346 347  
347 348 person3 = fast_create(Person)
348 349 organization.add_member(person3)
  350 + organization.reload
349 351 assert_equal "3 members", organization.more_popular_label
350 352 end
351 353  
352 354 should 'find more active organizations' do
353 355 person = fast_create(Person)
354   - Organization.destroy_all
355 356 p1 = fast_create(Organization)
356 357 p2 = fast_create(Organization)
357 358 p3 = fast_create(Organization)
358 359  
359 360 ActionTracker::Record.destroy_all
360   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p1.id)
361   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p2.id)
362   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p2.id)
363   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p3.id)
364   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p3.id)
365   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p3.id)
  361 + ActionTracker::Record.create!(:user => person, :target => p1, :verb => 'leave_scrap')
  362 + ActionTracker::Record.create!(:user => person, :target => p2, :verb => 'leave_scrap')
  363 + ActionTracker::Record.create!(:user => person, :target => p2, :verb => 'leave_scrap')
  364 + ActionTracker::Record.create!(:user => person, :target => p3, :verb => 'leave_scrap')
  365 + ActionTracker::Record.create!(:user => person, :target => p3, :verb => 'leave_scrap')
  366 + ActionTracker::Record.create!(:user => person, :target => p3, :verb => 'leave_scrap')
366 367  
367   - assert_equal [p3,p2,p1] , Organization.more_active
368   - end
369   -
370   - should 'more active profile take in consideration only actions created only in the recent delay interval' do
371   - ActionTracker::Record.destroy_all
372   - recent_delay = ActionTracker::Record::RECENT_DELAY.days.ago
373   -
374   - person = fast_create(Person)
375   - Organization.destroy_all
376   - p1 = fast_create(Organization)
377   - p2 = fast_create(Organization)
378   -
379   - ActionTracker::Record.destroy_all
380   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay, :target_id => p1.id)
381   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay, :target_id => p1.id)
382   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay, :target_id => p2.id)
383   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay - 1.day, :target_id => p2.id)
384   -
385   - assert_equal [p1,p2] , Organization.more_active
  368 + assert_order [p3,p2,p1] , Organization.more_active
386 369 end
387 370  
388 371 should 'list profiles that have no actions in more active list' do
... ... @@ -422,4 +405,24 @@ class OrganizationTest &lt; ActiveSupport::TestCase
422 405 assert !organization.visible
423 406 end
424 407  
  408 + should 'increase members_count on new membership' do
  409 + member = fast_create(Person)
  410 + organization = fast_create(Organization)
  411 + assert_difference organization, :members_count, 1 do
  412 + organization.add_member(member)
  413 + organization.reload
  414 + end
  415 + end
  416 +
  417 + should 'decrease members_count on membership removal' do
  418 + member = fast_create(Person)
  419 + organization = fast_create(Organization)
  420 + organization.add_member(member)
  421 + organization.reload
  422 + assert_difference organization, :members_count, -1 do
  423 + organization.remove_member(member)
  424 + organization.reload
  425 + end
  426 + end
  427 +
425 428 end
... ...
test/unit/person_test.rb
... ... @@ -404,15 +404,14 @@ class PersonTest &lt; ActiveSupport::TestCase
404 404  
405 405 should 'not allow simple member to view group pending tasks' do
406 406 community = fast_create(Community)
  407 + admin = fast_create(Person)
  408 + community.add_member(admin)
407 409 member = fast_create(Person)
  410 + community.reload
408 411 community.add_member(member)
409   -
410 412 community.tasks << Task.new
411 413  
412   - person = fast_create(Person)
413   - community.add_member(person)
414   -
415   - assert_not_includes Person.with_pending_tasks, person
  414 + assert_not_includes Person.with_pending_tasks, member
416 415 end
417 416  
418 417 should 'person has organization pending tasks' do
... ... @@ -642,16 +641,18 @@ class PersonTest &lt; ActiveSupport::TestCase
642 641 end
643 642  
644 643 should 'find more popular people' do
  644 + extend CacheCounterHelper
  645 +
645 646 Person.delete_all
646 647 p1 = fast_create(Person)
647 648 p2 = fast_create(Person)
648 649 p3 = fast_create(Person)
649 650  
650   - p1.add_friend(p2)
651   - p2.add_friend(p1)
652   - p2.add_friend(p3)
653   - assert_equal p2, Person.more_popular[0]
654   - assert_equal p1, Person.more_popular[1]
  651 + update_cache_counter(:friends_count, p1, 1)
  652 + update_cache_counter(:friends_count, p2, 2)
  653 + update_cache_counter(:friends_count, p3, 3)
  654 +
  655 + assert_order [p3, p2, p1], Person.more_popular
655 656 end
656 657  
657 658 should 'list people that have no friends in more popular list' do
... ... @@ -891,6 +892,7 @@ class PersonTest &lt; ActiveSupport::TestCase
891 892 p1 = fast_create(Person)
892 893 p2 = fast_create(Person)
893 894 p3 = fast_create(Person)
  895 + p4 = fast_create(Person)
894 896  
895 897 community.add_member(p1)
896 898 assert p1.is_member_of?(community)
... ... @@ -901,14 +903,15 @@ class PersonTest &lt; ActiveSupport::TestCase
901 903  
902 904 action_tracker = fast_create(ActionTracker::Record, :verb => 'create_article')
903 905 action_tracker.target = community
  906 + action_tracker.user = p4
904 907 action_tracker.save!
905 908 ActionTrackerNotification.delete_all
906   - assert_difference(ActionTrackerNotification, :count, 3) do
  909 + assert_difference(ActionTrackerNotification, :count, 4) do
907 910 Person.notify_activity(action_tracker)
908 911 process_delayed_job_queue
909 912 end
910 913 ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|
911   - assert [community,p1,p3].include?(profile)
  914 + assert [community,p1,p3,p4].include?(profile)
912 915 end
913 916 end
914 917  
... ... @@ -1011,9 +1014,9 @@ class PersonTest &lt; ActiveSupport::TestCase
1011 1014  
1012 1015 should 'the community specific notification created when a member joins community could not be propagated to members' do
1013 1016 ActionTracker::Record.delete_all
1014   - p1 = create_user('test_user').person
1015   - p2 = create_user('test_user').person
1016   - p3 = create_user('test_user').person
  1017 + p1 = create_user('p1').person
  1018 + p2 = create_user('p2').person
  1019 + p3 = create_user('p3').person
1017 1020 c = fast_create(Community, :name => "Foo")
1018 1021 c.add_member(p1)
1019 1022 process_delayed_job_queue
... ... @@ -1133,30 +1136,14 @@ class PersonTest &lt; ActiveSupport::TestCase
1133 1136 p3 = fast_create(Person)
1134 1137  
1135 1138 ActionTracker::Record.destroy_all
1136   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p1, :created_at => Time.now)
1137   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => Time.now)
1138   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => Time.now)
1139   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p3, :created_at => Time.now)
1140   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p3, :created_at => Time.now)
1141   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p3, :created_at => Time.now)
1142   -
1143   - assert_equal [p3,p2,p1] , Person.more_active
1144   - end
1145   -
1146   - should 'more active profile take in consideration only actions created only in the recent delay interval' do
1147   - Person.delete_all
1148   - ActionTracker::Record.destroy_all
1149   - recent_delay = ActionTracker::Record::RECENT_DELAY.days.ago
  1139 + ActionTracker::Record.create!(:user => p1, :verb => 'leave_scrap')
  1140 + ActionTracker::Record.create!(:user => p2, :verb => 'leave_scrap')
  1141 + ActionTracker::Record.create!(:user => p2, :verb => 'leave_scrap')
  1142 + ActionTracker::Record.create!(:user => p3, :verb => 'leave_scrap')
  1143 + ActionTracker::Record.create!(:user => p3, :verb => 'leave_scrap')
  1144 + ActionTracker::Record.create!(:user => p3, :verb => 'leave_scrap')
1150 1145  
1151   - p1 = fast_create(Person)
1152   - p2 = fast_create(Person)
1153   -
1154   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p1, :created_at => recent_delay)
1155   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p1, :created_at => recent_delay)
1156   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => recent_delay)
1157   - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => recent_delay - 1.day)
1158   -
1159   - assert_equal [p1,p2], Person.more_active
  1146 + assert_order [p3,p2,p1] , Person.more_active
1160 1147 end
1161 1148  
1162 1149 should 'list profiles that have no actions in more active list' do
... ... @@ -1363,7 +1350,7 @@ class PersonTest &lt; ActiveSupport::TestCase
1363 1350 u = create_user('user'+i.to_s)
1364 1351 u.deactivate
1365 1352 }
1366   - assert_equal activated, Person.activated
  1353 + assert_equivalent activated, Person.activated
1367 1354 end
1368 1355  
1369 1356 should 'deactivated named_scope return persons who are deactivated users' do
... ... @@ -1379,7 +1366,7 @@ class PersonTest &lt; ActiveSupport::TestCase
1379 1366 u = create_user('user'+i.to_s)
1380 1367 u.activate
1381 1368 }
1382   - assert_equal deactivated, Person.deactivated
  1369 + assert_equivalent deactivated, Person.deactivated
1383 1370 end
1384 1371  
1385 1372 should 'be able to retrieve memberships by role person has' do
... ... @@ -1413,4 +1400,31 @@ class PersonTest &lt; ActiveSupport::TestCase
1413 1400 person.reload
1414 1401 assert_equal person.activities, []
1415 1402 end
  1403 +
  1404 + should 'increase friends_count on new friendship' do
  1405 + person = create_user('person').person
  1406 + friend = create_user('friend').person
  1407 + assert_difference person, :friends_count, 1 do
  1408 + assert_difference friend, :friends_count, 1 do
  1409 + person.add_friend(friend)
  1410 + friend.reload
  1411 + end
  1412 + person.reload
  1413 + end
  1414 + end
  1415 +
  1416 + should 'decrease friends_count on friendship removal' do
  1417 + person = create_user('person').person
  1418 + friend = create_user('friend').person
  1419 + person.add_friend(friend)
  1420 + friend.reload
  1421 + person.reload
  1422 + assert_difference person, :friends_count, -1 do
  1423 + assert_difference friend, :friends_count, -1 do
  1424 + person.remove_friend(friend)
  1425 + friend.reload
  1426 + end
  1427 + person.reload
  1428 + end
  1429 + end
1416 1430 end
... ...
test/unit/profile_test.rb
... ... @@ -1688,6 +1688,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1688 1688 person = fast_create(Person)
1689 1689 community = fast_create(Community)
1690 1690 community.add_member(person)
  1691 + community.reload
1691 1692  
1692 1693 assert_equal 1, community.members_count
1693 1694 end
... ... @@ -1801,11 +1802,12 @@ class ProfileTest &lt; ActiveSupport::TestCase
1801 1802 original_community.add_member(original_member)
1802 1803 community1.add_member(plugin1_member)
1803 1804 community2.add_member(plugin2_member)
  1805 + original_community.reload
1804 1806  
1805 1807 assert_includes original_community.members, original_member
1806 1808 assert_includes original_community.members, plugin1_member
1807 1809 assert_includes original_community.members, plugin2_member
1808   - assert 3, original_community.members.count
  1810 + assert 3, original_community.members_count
1809 1811 end
1810 1812  
1811 1813 private
... ...
test/unit/role_assignment_ext_test.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class RoleAssignmentExtTest < ActiveSupport::TestCase
  4 + should 'increase organization members_count only on the first role_assignment' do
  5 + role1 = Role.create!(:name => 'role1')
  6 + role2 = Role.create!(:name => 'role2')
  7 + member = create_user('person').person
  8 + organization = Organization.create!(:name => 'Organization', :identifier => 'organization')
  9 + assert_difference organization, :members_count, 1 do
  10 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1)
  11 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2)
  12 + organization.reload
  13 + end
  14 + end
  15 +
  16 + should 'decrease organization members_count only on the last role_assignment' do
  17 + role1 = Role.create!(:name => 'role1')
  18 + role2 = Role.create!(:name => 'role2')
  19 + member = create_user('person').person
  20 + organization = Organization.create!(:name => 'Organization', :identifier => 'organization')
  21 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1)
  22 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2)
  23 + organization.reload
  24 + assert_difference organization, :members_count, -1 do
  25 + organization.role_assignments.destroy_all
  26 + organization.reload
  27 + end
  28 + end
  29 +end
... ...
test/unit/uploaded_file_test.rb
... ... @@ -316,12 +316,13 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
316 316  
317 317 should 'group trackers activity of image\'s upload' do
318 318 gallery = fast_create(Gallery, :profile_id => profile.id)
319   -
  319 + count = ActionTracker::Record.find_all_by_verb('upload_image').count
320 320 image1 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => profile)
321   - assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count
  321 + count += 1
  322 + assert_equal count, ActionTracker::Record.find_all_by_verb('upload_image').count
322 323  
323 324 image2 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/other-pic.jpg', 'image/jpg'), :parent => gallery, :profile => profile)
324   - assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count
  325 + assert_equal count, ActionTracker::Record.find_all_by_verb('upload_image').count
325 326 end
326 327  
327 328 {
... ...
vendor/plugins/action_tracker/lib/action_tracker_model.rb
1 1 module ActionTracker
2 2 class Record < ActiveRecord::Base
3   -
4 3 set_table_name 'action_tracker'
5 4  
6 5 belongs_to :user, :polymorphic => true
... ...