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,14 @@
|
|
1
|
+
class InterestBlockingsMigration < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :blockings do |t|
|
4
|
+
t.belongs_to :blocker, polymorphic: true, null: false
|
5
|
+
t.belongs_to :blockee, polymorphic: true, null: false
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :blockings, [:blocker_id, :blocker_type], name: :index_blockings_blocker
|
11
|
+
add_index :blockings, [:blockee_id, :blockee_type], name: :index_blockings_blockee
|
12
|
+
add_index :blockings, [:blocker_id, :blocker_type, :blockee_id, :blockee_type], unique: true, name: :index_blockings_uniqueness
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class InterestFollowingsMigration < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :followings do |t|
|
4
|
+
t.belongs_to :follower, polymorphic: true, null: false
|
5
|
+
t.belongs_to :followee, polymorphic: true, null: false
|
6
|
+
t.string :status, null: false
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :followings, [:follower_id, :follower_type], name: :index_followings_follower
|
12
|
+
add_index :followings, [:followee_id, :followee_type], name: :index_followings_followee
|
13
|
+
add_index :followings, [:follower_id, :follower_type, :followee_id, :followee_type], unique: true, name: :index_followings_uniqueness
|
14
|
+
end
|
15
|
+
end
|
data/lib/interest.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "interest/version"
|
2
|
+
require "interest/base"
|
3
|
+
require "interest/followable"
|
4
|
+
require "interest/follow_requestable"
|
5
|
+
require "interest/blockable"
|
6
|
+
require "active_support"
|
7
|
+
require "active_support/core_ext/string/inflections"
|
8
|
+
require "active_record"
|
9
|
+
|
10
|
+
module Interest
|
11
|
+
module Extension
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
include Base
|
16
|
+
extend Followable::Extension
|
17
|
+
extend FollowRequestable::Extension
|
18
|
+
extend Blockable::Extension
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def interest
|
23
|
+
acts_as_followable
|
24
|
+
acts_as_follow_requestable
|
25
|
+
acts_as_blockable
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def following_class_name
|
32
|
+
"::Following"
|
33
|
+
end
|
34
|
+
|
35
|
+
def following_class
|
36
|
+
@following_class ||= following_class_name.constantize
|
37
|
+
end
|
38
|
+
|
39
|
+
def blocking_class_name
|
40
|
+
"::Blocking"
|
41
|
+
end
|
42
|
+
|
43
|
+
def blocking_class
|
44
|
+
@blocking_class ||= blocking_class_name.constantize
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
ActiveRecord::Base.__send__ :include, Interest::Extension
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "interest/followable"
|
3
|
+
require "interest/follow_requestable"
|
4
|
+
require "interest/blockable"
|
5
|
+
|
6
|
+
module Interest
|
7
|
+
module Base
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
def followable?(other)
|
11
|
+
is_a?(Interest::Followable::Follower) and other.is_a?(Interest::Followable::Followee)
|
12
|
+
end
|
13
|
+
|
14
|
+
def follow_requestable?(other)
|
15
|
+
followable?(other) and is_a?(Interest::FollowRequestable::FollowRequester) and other.is_a?(Interest::FollowRequestable::FollowRequestee)
|
16
|
+
end
|
17
|
+
|
18
|
+
def blockable?(other)
|
19
|
+
is_a?(Interest::Blockable::Blocker) and other.is_a?(Interest::Blockable::Blockee)
|
20
|
+
end
|
21
|
+
|
22
|
+
def follower?
|
23
|
+
is_a? Interest::Followable::Follower
|
24
|
+
end
|
25
|
+
|
26
|
+
def followee?
|
27
|
+
is_a? Interest::Followable::Followee
|
28
|
+
end
|
29
|
+
|
30
|
+
def follow_requester?
|
31
|
+
is_a? Interest::FollowRequestable::FollowRequester
|
32
|
+
end
|
33
|
+
|
34
|
+
def follow_requestee?
|
35
|
+
is_a? Interest::FollowRequestable::FollowRequestee
|
36
|
+
end
|
37
|
+
|
38
|
+
def blocker?
|
39
|
+
is_a? Interest::Blockable::Blocker
|
40
|
+
end
|
41
|
+
|
42
|
+
def blockee?
|
43
|
+
is_a? Interest::Blockable::Blockee
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "interest/blockable/exceptions"
|
2
|
+
require "interest/blockable/blocking"
|
3
|
+
require "interest/blockable/blocker"
|
4
|
+
require "interest/blockable/blockee"
|
5
|
+
|
6
|
+
module Interest
|
7
|
+
module Blockable
|
8
|
+
module Extension
|
9
|
+
def acts_as_blocker
|
10
|
+
include Blocker
|
11
|
+
define_blocker_association_methods
|
12
|
+
end
|
13
|
+
|
14
|
+
def acts_as_blockee
|
15
|
+
include Blockee
|
16
|
+
define_blockee_association_methods
|
17
|
+
end
|
18
|
+
|
19
|
+
def acts_as_blockable
|
20
|
+
acts_as_blocker
|
21
|
+
acts_as_blockee
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "interest/definition"
|
3
|
+
|
4
|
+
module Interest
|
5
|
+
module Blockable
|
6
|
+
module Blockee
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
include Interest::Definition.instance_methods_for(:blockee, :blocker)
|
10
|
+
|
11
|
+
def blocked_by?(blocker)
|
12
|
+
blockee_collection_for(blockee).include? blocker
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
include Interest::Definition.class_methods_for(:blockee, :blocker)
|
17
|
+
|
18
|
+
def define_blockee_association_methods
|
19
|
+
has_many :blocker_relationships,
|
20
|
+
-> { uniq },
|
21
|
+
as: :blockee,
|
22
|
+
dependent: :destroy,
|
23
|
+
class_name: Interest.blocking_class_name do
|
24
|
+
include Interest::Definition.collection_methods_for(:blocker)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def define_blockee_association_method(source_type)
|
29
|
+
association_method_name = blockee_association_method_name_for source_type
|
30
|
+
|
31
|
+
has_many association_method_name,
|
32
|
+
-> { uniq },
|
33
|
+
through: :blocker_relationships,
|
34
|
+
source: :blocker,
|
35
|
+
source_type: source_type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_record"
|
3
|
+
require "interest/definition"
|
4
|
+
require "interest/blockable/exceptions"
|
5
|
+
require "interest/blockable/blockee"
|
6
|
+
|
7
|
+
module Interest
|
8
|
+
module Blockable
|
9
|
+
module Blocker
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
include Interest::Definition.instance_methods_for(:blocker, :blocking)
|
13
|
+
|
14
|
+
def followable?(other)
|
15
|
+
super and not (other.blockee? and blocking?(other)) and not (blockee? and other.blocker? and other.blocking? self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def blocking?(blockee)
|
19
|
+
blocker_collection_for(blockee).include? blockee
|
20
|
+
end
|
21
|
+
|
22
|
+
def block(blockee, raise_record_invalid = false)
|
23
|
+
blocking_relationships.create!(blockee: blockee)
|
24
|
+
rescue ActiveRecord::RecordInvalid => exception
|
25
|
+
raise_record_invalid ? (raise exception) : nil
|
26
|
+
rescue ActiveRecord::RecordNotUnique
|
27
|
+
blocking_relationships.find_by(blockee: blockee)
|
28
|
+
end
|
29
|
+
|
30
|
+
def block!(blockee)
|
31
|
+
block(blockee, true)
|
32
|
+
rescue ActiveRecord::RecordInvalid => exception
|
33
|
+
raise Interest::Blockable::Rejected.new(exception)
|
34
|
+
end
|
35
|
+
|
36
|
+
def unblock(blockee)
|
37
|
+
blocker_collection_for(blockee).delete blockee
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid_blocking_for?(blockee)
|
41
|
+
not (self == blockee or not blockable?(blockee))
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
include Interest::Definition.class_methods_for(:blocker, :blocking)
|
46
|
+
|
47
|
+
def define_blocker_association_methods
|
48
|
+
has_many :blocking_relationships,
|
49
|
+
-> { uniq },
|
50
|
+
as: :blocker,
|
51
|
+
dependent: :destroy,
|
52
|
+
class_name: Interest.blocking_class_name do
|
53
|
+
include Interest::Definition.collection_methods_for(:blockee)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def define_blocker_association_method(source_type)
|
58
|
+
association_method_name = blocker_association_method_name_for source_type
|
59
|
+
|
60
|
+
has_many association_method_name,
|
61
|
+
-> { uniq },
|
62
|
+
through: :blocking_relationships,
|
63
|
+
source: :blockee,
|
64
|
+
source_type: source_type
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "active_support"
|
2
|
+
|
3
|
+
module Interest
|
4
|
+
module Blockable
|
5
|
+
module Blocking
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
belongs_to :blocker, polymorphic: true
|
10
|
+
belongs_to :blockee, polymorphic: true
|
11
|
+
|
12
|
+
validates :blocker, presence: true
|
13
|
+
validates :blockee, presence: true
|
14
|
+
|
15
|
+
validate :validate_blocking_relationships, if: :should_validate_blocking_relationships?
|
16
|
+
|
17
|
+
scope :between, ->(a, b) {
|
18
|
+
a_to_b = where(blocker: a, blockee: b).where_values.reduce(:and)
|
19
|
+
b_to_a = where(blocker: b, blockee: a).where_values.reduce(:and)
|
20
|
+
|
21
|
+
where a_to_b.or(b_to_a)
|
22
|
+
}
|
23
|
+
|
24
|
+
after_create :destroy_following_relationships
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy_following_relationships
|
28
|
+
Interest.following_class.destroy_relationships_between blocker, blockee
|
29
|
+
end
|
30
|
+
|
31
|
+
def should_validate_blocking_relationships?
|
32
|
+
blocker.is_a?(ActiveRecord::Base) and blockee.is_a?(ActiveRecord::Base)
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_blocking_relationships
|
36
|
+
errors.add :blocker, :invalid unless blocker.blocker?
|
37
|
+
errors.add :blockee, :invalid unless blockee.blockee?
|
38
|
+
errors.add :blockee, :rejected if blocker.blocker? and not blocker.valid_blocking_for?(blockee)
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
def destroy_relationships_between(a, b)
|
43
|
+
between(a, b).destroy_all
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_support/core_ext/string/inflections"
|
3
|
+
require "interest/utils"
|
4
|
+
|
5
|
+
module Interest
|
6
|
+
module Definition
|
7
|
+
class << self
|
8
|
+
def instance_methods_for(source, target)
|
9
|
+
Module.new do
|
10
|
+
define_method :"#{source}_collection_for" do |record|
|
11
|
+
__send__ self.class.__send__(:"#{source}_association_method_name_for", record)
|
12
|
+
end
|
13
|
+
|
14
|
+
define_method :method_missing do |name, *args, &block|
|
15
|
+
return super(name, *args, &block) unless matches = /\A#{target}_(?<type>.+)\Z/.match(name.to_s)
|
16
|
+
|
17
|
+
self.class.__send__ :"define_#{source}_association_method", Interest::Utils.source_type_of(matches[:type])
|
18
|
+
|
19
|
+
__send__ name, *args, &block
|
20
|
+
end
|
21
|
+
|
22
|
+
define_method :respond_to_missing? do |name, include_private = false|
|
23
|
+
!! (super(name, include_private) or /\A#{target}_.+\Z/ =~ name.to_s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def class_methods_for(source, target)
|
29
|
+
Module.new do
|
30
|
+
define_method :"#{source}_association_method_name_for" do |record|
|
31
|
+
:"#{target}_#{Interest::Utils.symbolic_name_of record}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def collection_methods_for(target)
|
37
|
+
Module.new do
|
38
|
+
define_method :of do |*args|
|
39
|
+
where :"#{target}_type" => args.map(&Interest::Utils.method(:source_type_of))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "interest/follow_requestable/exceptions"
|
2
|
+
require "interest/follow_requestable/follow_requester"
|
3
|
+
require "interest/follow_requestable/follow_requestee"
|
4
|
+
require "interest/follow_requestable/follow_request"
|
5
|
+
|
6
|
+
module Interest
|
7
|
+
module FollowRequestable
|
8
|
+
module Extension
|
9
|
+
def acts_as_follow_requester
|
10
|
+
include FollowRequester
|
11
|
+
define_follow_requester_association_methods
|
12
|
+
end
|
13
|
+
|
14
|
+
def acts_as_follow_requestee
|
15
|
+
include FollowRequestee
|
16
|
+
define_follow_requestee_association_methods
|
17
|
+
end
|
18
|
+
|
19
|
+
def acts_as_follow_requestable
|
20
|
+
acts_as_follow_requester
|
21
|
+
acts_as_follow_requestee
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|