[Git][noosfero/noosfero][master] 2 commits: profile-activities: Fix pagination on SQL and eager load activities

Bráulio Bhavamitra gitlab at gitlab.com
Tue Aug 11 21:23:23 BRT 2015


Bráulio Bhavamitra pushed to branch master at Noosfero / noosfero


Commits:
4e0ad2ae by Braulio Bhavamitra at 2015-08-11T20:49:50Z
profile-activities: Fix pagination on SQL and eager load activities

All scraps and action trackers from profile were loaded at once as
will_paginate can't change SQL when find_by_sql is used.
Also, eager load activities to make it O(3) instead of O(n).

This increases performance by ~30% on profiles with lots of
scraps/action trackers.

- - - - -
16f70434 by Braulio Bhavamitra at 2015-08-11T21:22:58Z
Merge branch 'profile-activities' into noosfero

- - - - -


20 changed files:

- app/mailers/scrap_notifier.rb
- app/models/community.rb
- app/models/enterprise.rb
- app/models/person.rb
- app/models/profile.rb
- + app/models/profile_activity.rb
- app/models/scrap.rb
- app/views/profile/_profile_activities_list.html.erb
- + db/migrate/20150216213259_create_profile_activity.rb
- db/schema.rb
- lib/noosfero/action_tracker_ext.rb
- test/functional/profile_controller_test.rb
- test/unit/action_tracker_ext_test.rb
- test/unit/community_test.rb
- test/unit/enterprise_test.rb
- test/unit/person_notifier_test.rb
- test/unit/person_test.rb
- + test/unit/profile_activity_test.rb
- test/unit/scrap_notifier_test.rb
- test/unit/scrap_test.rb


Changes:

=====================================
app/mailers/scrap_notifier.rb
=====================================
--- a/app/mailers/scrap_notifier.rb
+++ b/app/mailers/scrap_notifier.rb
@@ -1,6 +1,9 @@
 class ScrapNotifier < ActionMailer::Base
   def notification(scrap)
     sender, receiver = scrap.sender, scrap.receiver
+    # for tests
+    return unless receiver.email
+
     @recipient = receiver.name
     @sender = sender.name
     @sender_link = sender.url


=====================================
app/models/community.rb
=====================================
--- a/app/models/community.rb
+++ b/app/models/community.rb
@@ -86,8 +86,8 @@ class Community < Organization
     {:title => _('Community Info and settings'), :icon => 'edit-profile-group'}
   end
 
-  def activities
-    Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.target_id = #{self.id} and action_tracker.verb != 'join_community' and action_tracker.verb != 'leave_scrap' UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC")
+  def exclude_verbs_on_activities
+    %w[join_community leave_scrap]
   end
 
 end


=====================================
app/models/enterprise.rb
=====================================
--- a/app/models/enterprise.rb
+++ b/app/models/enterprise.rb
@@ -194,10 +194,6 @@ class Enterprise < Organization
     true
   end
 
-  def activities
-    Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY updated_at DESC")
-  end
-
   def catalog_url
     { :profile => identifier, :controller => 'catalog'}
   end


=====================================
app/models/person.rb
=====================================
--- a/app/models/person.rb
+++ b/app/models/person.rb
@@ -496,8 +496,8 @@ roles] }
     user.save!
   end
 
-  def activities
-    Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' and action_tracker.verb != 'reply_scrap_on_self' ORDER BY updated_at DESC")
+  def exclude_verbs_on_activities
+    %w[leave_scrap_to_self add_member_in_community reply_scrap_on_self]
   end
 
   # by default, all fields are private


=====================================
app/models/profile.rb
=====================================
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -146,6 +146,7 @@ class Profile < ActiveRecord::Base
 
   acts_as_trackable :dependent => :destroy
 
+  has_many :profile_activities
   has_many :action_tracker_notifications, :foreign_key => 'profile_id'
   has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC'
   has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy
@@ -976,9 +977,13 @@ private :generate_url, :url_options
     name
   end
 
