From c124eb8e7709f777e7f6e48cba3f74c8e9fdb055 Mon Sep 17 00:00:00 2001 From: Rodrigo Souto Date: Tue, 18 Mar 2014 20:20:42 +0000 Subject: [PATCH] organization: register and use members_count to fetch most_popular organizations --- app/models/organization.rb | 6 +----- app/models/profile.rb | 4 ---- config/initializers/noosfero_extensions.rb | 1 + db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb | 12 ++++++++++++ lib/noosfero/role_assignment_ext.rb | 29 +++++++++++++++++++++++++++++ test/unit/organization_test.rb | 27 ++++++++++++++++++++++++--- test/unit/role_assignment_ext_test.rb | 28 ++++++++++++++++++++++++++++ 7 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 config/initializers/noosfero_extensions.rb create mode 100644 db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb create mode 100644 lib/noosfero/role_assignment_ext.rb create mode 100644 test/unit/role_assignment_ext_test.rb diff --git a/app/models/organization.rb b/app/models/organization.rb index 9e602c6..889d8dc 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -26,11 +26,7 @@ class Organization < Profile has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source' - named_scope :more_popular, - :select => "#{Profile.qualified_column_names}, count(resource_id) as total", - :group => Profile.qualified_column_names, - :joins => "LEFT OUTER JOIN role_assignments ON profiles.id = role_assignments.resource_id", - :order => "total DESC" + named_scope :more_popular, :order => 'members_count DESC' def validation_methodology self.validation_info ? self.validation_info.validation_methodology : nil diff --git a/app/models/profile.rb b/app/models/profile.rb index 45290f9..1366523 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -87,10 +87,6 @@ class Profile < ActiveRecord::Base scopes.size == 1 ? scopes.first : Person.or_scope(scopes) end - def members_count - members.count - end - class << self def count_with_distinct(*args) options = args.last || {} diff --git a/config/initializers/noosfero_extensions.rb b/config/initializers/noosfero_extensions.rb new file mode 100644 index 0000000..37791a8 --- /dev/null +++ b/config/initializers/noosfero_extensions.rb @@ -0,0 +1 @@ +require 'noosfero/role_assignment_ext' diff --git a/db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb b/db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb new file mode 100644 index 0000000..eeea182 --- /dev/null +++ b/db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb @@ -0,0 +1,12 @@ +class DefineInitialValueForProfilesMembersCount < ActiveRecord::Migration + def self.up + 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;") + members_counts.each do |count| + execute("UPDATE profiles SET members_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};") + end + end + + def self.down + execute("UPDATE profiles SET members_count=0;") + end +end diff --git a/lib/noosfero/role_assignment_ext.rb b/lib/noosfero/role_assignment_ext.rb new file mode 100644 index 0000000..7b11314 --- /dev/null +++ b/lib/noosfero/role_assignment_ext.rb @@ -0,0 +1,29 @@ +Rails.configuration.to_prepare do + RoleAssignment.module_eval do + extend CacheCounterHelper + + after_create do |role_assignment| + accessor = role_assignment.accessor + resource = role_assignment.resource + if resource.kind_of?(Organization) + #FIXME This will only work as long as the role_assignment associations + #happen only between profiles, due to the polymorphic column type. + if resource.role_assignments.where(:accessor_id => accessor.id).count == 1 + update_cache_counter(:members_count, resource, 1) + end + end + end + + after_destroy do |role_assignment| + accessor = role_assignment.accessor + resource = role_assignment.resource + if resource.kind_of?(Organization) + #FIXME This will only work as long as the role_assignment associations + #happen only between profiles, due to the polymorphic column type. + if resource.role_assignments.where(:accessor_id => accessor.id).count == 0 + update_cache_counter(:members_count, resource, -1) + end + end + end + end +end diff --git a/test/unit/organization_test.rb b/test/unit/organization_test.rb index 3dcd50c..0bce8ed 100644 --- a/test/unit/organization_test.rb +++ b/test/unit/organization_test.rb @@ -302,18 +302,17 @@ class OrganizationTest < ActiveSupport::TestCase end should 'find more popular organizations' do - Organization.delete_all o1 = fast_create(Organization) o2 = fast_create(Organization) p1 = fast_create(Person) p2 = fast_create(Person) o1.add_member(p1) - assert_equal [o1,o2] , Organization.more_popular + assert_order [o1,o2] , Organization.more_popular o2.add_member(p1) o2.add_member(p2) - assert_equal [o2,o1] , Organization.more_popular + assert_order [o2,o1] , Organization.more_popular end should 'list organizations that have no members in more popular list' do @@ -331,6 +330,7 @@ class OrganizationTest < ActiveSupport::TestCase person = fast_create(Person) organization = fast_create(Organization) organization.add_member(person) + organization.reload assert_equal "one member", organization.more_popular_label end @@ -342,10 +342,12 @@ class OrganizationTest < ActiveSupport::TestCase organization.add_member(person1) organization.add_member(person2) + organization.reload assert_equal "2 members", organization.more_popular_label person3 = fast_create(Person) organization.add_member(person3) + organization.reload assert_equal "3 members", organization.more_popular_label end @@ -433,5 +435,24 @@ class OrganizationTest < ActiveSupport::TestCase end end + should 'increase members_count on new membership' do + member = fast_create(Person) + organization = fast_create(Organization) + assert_difference organization, :members_count, 1 do + organization.add_member(member) + organization.reload + end + end + + should 'decrease members_count on membership removal' do + member = fast_create(Person) + organization = fast_create(Organization) + organization.add_member(member) + organization.reload + assert_difference organization, :members_count, -1 do + organization.remove_member(member) + organization.reload + end + end end diff --git a/test/unit/role_assignment_ext_test.rb b/test/unit/role_assignment_ext_test.rb new file mode 100644 index 0000000..c4a182c --- /dev/null +++ b/test/unit/role_assignment_ext_test.rb @@ -0,0 +1,28 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class RoleAssignmentExtTest < ActiveSupport::TestCase + should 'increase organization members_count only on the first role_assignment' do + role1 = Role.create!(:name => 'role1') + role2 = Role.create!(:name => 'role2') + member = create_user('person').person + organization = Organization.create!(:name => 'Organization', :identifier => 'organization') + assert_difference organization, :members_count, 1 do + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1) + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2) + organization.reload + end + end + + should 'decrease organization members_count only on the last role_assignment' do + role1 = Role.create!(:name => 'role1') + role2 = Role.create!(:name => 'role2') + member = create_user('person').person + organization = Organization.create!(:name => 'Organization', :identifier => 'organization') + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1) + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2) + assert_difference organization, :members_count, -1 do + organization.role_assignments.destroy_all + organization.reload + end + end +end -- libgit2 0.21.2