socialization 0.4.0 → 0.5.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -1
- data/CHANGELOG.md +41 -0
- data/README.md +246 -0
- data/demo/{demo_app/.gitignore → .gitignore} +0 -0
- data/demo/{demo_app/Gemfile → Gemfile} +1 -1
- data/demo/{demo_app/README.rdoc → README.rdoc} +0 -0
- data/demo/{demo_app/Rakefile → Rakefile} +0 -0
- data/demo/{demo_app/app → app}/assets/images/rails.png +0 -0
- data/demo/{demo_app/app → app}/assets/javascripts/application.js +0 -0
- data/demo/{demo_app/app → app}/assets/stylesheets/application.css +0 -0
- data/demo/{demo_app/app → app}/controllers/application_controller.rb +0 -0
- data/demo/{demo_app/app → app}/helpers/application_helper.rb +0 -0
- data/demo/{demo_app/app → app}/mailers/.gitkeep +0 -0
- data/demo/{demo_app/app → app}/models/.gitkeep +0 -0
- data/demo/{demo_app/app → app}/models/celebrity.rb +0 -0
- data/demo/{demo_app/app → app}/models/comment.rb +0 -0
- data/demo/app/models/follow.rb +2 -0
- data/demo/app/models/like.rb +2 -0
- data/demo/app/models/mention.rb +2 -0
- data/demo/{demo_app/app → app}/models/movie.rb +0 -0
- data/demo/{demo_app/app → app}/models/user.rb +0 -0
- data/demo/{demo_app/app → app}/views/layouts/application.html.erb +0 -0
- data/demo/{demo_app/config.ru → config.ru} +0 -0
- data/demo/{demo_app/config → config}/application.rb +0 -0
- data/demo/{demo_app/config → config}/boot.rb +0 -0
- data/demo/{demo_app/config → config}/database.yml +0 -0
- data/demo/{demo_app/config → config}/environment.rb +0 -0
- data/demo/{demo_app/config → config}/environments/development.rb +0 -0
- data/demo/{demo_app/config → config}/environments/production.rb +0 -0
- data/demo/{demo_app/config → config}/environments/test.rb +0 -0
- data/demo/{demo_app/config → config}/initializers/backtrace_silencers.rb +0 -0
- data/demo/{demo_app/config → config}/initializers/inflections.rb +0 -0
- data/demo/{demo_app/config → config}/initializers/mime_types.rb +0 -0
- data/demo/{demo_app/config → config}/initializers/secret_token.rb +0 -0
- data/demo/{demo_app/config → config}/initializers/session_store.rb +1 -1
- data/demo/{demo_app/config → config}/initializers/wrap_parameters.rb +1 -1
- data/demo/{demo_app/config → config}/locales/en.yml +0 -0
- data/demo/{demo_app/config → config}/routes.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120115051222_create_users.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120115051234_create_movies.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120115051255_create_celebrities.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120115054646_create_follows.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120115054647_create_likes.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120221200644_create_mentions.rb +0 -0
- data/demo/{demo_app/db → db}/migrate/20120221202703_create_comments.rb +0 -0
- data/demo/{demo_app/db → db}/schema.rb +0 -1
- data/demo/{demo_app/db → db}/seeds.rb +0 -0
- data/demo/{demo_app/lib → lib}/assets/.gitkeep +0 -0
- data/demo/{demo_app/lib → lib}/tasks/.gitkeep +0 -0
- data/demo/{demo_app/public → public}/404.html +0 -0
- data/demo/{demo_app/public → public}/422.html +0 -0
- data/demo/{demo_app/public → public}/500.html +0 -0
- data/demo/{demo_app/public → public}/favicon.ico +0 -0
- data/demo/{demo_app/public → public}/index.html +0 -0
- data/demo/{demo_app/public → public}/robots.txt +0 -0
- data/demo/{demo_app/script → script}/rails +0 -0
- data/demo/{demo_app/test → test}/fixtures/.gitkeep +0 -0
- data/demo/{demo_app/test → test}/fixtures/celebrities.yml +0 -0
- data/demo/{demo_app/test → test}/fixtures/movies.yml +0 -0
- data/demo/{demo_app/test → test}/fixtures/users.yml +0 -0
- data/demo/{demo_app/test → test}/functional/.gitkeep +0 -0
- data/demo/{demo_app/test → test}/integration/.gitkeep +0 -0
- data/demo/{demo_app/test → test}/performance/browsing_test.rb +0 -0
- data/demo/{demo_app/test → test}/test_helper.rb +0 -0
- data/demo/{demo_app/test → test}/unit/.gitkeep +0 -0
- data/demo/{demo_app/test → test}/unit/celebrity_test.rb +0 -0
- data/demo/{demo_app/test → test}/unit/movie_test.rb +0 -0
- data/demo/{demo_app/test → test}/unit/user_test.rb +0 -0
- data/demo/{demo_app/vendor → vendor}/assets/javascripts/.gitkeep +0 -0
- data/demo/{demo_app/vendor → vendor}/assets/stylesheets/.gitkeep +0 -0
- data/demo/{demo_app/vendor → vendor}/plugins/.gitkeep +0 -0
- data/lib/generators/socialization/socialization_generator.rb +20 -9
- data/{generators/socialization/templates → lib/generators/socialization/templates/active_record}/migration_follows.rb +0 -0
- data/{generators/socialization/templates → lib/generators/socialization/templates/active_record}/migration_likes.rb +0 -0
- data/{generators/socialization/templates → lib/generators/socialization/templates/active_record}/migration_mentions.rb +0 -0
- data/lib/generators/socialization/templates/active_record/model_follow.rb +2 -0
- data/lib/generators/socialization/templates/active_record/model_like.rb +2 -0
- data/lib/generators/socialization/templates/active_record/model_mention.rb +2 -0
- data/lib/socialization.rb +3 -5
- data/lib/socialization/actors/follower.rb +74 -0
- data/lib/socialization/actors/liker.rb +74 -0
- data/lib/socialization/actors/mentioner.rb +74 -0
- data/lib/socialization/acts_as_helpers.rb +43 -0
- data/lib/socialization/config.rb +45 -0
- data/lib/socialization/helpers/string.rb +17 -0
- data/lib/socialization/stores/active_record/follow_store.rb +143 -0
- data/lib/socialization/stores/active_record/like_store.rb +143 -0
- data/lib/socialization/stores/active_record/mention_store.rb +143 -0
- data/lib/socialization/stores/redis/base.rb +8 -0
- data/lib/socialization/stores/redis/config.rb +11 -0
- data/lib/socialization/stores/redis/follow_store.rb +126 -0
- data/lib/socialization/stores/redis/like_store.rb +126 -0
- data/lib/socialization/stores/redis/mention_store.rb +126 -0
- data/lib/socialization/version.rb +1 -1
- data/lib/socialization/victims/followable.rb +38 -0
- data/lib/socialization/victims/likeable.rb +38 -0
- data/lib/socialization/victims/mentionable.rb +38 -0
- data/socialization.gemspec +3 -3
- data/test/actors/follower_test.rb +74 -0
- data/test/actors/liker_test.rb +74 -0
- data/test/actors/mentioner_test.rb +74 -0
- data/test/stores/active_record/follow_store_test.rb +121 -0
- data/test/stores/active_record/like_store_test.rb +121 -0
- data/test/stores/active_record/mention_store_test.rb +121 -0
- data/test/stores/redis/config_test.rb +30 -0
- data/test/stores/redis/follow_store_test.rb +153 -0
- data/test/stores/redis/like_store_test.rb +153 -0
- data/test/stores/redis/mention_store_test.rb +153 -0
- data/test/string_test.rb +13 -0
- data/test/test_helper.rb +70 -12
- data/test/victims/followable_test.rb +34 -0
- data/test/victims/likeable_test.rb +34 -0
- data/test/victims/mentionable_test.rb +34 -0
- data/test/world_test.rb +80 -69
- metadata +261 -176
- data/README.rdoc +0 -186
- data/demo/demo_app/app/models/follow.rb +0 -3
- data/demo/demo_app/app/models/like.rb +0 -3
- data/demo/demo_app/app/models/mention.rb +0 -3
- data/demo/demo_app/doc/README_FOR_APP +0 -2
- data/gemfiles/activerecord30.gemfile +0 -6
- data/gemfiles/activerecord30.gemfile.lock +0 -23
- data/gemfiles/activerecord31.gemfile +0 -6
- data/gemfiles/activerecord31.gemfile.lock +0 -25
- data/gemfiles/activerecord32.gemfile +0 -6
- data/gemfiles/activerecord32.gemfile.lock +0 -25
- data/generators/socialization/USAGE +0 -1
- data/generators/socialization/socialization_generator.rb +0 -15
- data/generators/socialization/templates/model_follow.rb +0 -3
- data/generators/socialization/templates/model_like.rb +0 -3
- data/generators/socialization/templates/model_mention.rb +0 -3
- data/lib/socialization/follow_store.rb +0 -14
- data/lib/socialization/followable.rb +0 -34
- data/lib/socialization/follower.rb +0 -50
- data/lib/socialization/hello.rb +0 -53
- data/lib/socialization/like_store.rb +0 -14
- data/lib/socialization/likeable.rb +0 -34
- data/lib/socialization/liker.rb +0 -54
- data/lib/socialization/mention_store.rb +0 -14
- data/lib/socialization/mentionable.rb +0 -36
- data/lib/socialization/mentioner.rb +0 -54
- data/test/follow_test.rb +0 -125
- data/test/like_test.rb +0 -125
- data/test/mention_test.rb +0 -116
@@ -0,0 +1,126 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/base'
|
2
|
+
|
3
|
+
module Socialization
|
4
|
+
module RedisStores
|
5
|
+
class FollowStore < Socialization::RedisStores::Base
|
6
|
+
class << self
|
7
|
+
def follow!(follower, followable)
|
8
|
+
unless follows?(follower, followable)
|
9
|
+
Socialization.redis.sadd generate_followers_key(follower, followable), follower.id
|
10
|
+
Socialization.redis.sadd generate_followables_key(follower, followable), followable.id
|
11
|
+
|
12
|
+
call_after_create_hook(follower, followable)
|
13
|
+
follower.touch if [:all, :follower].include?(touch) && follower.respond_to?(:touch)
|
14
|
+
followable.touch if [:all, :followable].include?(touch) && followable.respond_to?(:touch)
|
15
|
+
true
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def unfollow!(follower, followable)
|
22
|
+
if follows?(follower, followable)
|
23
|
+
Socialization.redis.srem generate_followers_key(follower, followable), follower.id
|
24
|
+
Socialization.redis.srem generate_followables_key(follower, followable), followable.id
|
25
|
+
|
26
|
+
call_after_destroy_hook(follower, followable)
|
27
|
+
follower.touch if [:all, :follower].include?(touch) && follower.respond_to?(:touch)
|
28
|
+
followable.touch if [:all, :followable].include?(touch) && followable.respond_to?(:touch)
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def follows?(follower, followable)
|
36
|
+
Socialization.redis.sismember generate_followers_key(follower, followable), follower.id
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns an ActiveRecord::Relation of all the followers of a certain type that are following followable
|
40
|
+
def followers_relation(followable, klass, opts = {})
|
41
|
+
ids = followers(followable, klass, :pluck => :id)
|
42
|
+
klass.where('id IN (?)', ids)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns all the followers of a certain type that are following followable
|
46
|
+
def followers(followable, klass, opts = {})
|
47
|
+
if opts[:pluck]
|
48
|
+
Socialization.redis.smembers(generate_followers_key(klass, followable)).map { |id|
|
49
|
+
id.to_i if id.is_integer?
|
50
|
+
}
|
51
|
+
else
|
52
|
+
followers_relation(followable, klass, opts).all
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns an ActiveRecord::Relation of all the followables of a certain type that are followed by follower
|
57
|
+
def followables_relation(follower, klass, opts = {})
|
58
|
+
ids = followables(follower, klass, :pluck => :id)
|
59
|
+
klass.where('id IN (?)', ids)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all the followables of a certain type that are followed by follower
|
63
|
+
def followables(follower, klass, opts = {})
|
64
|
+
if opts[:pluck]
|
65
|
+
Socialization.redis.smembers(generate_followables_key(follower, klass)).map { |id|
|
66
|
+
id.to_i if id.is_integer?
|
67
|
+
}
|
68
|
+
else
|
69
|
+
followables_relation(follower, klass, opts).all
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def touch(what = nil)
|
74
|
+
if what.nil?
|
75
|
+
@touch || false
|
76
|
+
else
|
77
|
+
raise ArgumentError unless [:all, :follower, :followable, false, nil].include?(what)
|
78
|
+
@touch = what
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def after_follow(method)
|
83
|
+
raise ArgumentError unless method.is_a?(Symbol) || method.nil?
|
84
|
+
@after_create_hook = method
|
85
|
+
end
|
86
|
+
|
87
|
+
def after_unfollow(method)
|
88
|
+
raise ArgumentError unless method.is_a?(Symbol) || method.nil?
|
89
|
+
@after_destroy_hook = method
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def call_after_create_hook(follower, followable)
|
94
|
+
self.send(@after_create_hook, follower, followable) if @after_create_hook
|
95
|
+
end
|
96
|
+
|
97
|
+
def call_after_destroy_hook(follower, followable)
|
98
|
+
self.send(@after_destroy_hook, follower, followable) if @after_destroy_hook
|
99
|
+
end
|
100
|
+
|
101
|
+
def generate_followers_key(follower, followable)
|
102
|
+
raise ArgumentError.new("`followable` needs to be an acts_as_followable objecs, not a class.") if followable.class == Class
|
103
|
+
follower_class = if follower.class == Class
|
104
|
+
follower
|
105
|
+
else
|
106
|
+
follower.class
|
107
|
+
end
|
108
|
+
|
109
|
+
"Followers:#{followable.class}:#{followable.id}:#{follower_class}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def generate_followables_key(follower, followable)
|
113
|
+
raise ArgumentError.new("`follower` needs to be an acts_as_follower object, not a class.") if follower.class == Class
|
114
|
+
followable_class = if followable.class == Class
|
115
|
+
followable
|
116
|
+
else
|
117
|
+
followable.class
|
118
|
+
end
|
119
|
+
|
120
|
+
"Followables:#{follower.class}:#{follower.id}:#{followable_class}"
|
121
|
+
end
|
122
|
+
end # class << self
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/base'
|
2
|
+
|
3
|
+
module Socialization
|
4
|
+
module RedisStores
|
5
|
+
class LikeStore < Socialization::RedisStores::Base
|
6
|
+
class << self
|
7
|
+
def like!(liker, likeable)
|
8
|
+
unless likes?(liker, likeable)
|
9
|
+
Socialization.redis.sadd generate_likers_key(liker, likeable), liker.id
|
10
|
+
Socialization.redis.sadd generate_likeables_key(liker, likeable), likeable.id
|
11
|
+
|
12
|
+
call_after_create_hook(liker, likeable)
|
13
|
+
liker.touch if [:all, :liker].include?(touch) && liker.respond_to?(:touch)
|
14
|
+
likeable.touch if [:all, :likeable].include?(touch) && likeable.respond_to?(:touch)
|
15
|
+
true
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def unlike!(liker, likeable)
|
22
|
+
if likes?(liker, likeable)
|
23
|
+
Socialization.redis.srem generate_likers_key(liker, likeable), liker.id
|
24
|
+
Socialization.redis.srem generate_likeables_key(liker, likeable), likeable.id
|
25
|
+
|
26
|
+
call_after_destroy_hook(liker, likeable)
|
27
|
+
liker.touch if [:all, :liker].include?(touch) && liker.respond_to?(:touch)
|
28
|
+
likeable.touch if [:all, :likeable].include?(touch) && likeable.respond_to?(:touch)
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def likes?(liker, likeable)
|
36
|
+
Socialization.redis.sismember generate_likers_key(liker, likeable), liker.id
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns an ActiveRecord::Relation of all the likers of a certain type that are likeing likeable
|
40
|
+
def likers_relation(likeable, klass, opts = {})
|
41
|
+
ids = likers(likeable, klass, :pluck => :id)
|
42
|
+
klass.where('id IN (?)', ids)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns all the likers of a certain type that are likeing likeable
|
46
|
+
def likers(likeable, klass, opts = {})
|
47
|
+
if opts[:pluck]
|
48
|
+
Socialization.redis.smembers(generate_likers_key(klass, likeable)).map { |id|
|
49
|
+
id.to_i if id.is_integer?
|
50
|
+
}
|
51
|
+
else
|
52
|
+
likers_relation(likeable, klass, opts).all
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns an ActiveRecord::Relation of all the likeables of a certain type that are liked by liker
|
57
|
+
def likeables_relation(liker, klass, opts = {})
|
58
|
+
ids = likeables(liker, klass, :pluck => :id)
|
59
|
+
klass.where('id IN (?)', ids)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all the likeables of a certain type that are liked by liker
|
63
|
+
def likeables(liker, klass, opts = {})
|
64
|
+
if opts[:pluck]
|
65
|
+
Socialization.redis.smembers(generate_likeables_key(liker, klass)).map { |id|
|
66
|
+
id.to_i if id.is_integer?
|
67
|
+
}
|
68
|
+
else
|
69
|
+
likeables_relation(liker, klass, opts).all
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def touch(what = nil)
|
74
|
+
if what.nil?
|
75
|
+
@touch || false
|
76
|
+
else
|
77
|
+
raise ArgumentError unless [:all, :liker, :likeable, false, nil].include?(what)
|
78
|
+
@touch = what
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def after_like(method)
|
83
|
+
raise ArgumentError unless method.is_a?(Symbol) || method.nil?
|
84
|
+
@after_create_hook = method
|
85
|
+
end
|
86
|
+
|
87
|
+
def after_unlike(method)
|
88
|
+
raise ArgumentError unless method.is_a?(Symbol) || method.nil?
|
89
|
+
@after_destroy_hook = method
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def call_after_create_hook(liker, likeable)
|
94
|
+
self.send(@after_create_hook, liker, likeable) if @after_create_hook
|
95
|
+
end
|
96
|
+
|
97
|
+
def call_after_destroy_hook(liker, likeable)
|
98
|
+
self.send(@after_destroy_hook, liker, likeable) if @after_destroy_hook
|
99
|
+
end
|
100
|
+
|
101
|
+
def generate_likers_key(liker, likeable)
|
102
|
+
raise ArgumentError.new("`likeable` needs to be an acts_as_likeable objecs, not a class.") if likeable.class == Class
|
103
|
+
liker_class = if liker.class == Class
|
104
|
+
liker
|
105
|
+
else
|
106
|
+
liker.class
|
107
|
+
end
|
108
|
+
|
109
|
+
"Likers:#{likeable.class}:#{likeable.id}:#{liker_class}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def generate_likeables_key(liker, likeable)
|
113
|
+
raise ArgumentError.new("`liker` needs to be an acts_as_liker object, not a class.") if liker.class == Class
|
114
|
+
likeable_class = if likeable.class == Class
|
115
|
+
likeable
|
116
|
+
else
|
117
|
+
likeable.class
|
118
|
+
end
|
119
|
+
|
120
|
+
"Likeables:#{liker.class}:#{liker.id}:#{likeable_class}"
|
121
|
+
end
|
122
|
+
end # class << self
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/base'
|
2
|
+
|
3
|
+
module Socialization
|
4
|
+
module RedisStores
|
5
|
+
class MentionStore < Socialization::RedisStores::Base
|
6
|
+
class << self
|
7
|
+
def mention!(mentioner, mentionable)
|
8
|
+
unless mentions?(mentioner, mentionable)
|
9
|
+
Socialization.redis.sadd generate_mentioners_key(mentioner, mentionable), mentioner.id
|
10
|
+
Socialization.redis.sadd generate_mentionables_key(mentioner, mentionable), mentionable.id
|
11
|
+
|
12
|
+
call_after_create_hook(mentioner, mentionable)
|
13
|
+
mentioner.touch if [:all, :mentioner].include?(touch) && mentioner.respond_to?(:touch)
|
14
|
+
mentionable.touch if [:all, :mentionable].include?(touch) && mentionable.respond_to?(:touch)
|
15
|
+
true
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def unmention!(mentioner, mentionable)
|
22
|
+
if mentions?(mentioner, mentionable)
|
23
|
+
Socialization.redis.srem generate_mentioners_key(mentioner, mentionable), mentioner.id
|
24
|
+
Socialization.redis.srem generate_mentionables_key(mentioner, mentionable), mentionable.id
|
25
|
+
|
26
|
+
call_after_destroy_hook(mentioner, mentionable)
|
27
|
+
mentioner.touch if [:all, :mentioner].include?(touch) && mentioner.respond_to?(:touch)
|
28
|
+
mentionable.touch if [:all, :mentionable].include?(touch) && mentionable.respond_to?(:touch)
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def mentions?(mentioner, mentionable)
|
36
|
+
Socialization.redis.sismember generate_mentioners_key(mentioner, mentionable), mentioner.id
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns an ActiveRecord::Relation of all the mentioners of a certain type that are mentioning mentionable
|
40
|
+
def mentioners_relation(mentionable, klass, opts = {})
|
41
|
+
ids = mentioners(mentionable, klass, :pluck => :id)
|
42
|
+
klass.where('id IN (?)', ids)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns all the mentioners of a certain type that are mentioning mentionable
|
46
|
+
def mentioners(mentionable, klass, opts = {})
|
47
|
+
if opts[:pluck]
|
48
|
+
Socialization.redis.smembers(generate_mentioners_key(klass, mentionable)).map { |id|
|
49
|
+
id.to_i if id.is_integer?
|
50
|
+
}
|
51
|
+
else
|
52
|
+
mentioners_relation(mentionable, klass, opts).all
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns an ActiveRecord::Relation of all the mentionables of a certain type that are mentioned by mentioner
|
57
|
+
def mentionables_relation(mentioner, klass, opts = {})
|
58
|
+
ids = mentionables(mentioner, klass, :pluck => :id)
|
59
|
+
klass.where('id IN (?)', ids)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all the mentionables of a certain type that are mentioned by mentioner
|
63
|
+
def mentionables(mentioner, klass, opts = {})
|
64
|
+
if opts[:pluck]
|
65
|
+
Socialization.redis.smembers(generate_mentionables_key(mentioner, klass)).map { |id|
|
66
|
+
id.to_i if id.is_integer?
|
67
|
+
}
|
68
|
+
else
|
69
|
+
mentionables_relation(mentioner, klass, opts).all
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def touch(what = nil)
|
74
|
+
if what.nil?
|
75
|
+
@touch || false
|
76
|
+
else
|
77
|
+
raise ArgumentError unless [:all, :mentioner, :mentionable, false, nil].include?(what)
|
78
|
+
@touch = what
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def after_mention(method)
|
83
|
+
raise ArgumentError unless method.is_a?(Symbol) || method.nil?
|
84
|
+
@after_create_hook = method
|
85
|
+
end
|
86
|
+
|
87
|
+
def after_unmention(method)
|
88
|
+
raise ArgumentError unless method.is_a?(Symbol) || method.nil?
|
89
|
+
@after_destroy_hook = method
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def call_after_create_hook(mentioner, mentionable)
|
94
|
+
self.send(@after_create_hook, mentioner, mentionable) if @after_create_hook
|
95
|
+
end
|
96
|
+
|
97
|
+
def call_after_destroy_hook(mentioner, mentionable)
|
98
|
+
self.send(@after_destroy_hook, mentioner, mentionable) if @after_destroy_hook
|
99
|
+
end
|
100
|
+
|
101
|
+
def generate_mentioners_key(mentioner, mentionable)
|
102
|
+
raise ArgumentError.new("`mentionable` needs to be an acts_as_mentionable objecs, not a class.") if mentionable.class == Class
|
103
|
+
mentioner_class = if mentioner.class == Class
|
104
|
+
mentioner
|
105
|
+
else
|
106
|
+
mentioner.class
|
107
|
+
end
|
108
|
+
|
109
|
+
"Mentioners:#{mentionable.class}:#{mentionable.id}:#{mentioner_class}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def generate_mentionables_key(mentioner, mentionable)
|
113
|
+
raise ArgumentError.new("`mentioner` needs to be an acts_as_mentioner object, not a class.") if mentioner.class == Class
|
114
|
+
mentionable_class = if mentionable.class == Class
|
115
|
+
mentionable
|
116
|
+
else
|
117
|
+
mentionable.class
|
118
|
+
end
|
119
|
+
|
120
|
+
"Mentionables:#{mentioner.class}:#{mentioner.id}:#{mentionable_class}"
|
121
|
+
end
|
122
|
+
end # class << self
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def is_followable?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Socialization
|
10
|
+
module Followable
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
# Specifies if self can be followed.
|
15
|
+
#
|
16
|
+
# @return [Boolean]
|
17
|
+
def is_followable?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Specifies if self is followed by a {Follower} object.
|
22
|
+
#
|
23
|
+
# @return [Boolean]
|
24
|
+
def followed_by?(follower)
|
25
|
+
raise ArgumentError, "#{follower} is not follower!" unless follower.respond_to?(:is_follower?) && follower.is_follower?
|
26
|
+
Socialization.follow_model.follows?(follower, self)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a scope of the {Follower}s following self.
|
30
|
+
#
|
31
|
+
# @param [Class] klass the {Follower} class to be included in the scope. e.g. `User`
|
32
|
+
# @return [Array<Follower, Numeric>] An array of Follower objects or IDs
|
33
|
+
def followers(klass, opts = {})
|
34
|
+
Socialization.follow_model.followers(self, klass, opts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def is_likeable?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Socialization
|
10
|
+
module Likeable
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
# Specifies if self can be liked.
|
15
|
+
#
|
16
|
+
# @return [Boolean]
|
17
|
+
def is_likeable?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Specifies if self is liked by a {Liker} object.
|
22
|
+
#
|
23
|
+
# @return [Boolean]
|
24
|
+
def liked_by?(liker)
|
25
|
+
raise ArgumentError, "#{liker} is not liker!" unless liker.respond_to?(:is_liker?) && liker.is_liker?
|
26
|
+
Socialization.like_model.likes?(liker, self)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a scope of the {Liker}s likeing self.
|
30
|
+
#
|
31
|
+
# @param [Class] klass the {Liker} class to be included in the scope. e.g. `User`.
|
32
|
+
# @return [Array<Liker, Numeric>] An array of Liker objects or IDs
|
33
|
+
def likers(klass, opts = {})
|
34
|
+
Socialization.like_model.likers(self, klass, opts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|