-  # Override in your subclasses
+  def exclude_verbs_on_activities
+    %w[]
+  end
+
+  # Customize in subclasses
   def activities
-    []
+    self.profile_activities.includes(:activity).order('updated_at DESC')
   end
 
   def may_display_field_to? field, user = nil


=====================================
app/models/profile_activity.rb
=====================================
--- /dev/null
+++ b/app/models/profile_activity.rb
@@ -0,0 +1,31 @@
+class ProfileActivity < ActiveRecord::Base
+
+  self.record_timestamps = false
+
+  attr_accessible :profile_id,
+    :profile, :activity
+
+  belongs_to :profile
+  belongs_to :activity, polymorphic: true
+
+  # non polymorphic versions
+  belongs_to :scrap, foreign_key: :activity_id, class_name: 'Scrap', conditions: {profile_activities: {activity_type: 'Scrap'}}
+  belongs_to :action_tracker, foreign_key: :activity_id, class_name: 'ActionTracker::Record', conditions: {profile_activities: {activity_type: 'ActionTracker::Record'}}
+
+  before_validation :copy_timestamps
+
+  def self.update_activity activity
+    profile_activity = ProfileActivity.where(activity_id: activity.id, activity_type: activity.class.base_class.name).first
+    profile_activity.send :copy_timestamps
+    profile_activity.save!
+    profile_activity
+  end
+
+  protected
+
+  def copy_timestamps
+    self.created_at = self.activity.created_at
+    self.updated_at = self.activity.updated_at
+  end
+
+end


=====================================
app/models/scrap.rb
=====================================
--- a/app/models/scrap.rb
+++ b/app/models/scrap.rb
@@ -13,6 +13,11 @@ class Scrap < ActiveRecord::Base
   has_many :replies, :class_name => 'Scrap', :foreign_key => 'scrap_id', :dependent => :destroy
   belongs_to :root, :class_name => 'Scrap', :foreign_key => 'scrap_id'
 
+  has_many :profile_activities, foreign_key: :activity_id, conditions: {profile_activities: {activity_type: 'Scrap'}}, dependent: :destroy
+
+  after_create :create_activity
+  after_update :update_activity
+
   scope :all_scraps, lambda {|profile| {:conditions => ["receiver_id = ? OR sender_id = ?", profile, profile], :limit => 30}}
 
   scope :not_replies, :conditions => {:scrap_id => nil}
@@ -23,10 +28,7 @@ class Scrap < ActiveRecord::Base
 
   track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver}
 
-  after_create do |scrap|
-    scrap.root.update_attribute('updated_at', DateTime.now) unless scrap.root.nil?
-    ScrapNotifier.notification(scrap).deliver if scrap.send_notification?
-  end
+  after_create :send_notification
 
   before_validation :strip_all_html_tags
 
@@ -57,4 +59,21 @@ class Scrap < ActiveRecord::Base
     sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?)
   end
 
+  protected
+
+  def create_activity
+    # do not scrap replies (when scrap_id is not nil)
+    return if self.scrap_id.present?
+    ProfileActivity.create! profile_id: self.receiver_id, activity: self
+  end
+
+  def update_activity
+    ProfileActivity.update_activity self
+  end
+
+  def send_notification
+    self.root.update_attribute('updated_at', DateTime.now) unless self.root.nil?
+    ScrapNotifier.notification(self).deliver if self.send_notification?
+  end
+
 end


=====================================
app/views/profile/_profile_activities_list.html.erb
=====================================
--- a/app/views/profile/_profile_activities_list.html.erb
+++ b/app/views/profile/_profile_activities_list.html.erb
@@ -1,6 +1,6 @@
 <% unless activities.nil? %>
-  <% activities.each do |a| %>
-    <% activity = a.klass.constantize.find(a.id) %>
+  <% activities.each do |profile_activity| %>
+    <% activity = profile_activity.activity %>
     <% if activity.kind_of?(ActionTracker::Record) %>
       <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %>
     <% else %>


