interest 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +329 -0
- data/Rakefile +2 -0
- data/interest.gemspec +29 -0
- data/lib/generators/interest_generator.rb +18 -0
- data/lib/generators/templates/migrations/blockings.rb +14 -0
- data/lib/generators/templates/migrations/followings.rb +15 -0
- data/lib/generators/templates/models/blocking.rb +3 -0
- data/lib/generators/templates/models/following.rb +4 -0
- data/lib/interest.rb +49 -0
- data/lib/interest/base.rb +49 -0
- data/lib/interest/blockable.rb +25 -0
- data/lib/interest/blockable/blockee.rb +40 -0
- data/lib/interest/blockable/blocker.rb +69 -0
- data/lib/interest/blockable/blocking.rb +48 -0
- data/lib/interest/blockable/exceptions.rb +12 -0
- data/lib/interest/definition.rb +45 -0
- data/lib/interest/exception.rb +10 -0
- data/lib/interest/follow_requestable.rb +25 -0
- data/lib/interest/follow_requestable/exceptions.rb +12 -0
- data/lib/interest/follow_requestable/follow_request.rb +45 -0
- data/lib/interest/follow_requestable/follow_requestee.rb +45 -0
- data/lib/interest/follow_requestable/follow_requester.rb +92 -0
- data/lib/interest/followable.rb +25 -0
- data/lib/interest/followable/exceptions.rb +12 -0
- data/lib/interest/followable/followee.rb +41 -0
- data/lib/interest/followable/follower.rb +68 -0
- data/lib/interest/followable/following.rb +62 -0
- data/lib/interest/utils.rb +29 -0
- data/lib/interest/version.rb +3 -0
- data/spec/blockable_spec.rb +127 -0
- data/spec/database.yml.example +3 -0
- data/spec/follow_requestable_spec.rb +126 -0
- data/spec/followable_spec.rb +171 -0
- data/spec/models/blocking_spec.rb +42 -0
- data/spec/models/following_spec.rb +120 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/support/database.rb +10 -0
- data/spec/support/models/blockable_user.rb +8 -0
- data/spec/support/models/blocking.rb +4 -0
- data/spec/support/models/collection.rb +6 -0
- data/spec/support/models/follow_requestable_and_blockable_user.rb +8 -0
- data/spec/support/models/follow_requestable_user.rb +9 -0
- data/spec/support/models/followable_and_blockable_user.rb +9 -0
- data/spec/support/models/followable_user.rb +8 -0
- data/spec/support/models/following.rb +4 -0
- data/spec/support/models/stuff.rb +6 -0
- data/spec/support/schema.rb +26 -0
- metadata +211 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require "active_support"
|
2
|
+
|
3
|
+
module Interest
|
4
|
+
module FollowRequestable
|
5
|
+
module FollowRequest
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
validate :validate_follow_request_relationships, if: :should_validate_follow_request_relationships?
|
10
|
+
end
|
11
|
+
|
12
|
+
def accept
|
13
|
+
update status: "accepted"
|
14
|
+
end
|
15
|
+
|
16
|
+
def accept!
|
17
|
+
update! status: "accepted"
|
18
|
+
end
|
19
|
+
|
20
|
+
def accept_mutual_follow
|
21
|
+
transaction { accept and mutual }
|
22
|
+
end
|
23
|
+
|
24
|
+
def accept_mutual_follow!
|
25
|
+
transaction { accept! and mutual! }
|
26
|
+
end
|
27
|
+
|
28
|
+
def reject
|
29
|
+
destroy
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :reject!, :reject
|
33
|
+
|
34
|
+
def should_validate_follow_request_relationships?
|
35
|
+
pending? and follower.is_a?(ActiveRecord::Base) and followee.is_a?(ActiveRecord::Base)
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate_follow_request_relationships
|
39
|
+
errors.add :follower, :invalid unless follower.follow_requester?
|
40
|
+
errors.add :followee, :invalid unless followee.follow_requestee?
|
41
|
+
errors.add :followee, :rejected if follower.follow_requester? and not follower.valid_follow_request_for?(followee)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "interest/utils"
|
3
|
+
require "interest/definition"
|
4
|
+
|
5
|
+
module Interest
|
6
|
+
module FollowRequestable
|
7
|
+
module FollowRequestee
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
include Interest::Definition.instance_methods_for(:follow_requestee, :follow_requester)
|
11
|
+
|
12
|
+
def requires_request_to_follow?(requester)
|
13
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_been_requested_to_follow?(requester)
|
17
|
+
follow_requestee_collection_for(requester).include? requester
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
include Interest::Definition.class_methods_for(:follow_requestee, :follow_requester)
|
22
|
+
|
23
|
+
def define_follow_requestee_association_methods
|
24
|
+
has_many :incoming_follow_requests,
|
25
|
+
-> { where(followings: {status: "pending"}).uniq },
|
26
|
+
as: :followee,
|
27
|
+
dependent: :destroy,
|
28
|
+
class_name: "Following" do
|
29
|
+
include Interest::Definition.collection_methods_for(:follower)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def define_follow_requestee_association_method(source_type)
|
34
|
+
association_method_name = follow_requestee_association_method_name_for source_type
|
35
|
+
|
36
|
+
has_many association_method_name,
|
37
|
+
-> { uniq },
|
38
|
+
through: :incoming_follow_requests,
|
39
|
+
source: :follower,
|
40
|
+
source_type: source_type
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_record"
|
3
|
+
require "interest/utils"
|
4
|
+
require "interest/definition"
|
5
|
+
require "interest/follow_requestable/exceptions"
|
6
|
+
require "interest/follow_requestable/follow_requestee"
|
7
|
+
|
8
|
+
module Interest
|
9
|
+
module FollowRequestable
|
10
|
+
module FollowRequester
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
include Interest::Definition.instance_methods_for(:follow_requester, :follow_requestee)
|
14
|
+
|
15
|
+
def required_request_to_follow?(requestee)
|
16
|
+
requestee.follow_requestee? and requestee.requires_request_to_follow?(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def request_to_follow(requestee, raise_record_invalid = false)
|
20
|
+
outgoing_follow_requests.create!(followee: requestee)
|
21
|
+
rescue ActiveRecord::RecordInvalid => exception
|
22
|
+
raise_record_invalid ? (raise exception) : nil
|
23
|
+
rescue ActiveRecord::RecordNotUnique
|
24
|
+
outgoing_follow_requests.find_by(followee: requestee)
|
25
|
+
end
|
26
|
+
|
27
|
+
def request_to_follow!(requestee)
|
28
|
+
request_to_follow(requestee, true)
|
29
|
+
rescue ActiveRecord::RecordInvalid => exception
|
30
|
+
raise Interest::FollowRequestable::Rejected.new(exception)
|
31
|
+
end
|
32
|
+
|
33
|
+
def cancel_request_to_follow(requestee)
|
34
|
+
follow_requester_collection_for(requestee).delete requestee
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_requested_to_follow?(requestee)
|
38
|
+
follow_requester_collection_for(requestee).include? requestee
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid_follow_request_for?(requestee)
|
42
|
+
not (self == requestee or not follow_requestable?(requestee) or (follower? and following? requestee))
|
43
|
+
end
|
44
|
+
|
45
|
+
def follow_or_request_to_follow!(other)
|
46
|
+
if required_request_to_follow? other
|
47
|
+
returned = request_to_follow! other
|
48
|
+
which = :request_to_follow
|
49
|
+
else
|
50
|
+
returned = follow! other
|
51
|
+
which = :follow
|
52
|
+
end
|
53
|
+
|
54
|
+
FollowOrRequestToFollow.new which, returned, other
|
55
|
+
end
|
56
|
+
|
57
|
+
class FollowOrRequestToFollow < Struct.new(:which, :returned, :target)
|
58
|
+
def followed?
|
59
|
+
which == :follow
|
60
|
+
end
|
61
|
+
|
62
|
+
def requested_to_follow?
|
63
|
+
which == :request_to_follow
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module ClassMethods
|
68
|
+
include Interest::Definition.class_methods_for(:follow_requester, :follow_requestee)
|
69
|
+
|
70
|
+
def define_follow_requester_association_methods
|
71
|
+
has_many :outgoing_follow_requests,
|
72
|
+
-> { where(followings: {status: "pending"}).uniq },
|
73
|
+
as: :follower,
|
74
|
+
dependent: :destroy,
|
75
|
+
class_name: "Following" do
|
76
|
+
include Interest::Definition.collection_methods_for(:followee)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def define_follow_requester_association_method(source_type)
|
81
|
+
association_method_name = follow_requester_association_method_name_for source_type
|
82
|
+
|
83
|
+
has_many association_method_name,
|
84
|
+
-> { uniq },
|
85
|
+
through: :outgoing_follow_requests,
|
86
|
+
source: :followee,
|
87
|
+
source_type: source_type
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "interest/followable/exceptions"
|
2
|
+
require "interest/followable/following"
|
3
|
+
require "interest/followable/follower"
|
4
|
+
require "interest/followable/followee"
|
5
|
+
|
6
|
+
module Interest
|
7
|
+
module Followable
|
8
|
+
module Extension
|
9
|
+
def acts_as_follower
|
10
|
+
include Follower
|
11
|
+
define_follower_association_methods
|
12
|
+
end
|
13
|
+
|
14
|
+
def acts_as_followee
|
15
|
+
include Followee
|
16
|
+
define_followee_association_methods
|
17
|
+
end
|
18
|
+
|
19
|
+
def acts_as_followable
|
20
|
+
acts_as_follower
|
21
|
+
acts_as_followee
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "interest/utils"
|
3
|
+
require "interest/definition"
|
4
|
+
|
5
|
+
module Interest
|
6
|
+
module Followable
|
7
|
+
module Followee
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
include Interest::Definition.instance_methods_for(:followee, :follower)
|
11
|
+
|
12
|
+
def followed_by?(follower)
|
13
|
+
followee_collection_for(follower).include? follower
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
include Interest::Definition.class_methods_for(:followee, :follower)
|
18
|
+
|
19
|
+
def define_followee_association_methods
|
20
|
+
has_many :follower_relationships,
|
21
|
+
-> { where(Interest.following_class.table_name.to_sym => {status: "accepted"}).uniq },
|
22
|
+
as: :followee,
|
23
|
+
dependent: :destroy,
|
24
|
+
class_name: Interest.following_class_name do
|
25
|
+
include Interest::Definition.collection_methods_for(:follower)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_followee_association_method(source_type)
|
30
|
+
association_method_name = followee_association_method_name_for source_type
|
31
|
+
|
32
|
+
has_many association_method_name,
|
33
|
+
-> { uniq },
|
34
|
+
through: :follower_relationships,
|
35
|
+
source: :follower,
|
36
|
+
source_type: source_type
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_record"
|
3
|
+
require "interest/utils"
|
4
|
+
require "interest/definition"
|
5
|
+
require "interest/followable/exceptions"
|
6
|
+
require "interest/followable/followee"
|
7
|
+
|
8
|
+
module Interest
|
9
|
+
module Followable
|
10
|
+
module Follower
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
include Interest::Definition.instance_methods_for(:follower, :following)
|
14
|
+
|
15
|
+
def following?(followee)
|
16
|
+
follower_collection_for(followee).include? followee
|
17
|
+
end
|
18
|
+
|
19
|
+
def follow(followee, raise_record_invalid = false)
|
20
|
+
following_relationships.create!(followee: followee)
|
21
|
+
rescue ActiveRecord::RecordInvalid => exception
|
22
|
+
raise_record_invalid ? (raise exception) : nil
|
23
|
+
rescue ActiveRecord::RecordNotUnique
|
24
|
+
if follow_requester? and followee.follow_requestee?
|
25
|
+
outgoing_follow_requests.find_by(followee: followee).try(:accept!)
|
26
|
+
end or following_relationships.find_by(followee: followee)
|
27
|
+
end
|
28
|
+
|
29
|
+
def follow!(followee)
|
30
|
+
follow(followee, true)
|
31
|
+
rescue ActiveRecord::RecordInvalid => exception
|
32
|
+
raise Interest::Followable::Rejected.new(exception)
|
33
|
+
end
|
34
|
+
|
35
|
+
def unfollow(followee)
|
36
|
+
follower_collection_for(followee).delete followee
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid_following_for?(followee)
|
40
|
+
not (followee == self or not followable?(followee))
|
41
|
+
end
|
42
|
+
|
43
|
+
module ClassMethods
|
44
|
+
include Interest::Definition.class_methods_for(:follower, :following)
|
45
|
+
|
46
|
+
def define_follower_association_methods
|
47
|
+
has_many :following_relationships,
|
48
|
+
-> { where(Interest.following_class.table_name.to_sym => {status: "accepted"}).uniq },
|
49
|
+
as: :follower,
|
50
|
+
dependent: :destroy,
|
51
|
+
class_name: Interest.following_class_name do
|
52
|
+
include Interest::Definition.collection_methods_for(:followee)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def define_follower_association_method(source_type)
|
57
|
+
association_method_name = follower_association_method_name_for source_type
|
58
|
+
|
59
|
+
has_many association_method_name,
|
60
|
+
-> { uniq },
|
61
|
+
through: :following_relationships,
|
62
|
+
source: :followee,
|
63
|
+
source_type: source_type
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "active_support"
|
2
|
+
|
3
|
+
module Interest
|
4
|
+
module Followable
|
5
|
+
module Following
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
belongs_to :follower, polymorphic: true
|
10
|
+
belongs_to :followee, polymorphic: true
|
11
|
+
|
12
|
+
validates :follower, presence: true
|
13
|
+
validates :followee, presence: true
|
14
|
+
validates :status, presence: true, inclusion: {in: %w(pending accepted)}
|
15
|
+
|
16
|
+
validate :validate_following_relationships, if: :should_validate_following_relationships?
|
17
|
+
|
18
|
+
scope :accepted, -> { where(status: "accepted") }
|
19
|
+
scope :pending, -> { where(status: "pending") }
|
20
|
+
|
21
|
+
scope :between, ->(a, b) {
|
22
|
+
a_to_b = where(follower: a, followee: b).where_values.reduce(:and)
|
23
|
+
b_to_a = where(follower: b, followee: a).where_values.reduce(:and)
|
24
|
+
|
25
|
+
where a_to_b.or(b_to_a)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def accepted?
|
30
|
+
status == "accepted"
|
31
|
+
end
|
32
|
+
|
33
|
+
def pending?
|
34
|
+
status == "pending"
|
35
|
+
end
|
36
|
+
|
37
|
+
def mutual
|
38
|
+
followee.follow(follower)
|
39
|
+
end
|
40
|
+
|
41
|
+
def mutual!
|
42
|
+
followee.follow!(follower)
|
43
|
+
end
|
44
|
+
|
45
|
+
def should_validate_following_relationships?
|
46
|
+
accepted? and follower.is_a?(ActiveRecord::Base) and followee.is_a?(ActiveRecord::Base)
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_following_relationships
|
50
|
+
errors.add :follower, :invalid unless follower.follower?
|
51
|
+
errors.add :followee, :invalid unless followee.followee?
|
52
|
+
errors.add :followee, :rejected if follower.follower? and not follower.valid_following_for?(followee)
|
53
|
+
end
|
54
|
+
|
55
|
+
module ClassMethods
|
56
|
+
def destroy_relationships_between(a, b)
|
57
|
+
between(a, b).destroy_all
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_support/core_ext/string/inflections"
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
module Interest
|
6
|
+
module Utils
|
7
|
+
class << self
|
8
|
+
def symbolic_name_of(object)
|
9
|
+
if object.is_a?(ActiveRecord::Base)
|
10
|
+
object.class.name
|
11
|
+
elsif object.is_a?(Class) and object < ActiveRecord::Base
|
12
|
+
object.name
|
13
|
+
else
|
14
|
+
object.to_s
|
15
|
+
end.underscore.pluralize
|
16
|
+
end
|
17
|
+
|
18
|
+
def source_type_of(object)
|
19
|
+
if object.is_a?(ActiveRecord::Base)
|
20
|
+
object.class.name
|
21
|
+
elsif object.is_a?(Class) and object < ActiveRecord::Base
|
22
|
+
object.name
|
23
|
+
else
|
24
|
+
object.to_s.classify
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Blockable" do
|
4
|
+
it "should block other" do
|
5
|
+
user = BlockableUser.create!
|
6
|
+
other_user = BlockableUser.create!
|
7
|
+
|
8
|
+
user.block(other_user)
|
9
|
+
|
10
|
+
expect(user).to be_blocking(other_user)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should not block self" do
|
14
|
+
user = BlockableUser.create!
|
15
|
+
|
16
|
+
user.block(user)
|
17
|
+
|
18
|
+
expect(user).not_to be_blocking(user)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not duplicate blockee" do
|
22
|
+
user = BlockableUser.create!
|
23
|
+
other_user = BlockableUser.create!
|
24
|
+
|
25
|
+
user.block(other_user)
|
26
|
+
user.block(other_user)
|
27
|
+
|
28
|
+
expect(user.blocking_relationships.count).to eq(1)
|
29
|
+
expect(user.blocking_blockable_users.count).to eq(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be a Blocking" do
|
33
|
+
user = BlockableUser.create!
|
34
|
+
other_user = BlockableUser.create!
|
35
|
+
|
36
|
+
user.block(other_user)
|
37
|
+
|
38
|
+
expect(user.blocking_relationships.of(BlockableUser)).to be_present.and all be_a Blocking
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be a model is blocked" do
|
42
|
+
user = BlockableUser.create!
|
43
|
+
other_user = BlockableUser.create!
|
44
|
+
collection = Collection.create!
|
45
|
+
|
46
|
+
user.block(other_user)
|
47
|
+
user.block(collection)
|
48
|
+
|
49
|
+
expect(user.blocking_blockable_users).to be_present.and all be_a BlockableUser
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should not block self and raise exception" do
|
53
|
+
user = BlockableUser.create!
|
54
|
+
|
55
|
+
expect { user.block!(user) }.to raise_error(Interest::Blockable::Rejected)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be followed by other user if user is not blocking one" do
|
59
|
+
user = FollowableAndBlockableUser.create!
|
60
|
+
other_user = FollowableAndBlockableUser.create!
|
61
|
+
|
62
|
+
expect { other_user.follow!(user) }.not_to raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should not be followed by other user if user is blocking one" do
|
66
|
+
user = FollowableAndBlockableUser.create!
|
67
|
+
other_user = FollowableAndBlockableUser.create!
|
68
|
+
|
69
|
+
user.block(other_user)
|
70
|
+
|
71
|
+
expect { other_user.follow!(user) }.to raise_error(Interest::Followable::Rejected)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should destroy their followship when either follower or followee blocks other" do
|
75
|
+
user = FollowableAndBlockableUser.create!
|
76
|
+
other_user = FollowableAndBlockableUser.create!
|
77
|
+
|
78
|
+
user.follow(other_user)
|
79
|
+
other_user.follow(user)
|
80
|
+
|
81
|
+
user.block(other_user)
|
82
|
+
|
83
|
+
expect(user).not_to be_following(other_user)
|
84
|
+
expect(other_user).not_to be_following(user)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should destroy their follow requests when either requester or requestee blocks other" do
|
88
|
+
user = FollowRequestableAndBlockableUser.create!
|
89
|
+
other_user = FollowRequestableAndBlockableUser.create!
|
90
|
+
|
91
|
+
user.request_to_follow(other_user)
|
92
|
+
other_user.request_to_follow(user)
|
93
|
+
|
94
|
+
user.block(other_user)
|
95
|
+
|
96
|
+
expect(user).not_to have_requested_to_follow(other_user)
|
97
|
+
expect(other_user).not_to have_been_requested_to_follow(user)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should find outgoing blocking of specified type" do
|
101
|
+
user = BlockableUser.create!
|
102
|
+
other_user1 = BlockableUser.create!
|
103
|
+
other_user2 = BlockableUser.create!
|
104
|
+
collection = Collection.create!
|
105
|
+
|
106
|
+
user.block(other_user1)
|
107
|
+
user.block(other_user2)
|
108
|
+
user.block(collection)
|
109
|
+
|
110
|
+
expect(user.blocking_relationships.of(BlockableUser)).to have_exactly(2).items
|
111
|
+
expect(user.blocking_relationships.of(Collection)).to have_exactly(1).items
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should find incoming blocking of specified type" do
|
115
|
+
user = BlockableUser.create!
|
116
|
+
other_user1 = BlockableUser.create!
|
117
|
+
other_user2 = BlockableUser.create!
|
118
|
+
collection = Collection.create!
|
119
|
+
|
120
|
+
other_user1.block(user)
|
121
|
+
other_user2.block(user)
|
122
|
+
collection.block(user)
|
123
|
+
|
124
|
+
expect(user.blocker_relationships.of(BlockableUser)).to have_exactly(2).items
|
125
|
+
expect(user.blocker_relationships.of(Collection)).to have_exactly(1).items
|
126
|
+
end
|
127
|
+
end
|