twrk-socialization 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/Appraisals +23 -0
- data/CHANGELOG.md +67 -0
- data/Gemfile +3 -0
- data/Guardfile +12 -0
- data/LICENSE +20 -0
- data/README.md +298 -0
- data/Rakefile +14 -0
- data/demo/.gitignore +15 -0
- data/demo/Gemfile +35 -0
- data/demo/README.rdoc +261 -0
- data/demo/Rakefile +7 -0
- data/demo/app/assets/images/rails.png +0 -0
- data/demo/app/assets/javascripts/application.js +15 -0
- data/demo/app/assets/stylesheets/application.css +13 -0
- data/demo/app/controllers/application_controller.rb +3 -0
- data/demo/app/helpers/application_helper.rb +2 -0
- data/demo/app/mailers/.gitkeep +0 -0
- data/demo/app/models/.gitkeep +0 -0
- data/demo/app/models/celebrity.rb +4 -0
- data/demo/app/models/comment.rb +5 -0
- data/demo/app/models/follow.rb +3 -0
- data/demo/app/models/like.rb +2 -0
- data/demo/app/models/mention.rb +2 -0
- data/demo/app/models/movie.rb +3 -0
- data/demo/app/models/user.rb +7 -0
- data/demo/app/views/layouts/application.html.erb +14 -0
- data/demo/config/application.rb +59 -0
- data/demo/config/boot.rb +6 -0
- data/demo/config/database.yml +25 -0
- data/demo/config/environment.rb +5 -0
- data/demo/config/environments/development.rb +37 -0
- data/demo/config/environments/production.rb +67 -0
- data/demo/config/environments/test.rb +37 -0
- data/demo/config/initializers/backtrace_silencers.rb +7 -0
- data/demo/config/initializers/inflections.rb +15 -0
- data/demo/config/initializers/mime_types.rb +5 -0
- data/demo/config/initializers/secret_token.rb +7 -0
- data/demo/config/initializers/session_store.rb +8 -0
- data/demo/config/initializers/wrap_parameters.rb +14 -0
- data/demo/config/locales/en.yml +5 -0
- data/demo/config/routes.rb +58 -0
- data/demo/config.ru +4 -0
- data/demo/db/migrate/20120115051222_create_users.rb +9 -0
- data/demo/db/migrate/20120115051234_create_movies.rb +9 -0
- data/demo/db/migrate/20120115051255_create_celebrities.rb +9 -0
- data/demo/db/migrate/20120115054646_create_follows.rb +14 -0
- data/demo/db/migrate/20120115054647_create_likes.rb +14 -0
- data/demo/db/migrate/20120221200644_create_mentions.rb +14 -0
- data/demo/db/migrate/20120221202703_create_comments.rb +9 -0
- data/demo/db/schema.rb +72 -0
- data/demo/db/seeds.rb +17 -0
- data/demo/lib/assets/.gitkeep +0 -0
- data/demo/lib/tasks/.gitkeep +0 -0
- data/demo/public/404.html +26 -0
- data/demo/public/422.html +26 -0
- data/demo/public/500.html +25 -0
- data/demo/public/favicon.ico +0 -0
- data/demo/public/index.html +204 -0
- data/demo/public/robots.txt +5 -0
- data/demo/script/rails +6 -0
- data/demo/test/fixtures/.gitkeep +0 -0
- data/demo/test/fixtures/celebrities.yml +7 -0
- data/demo/test/fixtures/movies.yml +7 -0
- data/demo/test/fixtures/users.yml +7 -0
- data/demo/test/functional/.gitkeep +0 -0
- data/demo/test/integration/.gitkeep +0 -0
- data/demo/test/performance/browsing_test.rb +12 -0
- data/demo/test/test_helper.rb +13 -0
- data/demo/test/unit/.gitkeep +0 -0
- data/demo/test/unit/celebrity_test.rb +7 -0
- data/demo/test/unit/movie_test.rb +7 -0
- data/demo/test/unit/user_test.rb +7 -0
- data/demo/vendor/assets/javascripts/.gitkeep +0 -0
- data/demo/vendor/assets/stylesheets/.gitkeep +0 -0
- data/demo/vendor/plugins/.gitkeep +0 -0
- data/init.rb +1 -0
- data/lib/generators/socialization/socialization_generator.rb +38 -0
- data/lib/generators/socialization/templates/active_record/migration_follows.rb +14 -0
- data/lib/generators/socialization/templates/active_record/migration_likes.rb +14 -0
- data/lib/generators/socialization/templates/active_record/migration_mentions.rb +14 -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/generators/socialization/templates/redis/model_follow.rb +2 -0
- data/lib/generators/socialization/templates/redis/model_like.rb +2 -0
- data/lib/generators/socialization/templates/redis/model_mention.rb +2 -0
- data/lib/socialization/actors/follower.rb +88 -0
- data/lib/socialization/actors/liker.rb +88 -0
- data/lib/socialization/actors/mentioner.rb +88 -0
- data/lib/socialization/config/config.rb +39 -0
- data/lib/socialization/helpers/acts_as_helpers.rb +39 -0
- data/lib/socialization/helpers/string.rb +17 -0
- data/lib/socialization/lib/exceptions.rb +3 -0
- data/lib/socialization/stores/active_record/follow.rb +125 -0
- data/lib/socialization/stores/active_record/like.rb +121 -0
- data/lib/socialization/stores/active_record/mention.rb +125 -0
- data/lib/socialization/stores/active_record/mixins/base.rb +12 -0
- data/lib/socialization/stores/mixins/base.rb +22 -0
- data/lib/socialization/stores/mixins/follow.rb +39 -0
- data/lib/socialization/stores/mixins/like.rb +40 -0
- data/lib/socialization/stores/mixins/mention.rb +40 -0
- data/lib/socialization/stores/redis/base.rb +125 -0
- data/lib/socialization/stores/redis/config.rb +11 -0
- data/lib/socialization/stores/redis/follow.rb +22 -0
- data/lib/socialization/stores/redis/like.rb +22 -0
- data/lib/socialization/stores/redis/mention.rb +22 -0
- data/lib/socialization/stores/redis/mixins/base.rb +8 -0
- data/lib/socialization/version.rb +3 -0
- data/lib/socialization/victims/followable.rb +50 -0
- data/lib/socialization/victims/likeable.rb +51 -0
- data/lib/socialization/victims/mentionable.rb +51 -0
- data/lib/socialization.rb +20 -0
- data/socialization.gemspec +32 -0
- data/spec/actors/follower_spec.rb +113 -0
- data/spec/actors/liker_spec.rb +105 -0
- data/spec/actors/mentioner_spec.rb +105 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/spec_support/data_stores.rb +232 -0
- data/spec/spec_support/matchers.rb +54 -0
- data/spec/stores/active_record/follow_store_spec.rb +147 -0
- data/spec/stores/active_record/like_store_spec.rb +146 -0
- data/spec/stores/active_record/mention_store_spec.rb +148 -0
- data/spec/stores/active_record/mixins/base_spec.rb +25 -0
- data/spec/stores/redis/base_spec.rb +195 -0
- data/spec/stores/redis/config_spec.rb +28 -0
- data/spec/stores/redis/follow_store_spec.rb +26 -0
- data/spec/stores/redis/like_store_spec.rb +23 -0
- data/spec/stores/redis/mention_store_spec.rb +23 -0
- data/spec/string_spec.rb +13 -0
- data/spec/victims/followable_spec.rb +59 -0
- data/spec/victims/likeable_spec.rb +58 -0
- data/spec/victims/mentionable_spec.rb +59 -0
- data/spec/world_spec.rb +107 -0
- metadata +322 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
STORES = %w(active_record redis)
|
5
|
+
|
6
|
+
class SocializationGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
source_root File.expand_path(File.join('templates'), File.dirname(__FILE__))
|
9
|
+
class_option :store, :type => :string, :default => 'active_record', :description => "Type of datastore"
|
10
|
+
|
11
|
+
def self.next_migration_number(dirname)
|
12
|
+
if ActiveRecord::Base.timestamped_migrations
|
13
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
14
|
+
else
|
15
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_migration_file
|
20
|
+
options[:store].downcase!
|
21
|
+
unless STORES.include?(options[:store])
|
22
|
+
puts "Invalid store '#{options[:store]}'. The following stores are valid: #{STORES.join(', ')}."
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
copy_file "#{options[:store]}/model_follow.rb", 'app/models/follow.rb'
|
27
|
+
copy_file "#{options[:store]}/model_like.rb", 'app/models/like.rb'
|
28
|
+
copy_file "#{options[:store]}/model_mention.rb", 'app/models/mention.rb'
|
29
|
+
|
30
|
+
if options[:store] == 'active_record'
|
31
|
+
migration_template "#{options[:store]}/migration_follows.rb", 'db/migrate/create_follows.rb'
|
32
|
+
sleep 1 # wait a second to have a unique migration timestamp
|
33
|
+
migration_template "#{options[:store]}/migration_likes.rb", 'db/migrate/create_likes.rb'
|
34
|
+
sleep 1 # wait a second to have a unique migration timestamp
|
35
|
+
migration_template "#{options[:store]}/migration_mentions.rb", 'db/migrate/create_mentions.rb'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateFollows < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :follows do |t|
|
4
|
+
t.string :follower_type
|
5
|
+
t.integer :follower_id
|
6
|
+
t.string :followable_type
|
7
|
+
t.integer :followable_id
|
8
|
+
t.datetime :created_at
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :follows, ["follower_id", "follower_type"], :name => "fk_follows"
|
12
|
+
add_index :follows, ["followable_id", "followable_type"], :name => "fk_followables"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateLikes < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :likes do |t|
|
4
|
+
t.string :liker_type
|
5
|
+
t.integer :liker_id
|
6
|
+
t.string :likeable_type
|
7
|
+
t.integer :likeable_id
|
8
|
+
t.datetime :created_at
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :likes, ["liker_id", "liker_type"], :name => "fk_likes"
|
12
|
+
add_index :likes, ["likeable_id", "likeable_type"], :name => "fk_likeables"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateMentions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :mentions do |t|
|
4
|
+
t.string :mentioner_type
|
5
|
+
t.integer :mentioner_id
|
6
|
+
t.string :mentionable_type
|
7
|
+
t.integer :mentionable_id
|
8
|
+
t.datetime :created_at
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :mentions, ["mentioner_id", "mentioner_type"], :name => "fk_mentions"
|
12
|
+
add_index :mentions, ["mentionable_id", "mentionable_type"], :name => "fk_mentionables"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def is_follower?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
alias follower? is_follower?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Socialization
|
11
|
+
module Follower
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
after_destroy { Socialization.follow_model.remove_followables(self) }
|
16
|
+
|
17
|
+
# Specifies if self can follow {Followable} objects.
|
18
|
+
#
|
19
|
+
# @return [Boolean]
|
20
|
+
def is_follower?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
alias follower? is_follower?
|
24
|
+
|
25
|
+
# Create a new {Follow follow} relationship.
|
26
|
+
#
|
27
|
+
# @param [Followable] followable the object to be followed.
|
28
|
+
# @return [Boolean]
|
29
|
+
def follow!(followable)
|
30
|
+
raise Socialization::ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
|
31
|
+
Socialization.follow_model.follow!(self, followable)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Delete a {Follow follow} relationship.
|
35
|
+
#
|
36
|
+
# @param [Followable] followable the object to unfollow.
|
37
|
+
# @return [Boolean]
|
38
|
+
def unfollow!(followable)
|
39
|
+
raise Socialization::ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
|
40
|
+
Socialization.follow_model.unfollow!(self, followable)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Toggles a {Follow follow} relationship.
|
44
|
+
#
|
45
|
+
# @param [Followable] followable the object to follow/unfollow.
|
46
|
+
# @return [Boolean]
|
47
|
+
def toggle_follow!(followable)
|
48
|
+
raise Socialization::ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
|
49
|
+
if follows?(followable)
|
50
|
+
unfollow!(followable)
|
51
|
+
false
|
52
|
+
else
|
53
|
+
follow!(followable)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Specifies if self follows a {Followable} object.
|
59
|
+
#
|
60
|
+
# @param [Followable] followable the {Followable} object to test against.
|
61
|
+
# @return [Boolean]
|
62
|
+
def follows?(followable)
|
63
|
+
raise Socialization::ArgumentError, "#{followable} is not followable!" unless followable.respond_to?(:is_followable?) && followable.is_followable?
|
64
|
+
Socialization.follow_model.follows?(self, followable)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns all the followables of a certain type that are followed by self
|
68
|
+
#
|
69
|
+
# @params [Followable] klass the type of {Followable} you want
|
70
|
+
# @params [Hash] opts a hash of options
|
71
|
+
# @return [Array<Followable, Numeric>] An array of Followable objects or IDs
|
72
|
+
def followables(klass, opts = {})
|
73
|
+
Socialization.follow_model.followables(self, klass, opts)
|
74
|
+
end
|
75
|
+
alias :followees :followables
|
76
|
+
|
77
|
+
# Returns a relation for all the followables of a certain type that are followed by self
|
78
|
+
#
|
79
|
+
# @params [Followable] klass the type of {Followable} you want
|
80
|
+
# @params [Hash] opts a hash of options
|
81
|
+
# @return ActiveRecord::Relation
|
82
|
+
def followables_relation(klass, opts = {})
|
83
|
+
Socialization.follow_model.followables_relation(self, klass, opts)
|
84
|
+
end
|
85
|
+
alias :followees_relation :followables_relation
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def is_liker?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
alias liker? is_liker?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Socialization
|
11
|
+
module Liker
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
after_destroy { Socialization.like_model.remove_likeables(self) }
|
16
|
+
|
17
|
+
# Specifies if self can like {Likeable} objects.
|
18
|
+
#
|
19
|
+
# @return [Boolean]
|
20
|
+
def is_liker?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
alias liker? is_liker?
|
24
|
+
|
25
|
+
# Create a new {Like like} relationship.
|
26
|
+
#
|
27
|
+
# @param [Likeable] likeable the object to be liked.
|
28
|
+
# @return [Boolean]
|
29
|
+
def like!(likeable)
|
30
|
+
raise Socialization::ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
|
31
|
+
Socialization.like_model.like!(self, likeable)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Delete a {Like like} relationship.
|
35
|
+
#
|
36
|
+
# @param [Likeable] likeable the object to unlike.
|
37
|
+
# @return [Boolean]
|
38
|
+
def unlike!(likeable)
|
39
|
+
raise Socialization::ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
|
40
|
+
Socialization.like_model.unlike!(self, likeable)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Toggles a {Like like} relationship.
|
44
|
+
#
|
45
|
+
# @param [Likeable] likeable the object to like/unlike.
|
46
|
+
# @return [Boolean]
|
47
|
+
def toggle_like!(likeable)
|
48
|
+
raise Socialization::ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
|
49
|
+
if likes?(likeable)
|
50
|
+
unlike!(likeable)
|
51
|
+
false
|
52
|
+
else
|
53
|
+
like!(likeable)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Specifies if self likes a {Likeable} object.
|
59
|
+
#
|
60
|
+
# @param [Likeable] likeable the {Likeable} object to test against.
|
61
|
+
# @return [Boolean]
|
62
|
+
def likes?(likeable)
|
63
|
+
raise Socialization::ArgumentError, "#{likeable} is not likeable!" unless likeable.respond_to?(:is_likeable?) && likeable.is_likeable?
|
64
|
+
Socialization.like_model.likes?(self, likeable)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns all the likeables of a certain type that are liked by self
|
68
|
+
#
|
69
|
+
# @params [Likeable] klass the type of {Likeable} you want
|
70
|
+
# @params [Hash] opts a hash of options
|
71
|
+
# @return [Array<Likeable, Numeric>] An array of Likeable objects or IDs
|
72
|
+
def likeables(klass, opts = {})
|
73
|
+
Socialization.like_model.likeables(self, klass, opts)
|
74
|
+
end
|
75
|
+
alias :likees :likeables
|
76
|
+
|
77
|
+
# Returns a relation for all the likeables of a certain type that are liked by self
|
78
|
+
#
|
79
|
+
# @params [Likeable] klass the type of {Likeable} you want
|
80
|
+
# @params [Hash] opts a hash of options
|
81
|
+
# @return ActiveRecord::Relation
|
82
|
+
def likeables_relation(klass, opts = {})
|
83
|
+
Socialization.like_model.likeables_relation(self, klass, opts)
|
84
|
+
end
|
85
|
+
alias :likees_relation :likeables_relation
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def is_mentioner?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
alias mentioner? is_mentioner?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Socialization
|
11
|
+
module Mentioner
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
after_destroy { Socialization.mention_model.remove_mentionables(self) }
|
16
|
+
|
17
|
+
# Specifies if self can mention {Mentionable} objects.
|
18
|
+
#
|
19
|
+
# @return [Boolean]
|
20
|
+
def is_mentioner?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
alias mentioner? is_mentioner?
|
24
|
+
|
25
|
+
# Create a new {Mention mention} relationship.
|
26
|
+
#
|
27
|
+
# @param [Mentionable] mentionable the object to be mentioned.
|
28
|
+
# @return [Boolean]
|
29
|
+
def mention!(mentionable)
|
30
|
+
raise Socialization::ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
|
31
|
+
Socialization.mention_model.mention!(self, mentionable)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Delete a {Mention mention} relationship.
|
35
|
+
#
|
36
|
+
# @param [Mentionable] mentionable the object to unmention.
|
37
|
+
# @return [Boolean]
|
38
|
+
def unmention!(mentionable)
|
39
|
+
raise Socialization::ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
|
40
|
+
Socialization.mention_model.unmention!(self, mentionable)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Toggles a {Mention mention} relationship.
|
44
|
+
#
|
45
|
+
# @param [Mentionable] mentionable the object to mention/unmention.
|
46
|
+
# @return [Boolean]
|
47
|
+
def toggle_mention!(mentionable)
|
48
|
+
raise Socialization::ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
|
49
|
+
if mentions?(mentionable)
|
50
|
+
unmention!(mentionable)
|
51
|
+
false
|
52
|
+
else
|
53
|
+
mention!(mentionable)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Specifies if self mentions a {Mentionable} object.
|
59
|
+
#
|
60
|
+
# @param [Mentionable] mentionable the {Mentionable} object to test against.
|
61
|
+
# @return [Boolean]
|
62
|
+
def mentions?(mentionable)
|
63
|
+
raise Socialization::ArgumentError, "#{mentionable} is not mentionable!" unless mentionable.respond_to?(:is_mentionable?) && mentionable.is_mentionable?
|
64
|
+
Socialization.mention_model.mentions?(self, mentionable)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns all the mentionables of a certain type that are mentioned by self
|
68
|
+
#
|
69
|
+
# @params [Mentionable] klass the type of {Mentionable} you want
|
70
|
+
# @params [Hash] opts a hash of options
|
71
|
+
# @return [Array<Mentionable, Numeric>] An array of Mentionable objects or IDs
|
72
|
+
def mentionables(klass, opts = {})
|
73
|
+
Socialization.mention_model.mentionables(self, klass, opts)
|
74
|
+
end
|
75
|
+
alias :mentionees :mentionables
|
76
|
+
|
77
|
+
# Returns a relation for all the mentionables of a certain type that are mentioned by self
|
78
|
+
#
|
79
|
+
# @params [Mentionable] klass the type of {Mentionable} you want
|
80
|
+
# @params [Hash] opts a hash of options
|
81
|
+
# @return ActiveRecord::Relation
|
82
|
+
def mentionables_relation(klass, opts = {})
|
83
|
+
Socialization.mention_model.mentionables_relation(self, klass, opts)
|
84
|
+
end
|
85
|
+
alias :mentionees_relation :mentionables_relation
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Socialization
|
2
|
+
class << self
|
3
|
+
def follow_model
|
4
|
+
if @follow_model
|
5
|
+
@follow_model
|
6
|
+
else
|
7
|
+
::Follow
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def follow_model=(klass)
|
12
|
+
@follow_model = klass
|
13
|
+
end
|
14
|
+
|
15
|
+
def like_model
|
16
|
+
if @like_model
|
17
|
+
@like_model
|
18
|
+
else
|
19
|
+
::Like
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def like_model=(klass)
|
24
|
+
@like_model = klass
|
25
|
+
end
|
26
|
+
|
27
|
+
def mention_model
|
28
|
+
if @mention_model
|
29
|
+
@mention_model
|
30
|
+
else
|
31
|
+
::Mention
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def mention_model=(klass)
|
36
|
+
@mention_model = klass
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Socialization
|
4
|
+
module ActsAsHelpers
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Make the current class a {Socialization::Follower}
|
9
|
+
def acts_as_follower(opts = {})
|
10
|
+
include Socialization::Follower
|
11
|
+
end
|
12
|
+
|
13
|
+
# Make the current class a {Socialization::Followable}
|
14
|
+
def acts_as_followable(opts = {})
|
15
|
+
include Socialization::Followable
|
16
|
+
end
|
17
|
+
|
18
|
+
# Make the current class a {Socialization::Liker}
|
19
|
+
def acts_as_liker(opts = {})
|
20
|
+
include Socialization::Liker
|
21
|
+
end
|
22
|
+
|
23
|
+
# Make the current class a {Socialization::Likeable}
|
24
|
+
def acts_as_likeable(opts = {})
|
25
|
+
include Socialization::Likeable
|
26
|
+
end
|
27
|
+
|
28
|
+
# Make the current class a {Socialization::Mentioner}
|
29
|
+
def acts_as_mentioner(opts = {})
|
30
|
+
include Socialization::Mentioner
|
31
|
+
end
|
32
|
+
|
33
|
+
# Make the current class a {Socialization::Mentionable}
|
34
|
+
def acts_as_mentionable(opts = {})
|
35
|
+
include Socialization::Mentionable
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Socialization
|
2
|
+
module ActiveRecordStores
|
3
|
+
class Follow < ActiveRecord::Base
|
4
|
+
extend Socialization::Stores::Mixins::Base
|
5
|
+
extend Socialization::Stores::Mixins::Follow
|
6
|
+
extend Socialization::ActiveRecordStores::Mixins::Base
|
7
|
+
|
8
|
+
belongs_to :follower, :polymorphic => true
|
9
|
+
belongs_to :followable, :polymorphic => true
|
10
|
+
|
11
|
+
scope :followed_by, lambda { |follower| where(
|
12
|
+
:follower_type => follower.class.table_name.classify,
|
13
|
+
:follower_id => follower.id)
|
14
|
+
}
|
15
|
+
|
16
|
+
scope :following, lambda { |followable| where(
|
17
|
+
:followable_type => followable.class.table_name.classify,
|
18
|
+
:followable_id => followable.id)
|
19
|
+
}
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def follow!(follower, followable)
|
23
|
+
unless follows?(follower, followable)
|
24
|
+
self.create! do |follow|
|
25
|
+
follow.follower = follower
|
26
|
+
follow.followable = followable
|
27
|
+
end
|
28
|
+
update_counter(follower, followees_count: +1)
|
29
|
+
update_counter(followable, followers_count: +1)
|
30
|
+
call_after_create_hooks(follower, followable)
|
31
|
+
true
|
32
|
+
else
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def unfollow!(follower, followable)
|
38
|
+
if follows?(follower, followable)
|
39
|
+
follow_for(follower, followable).destroy_all
|
40
|
+
update_counter(follower, followees_count: -1)
|
41
|
+
update_counter(followable, followers_count: -1)
|
42
|
+
call_after_destroy_hooks(follower, followable)
|
43
|
+
true
|
44
|
+
else
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def follows?(follower, followable)
|
50
|
+
!follow_for(follower, followable).empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns an ActiveRecord::Relation of all the followers of a certain type that are following followable
|
54
|
+
def followers_relation(followable, klass, opts = {})
|
55
|
+
rel = klass.where(:id =>
|
56
|
+
self.select(:follower_id).
|
57
|
+
where(:follower_type => klass.table_name.classify).
|
58
|
+
where(:followable_type => followable.class.to_s).
|
59
|
+
where(:followable_id => followable.id)
|
60
|
+
)
|
61
|
+
|
62
|
+
if opts[:pluck]
|
63
|
+
rel.pluck(opts[:pluck])
|
64
|
+
else
|
65
|
+
rel
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns all the followers of a certain type that are following followable
|
70
|
+
def followers(followable, klass, opts = {})
|
71
|
+
rel = followers_relation(followable, klass, opts)
|
72
|
+
if rel.is_a?(ActiveRecord::Relation)
|
73
|
+
rel.to_a
|
74
|
+
else
|
75
|
+
rel
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns an ActiveRecord::Relation of all the followables of a certain type that are followed by follower
|
80
|
+
def followables_relation(follower, klass, opts = {})
|
81
|
+
rel = klass.where(:id =>
|
82
|
+
self.select(:followable_id).
|
83
|
+
where(:followable_type => klass.table_name.classify).
|
84
|
+
where(:follower_type => follower.class.to_s).
|
85
|
+
where(:follower_id => follower.id)
|
86
|
+
)
|
87
|
+
|
88
|
+
if opts[:pluck]
|
89
|
+
rel.pluck(opts[:pluck])
|
90
|
+
else
|
91
|
+
rel
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns all the followables of a certain type that are followed by follower
|
96
|
+
def followables(follower, klass, opts = {})
|
97
|
+
rel = followables_relation(follower, klass, opts)
|
98
|
+
if rel.is_a?(ActiveRecord::Relation)
|
99
|
+
rel.to_a
|
100
|
+
else
|
101
|
+
rel
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Remove all the followers for followable
|
106
|
+
def remove_followers(followable)
|
107
|
+
self.where(:followable_type => followable.class.name.classify).
|
108
|
+
where(:followable_id => followable.id).destroy_all
|
109
|
+
end
|
110
|
+
|
111
|
+
# Remove all the followables for follower
|
112
|
+
def remove_followables(follower)
|
113
|
+
self.where(:follower_type => follower.class.name.classify).
|
114
|
+
where(:follower_id => follower.id).destroy_all
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def follow_for(follower, followable)
|
119
|
+
followed_by(follower).following(followable)
|
120
|
+
end
|
121
|
+
end # class << self
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|