=====================================
db/migrate/20150216213259_create_profile_activity.rb
=====================================
--- /dev/null
+++ b/db/migrate/20150216213259_create_profile_activity.rb
@@ -0,0 +1,26 @@
+class CreateProfileActivity < ActiveRecord::Migration
+  def up
+    ActiveRecord::Base.transaction do
+      create_table :profile_activities do |t|
+        t.integer :profile_id
+        t.integer :activity_id
+        t.string :activity_type
+        t.timestamps
+      end
+      add_index :profile_activities, :profile_id
+      add_index :profile_activities, [:activity_id, :activity_type]
+      add_index :profile_activities, :activity_type
+
+      Scrap.find_each batch_size: 50 do |scrap|
+        scrap.send :create_activity
+      end
+      ActionTracker::Record.find_each batch_size: 50 do |action_tracker|
+        action_tracker.send :create_activity
+      end
+    end
+  end
+
+  def down
+    drop_table :profile_activities
+  end
+end


=====================================
db/schema.rb
=====================================
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20150625234824) do
+ActiveRecord::Schema.define(:version => 20150712130827) do
 
   create_table "abuse_reports", :force => true do |t|
     t.integer  "reporter_id"
@@ -489,6 +489,18 @@ ActiveRecord::Schema.define(:version => 20150625234824) do
   add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id"
   add_index "products", ["profile_id"], :name => "index_products_on_profile_id"
 
+  create_table "profile_activities", :force => true do |t|
+    t.integer  "profile_id"
+    t.integer  "activity_id"
+    t.string   "activity_type"
+    t.datetime "created_at",    :null => false
+    t.datetime "updated_at",    :null => false
+  end
+
+  add_index "profile_activities", ["activity_id", "activity_type"], :name => "index_profile_activities_on_activity_id_and_activity_type"
+  add_index "profile_activities", ["activity_type"], :name => "index_profile_activities_on_activity_type"
+  add_index "profile_activities", ["profile_id"], :name => "index_profile_activities_on_profile_id"
+
   create_table "profile_suggestions", :force => true do |t|
     t.integer  "person_id"
     t.integer  "suggestion_id"
@@ -555,6 +567,8 @@ ActiveRecord::Schema.define(:version => 20150625234824) do
   add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
   add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count"
   add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id"
+  add_index "profiles", ["user_id", "type"], :name => "index_profiles_on_user_id_and_type"
+  add_index "profiles", ["user_id"], :name => "index_profiles_on_user_id"
 
   create_table "qualifier_certifiers", :force => true do |t|
     t.integer "qualifier_id"


=====================================
lib/noosfero/action_tracker_ext.rb
=====================================
--- a/lib/noosfero/action_tracker_ext.rb
+++ b/lib/noosfero/action_tracker_ext.rb
@@ -1,5 +1,5 @@
 Rails.configuration.to_prepare do
-  ActionTracker::Record.module_eval do
+  ActionTracker::Record.class_eval do
     extend CacheCounterHelper
 
     after_create do |record|
@@ -9,6 +9,11 @@ Rails.configuration.to_prepare do
       end
     end
 
+    has_many :profile_activities, foreign_key: :activity_id, conditions: {profile_activities: {activity_type: 'ActionTracker::Record'}}, dependent: :destroy
+
+    after_create :create_activity
+    after_update :update_activity
+
     after_destroy do |record|
       if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago
         ActionTracker::Record.update_cache_counter(:activities_count, record.user, -1)
@@ -17,5 +22,17 @@ Rails.configuration.to_prepare do
         end
       end
     end
+
+    protected
+
+    def create_activity
+      target = if self.target.is_a? Profile then self.target else self.target.profile rescue self.user end
+      return if self.verb.in? target.exclude_verbs_on_activities
+      ProfileActivity.create! profile: target, activity: self
+    end
+    def update_activity
+      ProfileActivity.update_activity self
+    end
+
   end
 end


