diff --git a/app/models/concerns/follower.rb b/app/models/concerns/follower.rb index 680f3db..9565ebe 100644 --- a/app/models/concerns/follower.rb +++ b/app/models/concerns/follower.rb @@ -4,6 +4,7 @@ module Follower def follow(profile, circles) circles = [circles] unless circles.is_a?(Array) circles.each do |new_circle| + next if new_circle.person != self || new_circle.profile_type != profile.class.name ProfileFollower.create(profile: profile, circle: new_circle) end end @@ -24,16 +25,15 @@ module Follower def update_profile_circles(profile, new_circles) profile_circles = ProfileFollower.with_profile(profile).with_follower(self).map(&:circle) circles_to_add = new_circles - profile_circles - circles_to_remove = profile_circles - new_circles - circles_to_add.each do |new_circle| - ProfileFollower.create(profile: profile, circle: new_circle) - end + self.follow(profile, circles_to_add) + circles_to_remove = profile_circles - new_circles ProfileFollower.where('circle_id IN (?) AND profile_id = ?', circles_to_remove.map(&:id), profile.id).destroy_all end def remove_profile_from_circle(profile, circle) + return if circle.person != self ProfileFollower.with_profile(profile).with_circle(circle).destroy_all end diff --git a/app/models/profile.rb b/app/models/profile.rb index b96162c..097376f 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -249,11 +249,6 @@ class Profile < ApplicationRecord has_many :email_templates, :foreign_key => :owner_id has_many :profile_followers - scope :memberships_of, -> person { - distinct.select('profiles.*'). - joins(:role_assignments). - where('role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id) - } def in_circles Circle.joins(:profile_followers). @@ -261,10 +256,10 @@ class Profile < ApplicationRecord end def followers - person_followers = Person.joins(:circles).merge(in_circles) - external_person_followers = ExternalPerson.joins(:circles).merge(in_circles) + person_followers = Person.joins(:circles).merge(in_circles).uniq + external_person_followers = ExternalPerson.joins(:circles).merge(in_circles).uniq - person_followers+external_person_followers + person_followers + external_person_followers end # has_many :followers, -> { uniq }, :through => :profile_followers, :source => :person diff --git a/test/unit/follower_test.rb b/test/unit/follower_test.rb new file mode 100644 index 0000000..5f18e07 --- /dev/null +++ b/test/unit/follower_test.rb @@ -0,0 +1,152 @@ +require_relative "../test_helper" + +class FollowerTest < ActiveSupport::TestCase + + def setup + @person1 = create_user('perso-test-1').person + @person2 = create_user('person-test-2').person + + @circle1 = Circle.create!(person: @person1, name: "Zombies", profile_type: 'Person') + @circle2 = Circle.create!(person: @person1, name: "Humans", profile_type: 'Person') + + @external_person = ExternalPerson.create!(identifier: 'johnlocke', + name: 'John Locke', + source: 'anerenvironment.org', + email: 'locke@island.org', + created_at: Date.yesterday) + end + + should 'follows? return false when no profile is passed as parameter' do + assert_equal false, @person1.follows?(nil) + end + + should 'follow person with regular user' do + assert_difference '@person1.followed_profiles.count' do + @person1.follow(@person2, @circle1) + end + assert @person1.follows?(@person2) + end + + should 'follow a community' do + community = fast_create(Community) + circle = Circle.create!(person: @person1, name: "Terminus", profile_type: 'Community') + + assert_difference '@person1.followed_profiles.count' do + @person1.follow(community, circle) + end + assert @person1.follows?(community) + end + + should 'not follow person if the user is not the ownner of the circle' do + person3 = create_user('perso-test-3').person + + assert_no_difference '@circle1.person.followed_profiles.count' do + person3.follow(@person2, @circle1) + end + assert_not @circle1.person.follows?(@person2) + end + + should 'not follow a community if circle profile type does not match' do + community = fast_create(Community) + + assert_no_difference '@person1.followed_profiles.count' do + @person1.follow(community, @circle1) + end + assert_not @person1.follows?(community) + end + + should 'follow person with external user' do + @circle1.update_attributes(person: @external_person) + + assert_difference '@external_person.followed_profiles.count' do + @external_person.follow(@person2, @circle1) + end + assert @external_person.follows?(@person2) + end + + should 'unfollow person with regular user' do + @person1.follow(@person2, @circle1) + + assert_difference '@person1.followed_profiles.count', -1 do + @person1.unfollow(@person2) + end + assert_not @person1.follows?(@person2) + end + + should 'unfollow person with external user' do + @circle1.update_attributes(person: @external_person) + @external_person.follow(@person2, @circle1) + + assert_difference '@external_person.followed_profiles.count', -1 do + @external_person.unfollow(@person2) + end + assert_not @external_person.follows?(@person2) + end + + should 'get the followed profiles for a regular user' do + person3 = create_user('person-test-3').person + + @person1.follow(@person2, @circle1) + @person1.follow(person3, @circle1) + assert_equivalent [@person2, person3], @person1.followed_profiles + end + + should 'get the followed profiles for an external user' do + person3 = create_user('person-test-3').person + @circle1.update_attributes(person: @external_person) + + @external_person.follow(@person2, @circle1) + @external_person.follow(person3, @circle1) + assert_equivalent [@person2, person3], @external_person.followed_profiles + end + + should 'not follow same person twice even with different circles' do + circle3 = Circle.create!(person: @person1, name: "Free Folk", profile_type: 'Person') + + @person1.follow(@person2, @circle1) + @person1.follow(@person2, @circle2) + @person1.follow(@person2, circle3) + assert_equivalent [@person2], @person1.followed_profiles + end + + should 'display an error if a person is already being followed' do + @person1.follow(@person2, @circle1) + profile_follower = ProfileFollower.new(circle: @circle1, profile: @person2) + + profile_follower.valid? + assert profile_follower.errors.messages[:profile_id].present? + end + + should 'update profile circles for a person' do + circle3 = Circle.create!(person: @person1, name: "Brains", profile_type: 'Person') + @person1.follow(@person2, [@circle1, @circle2]) + + @person1.update_profile_circles(@person2, [@circle2, circle3]) + assert_equivalent [@circle2, circle3], @person2.in_circles + end + + should 'keep other follower circles after update' do + person3 = create_user('person-test-3').person + circle3 = Circle.create!(person: person3, name: "Humans", profile_type: 'Person') + @person1.follow(@person2, @circle1) + person3.follow(@person2, circle3) + + @person1.update_profile_circles(@person2, [@circle1, @circle2]) + assert_equivalent [@circle1, @circle2, circle3], @person2.in_circles + end + + should 'remove a person from a circle' do + @person1.follow(@person2, [@circle1, @circle2]) + + @person1.remove_profile_from_circle(@person2, @circle2) + assert_equivalent [@circle1], @person2.in_circles + end + + should 'not remove a person from a circle if the user is not the owner' do + person3 = create_user('person-test-3').person + @person1.follow(@person2, [@circle1, @circle2]) + + person3.remove_profile_from_circle(@person2, @circle2) + assert_equivalent [@circle1, @circle2], @person2.in_circles + end +end diff --git a/test/unit/person_test.rb b/test/unit/person_test.rb index f73dbe2..ae68fd0 100644 --- a/test/unit/person_test.rb +++ b/test/unit/person_test.rb @@ -1640,11 +1640,6 @@ class PersonTest < ActiveSupport::TestCase assert person.can_change_homepage? end - should 'follow? return false when no profile is passed as parameter' do - person = Person.new - assert_equal false, person.follows?(nil) - end - should 'allow posting content when has post_content permission' do person = create_user('person').person profile = mock @@ -1957,53 +1952,4 @@ class PersonTest < ActiveSupport::TestCase person.user.expects(:save!).never person.save! end - - should 'update profile circles for a person' do - person = create_user('testuser').person - community = fast_create(Community) - circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') - circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community') - circle3 = Circle.create!(:person=> person, :name => "Quadrado", :profile_type => 'Community') - person.follow(community, [circle, circle2]) - person.update_profile_circles(community, [circle2, circle3]) - assert_equivalent [circle2, circle3], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) - end - - should 'a person follow a profile' do - person = create_user('testuser').person - community = fast_create(Community) - circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') - person.follow(community, circle) - assert_includes person.followed_profiles, community - end - - should 'a person follow a profile with more than one circle' do - person = create_user('testuser').person - community = fast_create(Community) - circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') - circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community') - person.follow(community, [circle, circle2]) - assert_includes person.followed_profiles, community - assert_equivalent [circle, circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) - end - - should 'a person unfollow a profile' do - person = create_user('testuser').person - community = fast_create(Community) - circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') - person.follow(community, circle) - person.unfollow(community) - assert_not_includes person.followed_profiles, community - end - - should 'a person remove a profile from a circle' do - person = create_user('testuser').person - community = fast_create(Community) - circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community') - circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community') - person.follow(community, [circle, circle2]) - person.remove_profile_from_circle(community, circle) - assert_equivalent [circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle) - end - end diff --git a/test/unit/profile_followers_test.rb b/test/unit/profile_followers_test.rb deleted file mode 100644 index 225a765..0000000 --- a/test/unit/profile_followers_test.rb +++ /dev/null @@ -1,73 +0,0 @@ -require_relative "../test_helper" - -class ProfileFollowersTest < ActiveSupport::TestCase - - should 'a person follow another' do - p1 = create_user('person_test').person - p2 = create_user('person_test_2').person - circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') - - assert_difference 'ProfileFollower.count' do - p1.follow(p2, circle) - end - - assert_includes p2.followers, p1 - assert_not_includes p1.followers, p2 - end - - should 'a person unfollow another person' do - p1 = create_user('person_test').person - p2 = create_user('person_test_2').person - circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') - - p1.follow(p2,circle) - - assert_difference 'ProfileFollower.count', -1 do - p1.unfollow(p2) - end - - assert_not_includes p2.followers, p1 - end - - should 'get the followed persons for a profile' do - p1 = create_user('person_test').person - p2 = create_user('person_test_2').person - p3 = create_user('person_test_3').person - circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') - - p1.follow(p2, circle) - p1.follow(p3, circle) - - assert_equivalent p1.followed_profiles, [p2,p3] - assert_equivalent Profile.followed_by(p1), [p2,p3] - end - - should 'not follow same person twice' do - p1 = create_user('person_test').person - p2 = create_user('person_test_2').person - circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') - - assert_difference 'ProfileFollower.count' do - p1.follow(p2, circle) - p1.follow(p2, circle) - end - - assert_equivalent p1.followed_profiles, [p2] - assert_equivalent p2.followers, [p1] - end - - should 'show the correct message when a profile is followed by the same person' do - p1 = create_user('person_test').person - p2 = create_user('person_test_2').person - circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person') - - p1.follow(p2, circle) - profile_follower = ProfileFollower.new - profile_follower.circle = circle - profile_follower.profile = p2 - profile_follower.valid? - - assert_includes profile_follower.errors.messages[:profile_id], - "can't put a profile in the same circle twice" - end -end diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb index 9c998ba..e493e05 100644 --- a/test/unit/profile_test.rb +++ b/test/unit/profile_test.rb @@ -2232,4 +2232,47 @@ class ProfileTest < ActiveSupport::TestCase c.add_member(p) end end + + should 'return all circles and followers, and do not repeat' do + person1 = create_user('testperson-1').person + person2 = create_user('testperson-2').person + person3 = create_user('testperson-3').person + circle1 = Circle.create!(:person => person1, :name => "Night's Watch", :profile_type => 'Person') + circle2 = Circle.create!(:person => person1, :name => "Free Folk", :profile_type => 'Person') + circle3 = Circle.create!(:person => person2, :name => "The Unsullied", :profile_type => 'Person') + + person1.follow(person3, circle1) + person1.follow(person3, circle2) + person2.follow(person3, circle3) + + assert_equivalent person3.in_circles, [circle1, circle2, circle3] + assert_equivalent person3.followers, [person1, person2] + end + + should 'return all profiles followed by a regular person' do + person1 = create_user('testperson-1').person + person2 = create_user('testperson-2').person + community = fast_create(Community) + circle1 = Circle.create!(:person => person1, :name => "Night's Watch", :profile_type => 'Person') + circle2 = Circle.create!(:person => person1, :name => "Free Folk", :profile_type => 'Community') + + person1.follow(person2, circle1) + person1.follow(community, circle2) + assert_equivalent [person2, community], Profile.followed_by(person1) + end + + should 'return all profiles followed by an external person' do + external_person = ExternalPerson.create!(identifier: 'johnlocke', name: 'John Locke', + source: 'anerenvironment.org', email: 'locke@island.org', + created_at: Date.yesterday) + person = create_user('testperson-2').person + community = fast_create(Community) + circle1 = Circle.create!(:person => external_person, :name => "Night's Watch", :profile_type => 'Person') + circle2 = Circle.create!(:person => external_person, :name => "Free Folk", :profile_type => 'Community') + + external_person.follow(person, circle1) + external_person.follow(community, circle2) + assert_equivalent [person, community], Profile.followed_by(external_person) + end + end -- libgit2 0.21.2