=====================================
test/functional/profile_controller_test.rb
=====================================
--- a/test/functional/profile_controller_test.rb
+++ b/test/functional/profile_controller_test.rb
@@ -724,7 +724,7 @@ class ProfileControllerTest < ActionController::TestCase
     40.times{create(Scrap, defaults_for_scrap(:sender => p1, :receiver => p1))}
     login_as(p1.identifier)
     get :index, :profile => p1.identifier
-    assert_equal 15, assigns(:activities).count
+    assert_equal 15, assigns(:activities).size
   end
 
   should 'not see the friends activities in the current profile' do
@@ -747,7 +747,7 @@ class ProfileControllerTest < ActionController::TestCase
     login_as(profile.identifier)
     get :index, :profile => p3.identifier
     assert_not_nil assigns(:activities)
-    assert_equivalent [scrap1, article1.activity], assigns(:activities).map { |a| a.klass.constantize.find(a.id) }
+    assert_equivalent [scrap1, article1.activity], assigns(:activities).map(&:activity)
   end
 
   should 'see all the activities in the current profile network' do
@@ -759,18 +759,17 @@ class ProfileControllerTest < ActionController::TestCase
     p3.add_friend(p1)
     p1.add_friend(p3)
 
-    ActionTracker::Record.delete_all
+    ActionTracker::Record.destroy_all
 
     User.current = p1.user
-    create(Scrap,defaults_for_scrap(:sender => p1, :receiver => p1))
+    create(Scrap, sender: p1, receiver: p1)
     a1 = ActionTracker::Record.last
 
     User.current = p2.user
-    create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3))
-    a2 = ActionTracker::Record.last
+    create(Scrap, sender: p2, receiver: p3)
 
     User.current = p3.user
-    create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1))
+    create(Scrap, sender: p3, receiver: p1)
     a3 = ActionTracker::Record.last
 
     process_delayed_job_queue
@@ -933,9 +932,9 @@ class ProfileControllerTest < ActionController::TestCase
     p1 = fast_create(Person)
     p2 = fast_create(Person)
     p3 = fast_create(Person)
-    s1 = fast_create(Scrap, :sender_id => p1.id, :receiver_id => p2.id)
-    s2 = fast_create(Scrap, :sender_id => p2.id, :receiver_id => p1.id)
-    s3 = fast_create(Scrap, :sender_id => p3.id, :receiver_id => p1.id)
+    s1 = create(Scrap, :sender_id => p1.id, :receiver_id => p2.id)
+    s2 = create(Scrap, :sender_id => p2.id, :receiver_id => p1.id)
+    s3 = create(Scrap, :sender_id => p3.id, :receiver_id => p1.id)
 
     @controller.stubs(:logged_in?).returns(true)
     user = mock()
@@ -944,7 +943,7 @@ class ProfileControllerTest < ActionController::TestCase
     @controller.stubs(:current_user).returns(user)
     Person.any_instance.stubs(:follows?).returns(true)
     get :index, :profile => p1.identifier
-    assert_equal [s2,s3], assigns(:activities)
+    assert_equal [s3,s2], assigns(:activities).map(&:activity)
   end
 
   should 'the activities be the received scraps in community profile' do
@@ -952,9 +951,9 @@ class ProfileControllerTest < ActionController::TestCase
     p1 = fast_create(Person)
     p2 = fast_create(Person)
     p3 = fast_create(Person)
-    s1 = fast_create(Scrap, :sender_id => p1.id, :receiver_id => p2.id)
-    s2 = fast_create(Scrap, :sender_id => p2.id, :receiver_id => c.id)
-    s3 = fast_create(Scrap, :sender_id => p3.id, :receiver_id => c.id)
+    s1 = create(Scrap, :sender_id => p1.id, :receiver_id => p2.id)
+    s2 = create(Scrap, :sender_id => p2.id, :receiver_id => c.id)
+    s3 = create(Scrap, :sender_id => p3.id, :receiver_id => c.id)
 
     @controller.stubs(:logged_in?).returns(true)
     user = mock()
@@ -963,12 +962,12 @@ class ProfileControllerTest < ActionController::TestCase
     @controller.stubs(:current_user).returns(user)
     Person.any_instance.stubs(:follows?).returns(true)
     get :index, :profile => c.identifier
-    assert_equivalent [s2,s3], assigns(:activities)
+    assert_equivalent [s2,s3], assigns(:activities).map(&:activity)
   end
 
   should 'the activities be paginated in people profiles' do
     p1= fast_create(Person)
-    40.times{fast_create(Scrap, :receiver_id => p1.id, :created_at => Time.now)}
+    40.times{create(Scrap, :receiver_id => p1.id, :created_at => Time.now)}
 
     @controller.stubs(:logged_in?).returns(true)
     user = mock()
@@ -978,13 +977,13 @@ class ProfileControllerTest < ActionController::TestCase
     Person.any_instance.stubs(:follows?).returns(true)
     assert_equal 40, p1.scraps_received.not_replies.count
     get :index, :profile => p1.identifier
-    assert_equal 15, assigns(:activities).count
+    assert_equal 15, assigns(:activities).size
   end
 
   should 'the activities be paginated in community profiles' do
     p1= fast_create(Person)
     c = fast_create(Community)
-    40.times{fast_create(Scrap, :receiver_id => c.id)}
+    40.times{create(Scrap, :receiver_id => c.id)}
 
     @controller.stubs(:logged_in?).returns(true)
     user = mock()
@@ -994,7 +993,7 @@ class ProfileControllerTest < ActionController::TestCase
     Person.any_instance.stubs(:follows?).returns(true)
     assert_equal 40, c.scraps_received.not_replies.count
     get :index, :profile => c.identifier
-    assert_equal 15, assigns(:activities).count
+    assert_equal 15, assigns(:activities).size
   end
 
   should "the owner of activity could remove it" do
@@ -1140,7 +1139,7 @@ class ProfileControllerTest < ActionController::TestCase
     get :view_more_activities, :profile => profile.identifier, :page => 2
     assert_response :success
     assert_template '_profile_activities_list'
-    assert_equal 10, assigns(:activities).count
+    assert_equal 10, assigns(:activities).size
   end
 
   should "be logged in to access the view_more_activities action" do
@@ -1193,8 +1192,8 @@ class ProfileControllerTest < ActionController::TestCase
   should "not index display scraps replies" do
     login_as(profile.identifier)
     Scrap.destroy_all
-    scrap = fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id)
-    20.times {fast_create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)}
+    scrap = create(Scrap, :sender_id => profile.id, :receiver_id => profile.id)
+    20.times {create(Scrap, :sender_id => profile.id, :receiver_id => profile.id, :scrap_id => scrap.id)}
     profile.reload
     get :index, :profile => profile.identifier
     assert_tag 'ul', :attributes => {:class => 'profile-wall-activities-comments scrap-replies'}, :children => {:count => 0 }
@@ -1340,7 +1339,7 @@ class ProfileControllerTest < ActionController::TestCase
     login_as(profile.identifier)
     get :index, :profile => profile.identifier
 
-    assert_equivalent [scrap,activity], assigns(:activities).map {|a| a.klass.constantize.find(a.id)}
+    assert_equivalent [scrap,activity], assigns(:activities).map(&:activity)
   end
 
   should "be logged in to leave comment on an activity" do


=====================================
test/unit/action_tracker_ext_test.rb
=====================================
--- a/test/unit/action_tracker_ext_test.rb
+++ b/test/unit/action_tracker_ext_test.rb
@@ -1,6 +1,7 @@
 require_relative "../test_helper"
 
 class ActionTrackerExtTest < ActiveSupport::TestCase
+
   should 'increase person activities_count on new activity' do
     person = fast_create(Person)
     assert_difference 'person.activities_count', 1 do
@@ -61,4 +62,12 @@ class ActionTrackerExtTest < ActiveSupport::TestCase
       organization.reload
     end
   end
+
+  should 'create profile activity' do
+    person = fast_create(Profile)
+    organization = fast_create(Enterprise)
+    record = create ActionTracker::Record, :verb => :create_product, :user => person, :target => organization
+    assert_equal record, organization.activities.first.activity
+  end
+
 end


=====================================
test/unit/community_test.rb
=====================================
--- a/test/unit/community_test.rb
+++ b/test/unit/community_test.rb
@@ -368,7 +368,7 @@ class CommunityTest < ActiveSupport::TestCase
     scrap = create(Scrap, defaults_for_scrap(:sender => person, :receiver => community, :content => 'A scrap'))
     activity = ActionTracker::Record.last
 
-    assert_equal [scrap], community.activities.map { |a| a.klass.constantize.find(a.id) }
+    assert_equal [scrap], community.activities.map(&:activity)
   end
 
   should 'return tracked_actions of community as activities' do
@@ -378,7 +378,7 @@ class CommunityTest < ActiveSupport::TestCase
     User.current = person.user
     assert_difference 'ActionTracker::Record.count', 1 do
       article = create(TinyMceArticle, :profile => community, :name => 'An article about free software')
-      assert_equal [article.activity], community.activities.map { |a| a.klass.constantize.find(a.id) }
+      assert_equal [article.activity], community.activities.map(&:activity)
     end
   end
 
@@ -393,12 +393,12 @@ class CommunityTest < ActiveSupport::TestCase
     assert_not_includes community.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity
   end
 
- 
+
   should 'check if a community admin user is really a community admin' do
     c = fast_create(Community, :name => 'my test profile', :identifier => 'mytestprofile')
     admin = create_user('adminuser').person
     c.add_admin(admin)
-   
+
     assert c.is_admin?(admin)
   end
 


=====================================
test/unit/enterprise_test.rb
=====================================
--- a/test/unit/enterprise_test.rb
+++ b/test/unit/enterprise_test.rb
@@ -468,7 +468,7 @@ class EnterpriseTest < ActiveSupport::TestCase
     activity = ActionTracker::Record.last
     scrap = create(Scrap, defaults_for_scrap(:sender => person, :receiver => enterprise, :content => 'A scrap'))
 
-    assert_equal [scrap], enterprise.activities.map { |a| a.klass.constantize.find(a.id) }
+    assert_equal [scrap], enterprise.activities.map(&:activity)
   end
 
   should 'return tracked_actions of community as activities' do
@@ -478,7 +478,7 @@ class EnterpriseTest < ActiveSupport::TestCase
     User.current = person.user
     article = create(TinyMceArticle, :profile => enterprise, :name => 'An article about free software')
 
-    assert_equal [article.activity], enterprise.activities.map { |a| a.klass.constantize.find(a.id) }
+    assert_equal [article.activity], enterprise.activities.map(&:activity)
   end
 
   should 'not return tracked_actions of other community as activities' do
@@ -489,7 +489,7 @@ class EnterpriseTest < ActiveSupport::TestCase
     User.current = person.user
     article = create(TinyMceArticle, :profile => enterprise2, :name => 'Another article about free software')
 
-    assert_not_includes enterprise.activities.map { |a| a.klass.constantize.find(a.id) }, article.activity
+    assert_not_includes enterprise.activities.map(&:activity), article.activity
   end
 
   should 'provide URL to catalog area' do
@@ -503,7 +503,7 @@ class EnterpriseTest < ActiveSupport::TestCase
     c = fast_create(Enterprise, :name => 'my test profile', :identifier => 'mytestprofile')
     admin = create_user('adminuser').person
     c.add_admin(admin)
-   
+
     assert c.is_admin?(admin)
   end
 


=====================================
test/unit/person_notifier_test.rb
=====================================
--- a/test/unit/person_notifier_test.rb
+++ b/test/unit/person_notifier_test.rb
@@ -168,7 +168,8 @@ class PersonNotifierTest < ActiveSupport::TestCase
       a.verb = verb
       a.user = @member
       a.created_at = @member.notifier.notify_from + 1.day
-      a.target = fast_create(Forum)
+      profile = create(Community)
+      a.target = create(Forum, profile: profile)
       a.comments_count = 0
       a.params = {
         'name' => 'home', 'url' => '/', 'lead' => '',


=====================================
test/unit/person_test.rb
=====================================
--- a/test/unit/person_test.rb
+++ b/test/unit/person_test.rb
@@ -916,7 +916,7 @@ class PersonTest < ActiveSupport::TestCase
     refute p2.is_member_of?(community)
     process_delayed_job_queue
 
-    action_tracker = fast_create(ActionTracker::Record, :verb => 'create_article')
+    action_tracker = create(ActionTracker::Record, user: p1, verb: 'create_article')
     action_tracker.target = community
     action_tracker.user = p4
     action_tracker.save!
@@ -1254,7 +1254,7 @@ class PersonTest < ActiveSupport::TestCase
     User.current = person.user
     article = create(TinyMceArticle, :profile => person, :name => 'An article about free software')
 
-    assert_equivalent [scrap,article.activity], person.activities.map { |a| a.klass.constantize.find(a.id) }
+    assert_equivalent [scrap,article.activity], person.activities.map { |a| a.activity }
   end
 
   should 'not return tracked_actions and scraps from others as activities' do
@@ -1273,7 +1273,7 @@ class PersonTest < ActiveSupport::TestCase
     create(TinyMceArticle, :profile => person, :name => 'An article about free software')
     person_activity = ActionTracker::Record.last
 
-    assert_equivalent [person_scrap,person_activity], person.activities.map { |a| a.klass.constantize.find(a.id) }
+    assert_equivalent [person_scrap,person_activity], person.activities.map { |a| a.activity }
   end
 
   should 'grant every permission over profile for its admin' do


=====================================
test/unit/profile_activity_test.rb
=====================================
--- /dev/null
+++ b/test/unit/profile_activity_test.rb
@@ -0,0 +1,21 @@
+require_relative '../test_helper'
+
+class ProfileActivityTest < ActiveSupport::TestCase
+
+  def setup
+    super
+  end
+
+  should 'use timestamps from activity' do
+    profile = fast_create Person
+    target = fast_create Person
+
+    ActionTracker::Record.attr_accessible :created_at, :updated_at
+    tracker = ActionTracker::Record.create! verb: :leave_scrap, user: profile, target: target, created_at: Time.now-2.days, updated_at: Time.now-1.day
+
+    pa = ProfileActivity.create! profile: profile, activity: tracker
+    assert_equal pa.created_at, pa.activity.created_at
+    assert_equal pa.updated_at, pa.activity.updated_at
+  end
+
+end


=====================================
test/unit/scrap_notifier_test.rb
=====================================
--- a/test/unit/scrap_notifier_test.rb
+++ b/test/unit/scrap_notifier_test.rb
@@ -58,7 +58,7 @@ class ScrapNotifierTest < ActiveSupport::TestCase
   should 'not deliver mail if is a reply on a community' do
     community = fast_create(Community)
     person = create_user.person
-    scrap = fast_create(Scrap, :receiver_id => community.id, :sender_id => @sender.id)
+    scrap = create(Scrap, receiver_id: community.id, sender_id: @sender.id)
     assert_no_difference 'ActionMailer::Base.deliveries.size' do
       Scrap.create!(:sender_id => person.id, :receiver_id => @sender.id, :scrap_id => scrap.id, :content => 'Hi myself!')
     end


=====================================
test/unit/scrap_test.rb
=====================================
--- a/test/unit/scrap_test.rb
+++ b/test/unit/scrap_test.rb
@@ -3,8 +3,8 @@ require_relative "../test_helper"
 class ScrapTest < ActiveSupport::TestCase
 
   def setup
-    Person.delete_all
-    Scrap.delete_all
+    Person.destroy_all
+    Scrap.destroy_all
     ActionTracker::Record.destroy_all
   end
 
@@ -126,16 +126,16 @@ class ScrapTest < ActiveSupport::TestCase
     p1 = create_user.person
     p2 = create_user.person
     p1.add_friend(p2)
-    ActionTrackerNotification.delete_all
-    Delayed::Job.delete_all
+    process_delayed_job_queue
     s = Scrap.new
     s.sender= p1
     s.receiver= p2
     s.content = 'some content'
     s.save!
-    process_delayed_job_queue
-    assert_equal 2, ActionTrackerNotification.count
-    ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|
+    assert_difference 'ActionTrackerNotification.count', 2 do
+      process_delayed_job_queue
+    end
+    ActionTrackerNotification.all.map(&:profile).map do |profile|
       assert [p1,p2].include?(profile)
     end
   end
@@ -151,7 +151,9 @@ class ScrapTest < ActiveSupport::TestCase
     s.receiver= c
     s.content = 'some content'
     s.save!
-    process_delayed_job_queue
+    assert_difference 'ActionTrackerNotification.count', 2 do
+      process_delayed_job_queue
+    end
     assert_equal 2, ActionTrackerNotification.count
     ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|
       assert [p,c].include?(profile)
@@ -183,8 +185,9 @@ class ScrapTest < ActiveSupport::TestCase
     s.receiver= p1
     s.content = 'some content'
     s.save!
-    process_delayed_job_queue
-    assert_equal 2, ActionTrackerNotification.count
+    assert_difference 'ActionTrackerNotification.count', 2 do
+      process_delayed_job_queue
+    end
     ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|
       assert [p1,p2].include?(profile)
     end
@@ -218,7 +221,7 @@ class ScrapTest < ActiveSupport::TestCase
 
   should "update the scrap on reply creation" do
     person = create_user.person
-    s = fast_create(Scrap, :updated_at => DateTime.parse('2010-01-01'))
+    s = create(Scrap, sender: person, receiver: person, updated_at: DateTime.parse('2010-01-01'))
     assert_equal DateTime.parse('2010-01-01'), s.updated_at.strftime('%Y-%m-%d')
     DateTime.stubs(:now).returns(DateTime.parse('2010-09-07'))
     s1 = create(Scrap, :content => 'some content', :sender => person, :receiver => person, :scrap_id => s.id)
@@ -288,7 +291,7 @@ class ScrapTest < ActiveSupport::TestCase
 
   should 'create activity with reply_scrap_on_self when top_root scrap receiver is the same as sender' do
     s, r = create_user.person, create_user.person
-    root = fast_create(Scrap, :sender_id => s.id, :receiver_id => r.id)
+    root = create(Scrap, :sender_id => s.id, :receiver_id => r.id)
     assert_difference 'ActionTracker::Record.count', 1 do
       reply = create(Scrap, :sender => r, :receiver => s, :scrap_id => root.id, :content => 'sample')
     end
@@ -296,4 +299,10 @@ class ScrapTest < ActiveSupport::TestCase
     assert_equal 'reply_scrap_on_self', activity.verb.to_s
   end
 
+  should 'create profile activity' do
+    p1, p2 = create_user.person, create_user.person
+    s = create Scrap, :sender => p1, :receiver => p2, :content => "Hello!"
+    assert_equal s, p2.activities.first.activity
+  end
+
 end



View it on GitLab: https://gitlab.com/noosfero/noosfero/compare/96e1744b9ed5f91df815c3f0aefeae79ea1b9e5d...16f70434a650efc21b1603f004670bf5faeded4d
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20150812/b22b348a/attachment-0001.html>


More information about the Noosfero-dev mailing list