mongo_followable 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in mongo_followable.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Jie Fan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,115 @@
1
+ = mongo_followable
2
+
3
+ Now works for both Mongoid and Mongo_Mapper!
4
+
5
+ == Installation
6
+
7
+ In console:
8
+ gem install mongo_followable
9
+ or in Gemfile:
10
+ gem 'mongo_followable', "~> 0.2.0"
11
+
12
+ == Usage
13
+
14
+ To make model followable you need to include Mongo::Followable into your document;Meanwhile, you also need to include Mongo::Follower in your follower model:
15
+ class User
16
+ include Mongo::Document
17
+ include Mongo::Followable
18
+ include Mongo::Follower
19
+ end
20
+
21
+ class Group
22
+ include Mongo::Document
23
+ include Mongo::Followable
24
+ end
25
+
26
+ Now you can set authorization:
27
+ current_user.set_authorization('user', 'game') # now current_user cannot follow User and Game model
28
+ current_user.unset_authorization('User', 'Game')
29
+
30
+ And then you can follow a model:
31
+
32
+ @group = Group.new
33
+ @group.save
34
+
35
+ current_user.follow(@group)
36
+ current_user.unfollow(@group)
37
+
38
+ You can also judge whether a model is a follower of another model or a model is a followee of another model:
39
+
40
+ current_user.follower_of?(@group)
41
+ current_user.followee_of?(@group)
42
+
43
+ Moreover, it's easy to get a model's follower/followee count:
44
+
45
+ current_user.followers_count
46
+ current_user.followees_count
47
+
48
+ Of course, you can get a list of followers/followees:
49
+
50
+ User.followers_of(@group)
51
+ User.followees_of(@group)
52
+
53
+ @group.all_followers
54
+ @user.all_followees
55
+
56
+ Getting a model's followers/followees by type is also possible:
57
+
58
+ @group.followers_by_type("user")
59
+ @user.followees_by_type("group")
60
+
61
+ And their count:
62
+
63
+ @group.followers_by_type("user")
64
+ @group.followers_count_by_type("user")
65
+ @user.followees_by_type("group")
66
+ @user.followees_count_by_type("group")
67
+
68
+ You can also get a model's follow/followed history:
69
+
70
+ @user.ever_follow
71
+ @group.ever_followed
72
+
73
+ Another feature is to get a list of models which has the most followers/followees:
74
+
75
+ User.with_max_followees
76
+ User.with_min_followees
77
+ User.with_max_followees_by_type('group')
78
+ User.with_min_followees_by_type('group')
79
+ Group.with_max_followers
80
+ Group.with_min_followers
81
+ Group.with_max_followers_by_type('user')
82
+ Group.with_min_followers_by_type('user')
83
+
84
+ Now you can tell if two models have some common followers/followees by following methods:
85
+
86
+ @user.common_followees?(@another_user)
87
+ @user.common_followers?(@group)
88
+
89
+ And see what the common followers/followees are:
90
+
91
+ @user.common_followees_with(@another_user)
92
+ @user.common_followers_with(@group)
93
+
94
+ * Any bug or issue, please send me an email: ustc.flyingfox@gmail.com
95
+
96
+ == TODO
97
+
98
+ * inter-models followable #FINISHED#
99
+ * divide into two parts: followable(being followed) and follower(following others) #FINISHED#
100
+ * following history/followed history #FINISHED#
101
+ * most/least followed/following #FINISHED
102
+ * add authorization to followable models #FINISHED#
103
+ * common followers/followees #FINISHED#
104
+ * add support for mongo_mapper in next version #FINISHED#
105
+
106
+ !!If you have any advice, plese do not hesitate to tell me!!
107
+
108
+ == Thanks
109
+
110
+ Thanks the author(s) of acts_as_followable, you can find this gem here[https://github.com/xpepermint/acts_as_followable]
111
+ Thanks the author(s) of voteable_mongo, you can find this gem here[https://github.com/vinova/voteable_mongo]
112
+
113
+ == Copyright
114
+
115
+ Copyright (c) Jie Fan. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,19 @@
1
+ class Follow
2
+ if defined?(Mongoid)
3
+ include Mongoid::Document
4
+
5
+ field :f_type, :type => String
6
+ field :f_id, :type => String
7
+ elsif defined?(MongoMapper)
8
+ include MongoMapper::Document
9
+
10
+ key :f_type, :type => String
11
+ key :f_id, :type => String
12
+ end
13
+
14
+ belongs_to :followable, :polymorphic => true
15
+ belongs_to :following, :polymorphic => true
16
+
17
+ scope :by_type, lambda { |type| where(:f_type => type.capitalize) }
18
+ scope :by_model, lambda { |model| where(:f_id => model.id.to_s).by_type(model.class.name) }
19
+ end
@@ -0,0 +1,185 @@
1
+ module Mongo
2
+ module Followable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |base|
6
+ if defined?(Mongoid)
7
+ base.field :cannot_followed, :type => Array, :default => []
8
+ base.field :followed_history, :type => Array, :default => []
9
+ base.has_many :followers, :class_name => "Follow", :as => :followable, :dependent => :destroy
10
+ elsif defined?(MongoMapper)
11
+ base.key :cannot_followed, :type => Array, :default => []
12
+ base.key :followed_history, :type => Array, :default => []
13
+ base.many :followers, :class_name => "Follow", :as => :followable, :dependent => :destroy
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+ # get certain model's followees of this type
20
+ #
21
+ # Example:
22
+ # >> @jim = User.new
23
+ # >> @ruby = Group.new
24
+ # >> @jim.save
25
+ # >> @ruby.save
26
+ #
27
+ # >> @jim.follow(@ruby)
28
+ # >> User.followees_of(@jim)
29
+ # => [@ruby]
30
+ #
31
+ # Arguments:
32
+ # model: instance of some followable model
33
+
34
+ def followees_of(model)
35
+ model.followees_by_type(self.name)
36
+ end
37
+
38
+ # 4 methods in this function
39
+ #
40
+ # Example:
41
+ # >> Group.with_max_followers
42
+ # => [@ruby]
43
+ # >> Group.with_max_followers_by_type('user')
44
+ # => [@ruby]
45
+
46
+ def method_missing(name, *args)
47
+ if name.to_s =~ /^with_(max|min)_followers$/i
48
+ follow_array = self.all.to_a.sort! { |a, b| a.followers_count <=> b.followers_count }
49
+ if $1 == "max"
50
+ max = follow_array[-1].followers_count
51
+ follow_array.select { |c| c.followers_count == max }
52
+ elsif $1 == "min"
53
+ min = follow_array[0].followers_count
54
+ follow_array.select { |c| c.followers_count == min }
55
+ end
56
+ elsif name.to_s =~ /^with_(max|min)_followers_by_type$/i
57
+ follow_array = self.all.to_a.sort! { |a, b| a.followers_count_by_type(args[0]) <=> b.followers_count_by_type(args[0]) }
58
+ if $1 == "max"
59
+ max = follow_array[-1].followers_count_by_type(args[0])
60
+ follow_array.select { |c| c.followers_count_by_type(args[0]) == max }
61
+ elsif $1 == "min"
62
+ min = follow_array[0].followers_count
63
+ follow_array.select { |c| c.followers_count_by_type(args[0]) == min }
64
+ end
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ # set which mongoid cannot follow self
73
+ #
74
+ # Example:
75
+ # >> @ruby.set_authorization('user')
76
+ # => true
77
+
78
+ def set_authorization(*models)
79
+ models.each do |model|
80
+ self.cannot_followed << model.capitalize
81
+ end
82
+ self.save
83
+ end
84
+
85
+ def unset_authorization(*models)
86
+ models.each do |model|
87
+ self.cannot_followed -= [model.capitalize]
88
+ end
89
+ self.save
90
+ end
91
+
92
+ # see if this model is followee of some model
93
+ #
94
+ # Example:
95
+ # >> @ruby.followee_of?(@jim)
96
+ # => true
97
+
98
+ def followee_of?(model)
99
+ 0 < self.followers.by_model(model).limit(1).count * model.followees.by_model(self).limit(1).count
100
+ end
101
+
102
+ # get all the followers of this model, same with classmethod followers_of
103
+ #
104
+ # Example:
105
+ # >> @ruby.all_followers
106
+ # => [@jim]
107
+
108
+ def all_followers
109
+ rebuild_instances(self.followers)
110
+ end
111
+
112
+ # get all the followers of this model in certain type
113
+ #
114
+ # Example:
115
+ # >> @ruby.followers_by_type("user")
116
+ # => [@jim]
117
+
118
+ def followers_by_type(type)
119
+ rebuild_instances(self.followers.by_type(type))
120
+ end
121
+
122
+ # get the number of followers
123
+ #
124
+ # Example:
125
+ # >> @ruby.followers_count
126
+ # => 1
127
+
128
+ def followers_count
129
+ self.followers.count
130
+ end
131
+
132
+ # get the number of followers in certain type
133
+ #
134
+ # Example:
135
+ # >> @ruby.followers_count_by_type("user")
136
+ # => 1
137
+
138
+ def followers_count_by_type(type)
139
+ self.followers.by_type(type).count
140
+ end
141
+
142
+ # see model's followed history
143
+ #
144
+ # Example:
145
+ # >> @ruby.ever_followed
146
+ # => [@jim]
147
+
148
+ def ever_followed
149
+ follow = []
150
+ self.followed_history.each do |h|
151
+ follow << h.split('_')[0].constantize.find(h.split('_')[1])
152
+ end
153
+ follow
154
+ end
155
+
156
+ # return if there is any common followers
157
+ #
158
+ # Example:
159
+ # >> @ruby.common_followees?(@python)
160
+ # => true
161
+
162
+ def common_followers?(model)
163
+ 0 < (rebuild_instances(self.followers) & rebuild_instances(model.followers)).length
164
+ end
165
+
166
+ # get common followers with some model
167
+ #
168
+ # Example:
169
+ # >> @ruby.common_followers_with(@python)
170
+ # => [@jim]
171
+
172
+ def common_followers_with(model)
173
+ rebuild_instances(self.followers) & rebuild_instances(model.followers)
174
+ end
175
+
176
+ private
177
+ def rebuild_instances(follows)
178
+ follow_list = []
179
+ follows.each do |follow|
180
+ follow_list << follow.f_type.capitalize.constantize.find(follow.f_id)
181
+ end
182
+ follow_list
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,213 @@
1
+ module Mongo
2
+ module Follower
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |base|
6
+ if defined?(Mongoid)
7
+ base.field :cannot_follow, :type => Array, :default => []
8
+ base.field :follow_history, :type => Array, :default => []
9
+ base.has_many :followees, :class_name => "Follow", :as => :following, :dependent => :destroy
10
+ elsif defined?(MongoMapper)
11
+ base.key :cannot_follow, :type => Array, :default => []
12
+ base.key :follow_history, :type => Array, :default => []
13
+ base.many :followees, :class_name => "Follow", :as => :following, :dependent => :destroy
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+ # get certain model's followers of this type
20
+ #
21
+ # Example:
22
+ # >> @jim = User.new
23
+ # >> @ruby = Group.new
24
+ # >> @jim.save
25
+ # >> @ruby.save
26
+ #
27
+ # >> @jim.follow(@ruby)
28
+ # >> User.followers_of(@ruby)
29
+ # => [@jim]
30
+ #
31
+ # Arguments:
32
+ # model: instance of some followable model
33
+
34
+ def followers_of(model)
35
+ model.followers_by_type(self.name)
36
+ end
37
+
38
+ # 4 methods in this function
39
+ #
40
+ # Example:
41
+ # >> User.with_max_followees
42
+ # => [@jim]
43
+ # >> User.with_max_followees_by_type('group')
44
+ # => [@jim]
45
+
46
+ def method_missing(name, *args)
47
+ if name.to_s =~ /^with_(max|min)_followees$/i
48
+ follow_array = self.all.to_a.sort! { |a, b| a.followees_count <=> b.followees_count }
49
+ if $1 == "max"
50
+ max = follow_array[-1].followees_count
51
+ follow_array.select { |c| c.followees_count == max }
52
+ elsif $1 == "min"
53
+ min = follow_array[0].followees_count
54
+ follow_array.select { |c| c.followees_count == min }
55
+ end
56
+ elsif name.to_s =~ /^with_(max|min)_followees_by_type$/i
57
+ follow_array = self.all.to_a.sort! { |a, b| a.followees_count_by_type(args[0]) <=> b.followees_count_by_type(args[0]) }
58
+ if $1 == "max"
59
+ max = follow_array[-1].followees_count_by_type(args[0])
60
+ follow_array.select { |c| c.followees_count_by_type(args[0]) == max }
61
+ elsif $1 == "min"
62
+ min = follow_array[0].followees_count
63
+ follow_array.select { |c| c.followees_count_by_type(args[0]) == min }
64
+ end
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ # set which mongoid user cannot follow
73
+ #
74
+ # Example:
75
+ # >> @jim.set_authorization('group', 'user')
76
+ # => true
77
+
78
+ def set_authorization(*models)
79
+ models.each do |model|
80
+ self.cannot_follow << model.capitalize
81
+ end
82
+ self.save
83
+ end
84
+
85
+ #unset which mongoid user cannot follow
86
+
87
+ def unset_authorization(*models)
88
+ models.each do |model|
89
+ self.cannot_follow -= [model.capitalize]
90
+ end
91
+ self.save
92
+ end
93
+
94
+ # see if this model is follower of some model
95
+ #
96
+ # Example:
97
+ # >> @jim.follower_of?(@ruby)
98
+ # => true
99
+
100
+ def follower_of?(model)
101
+ 0 < self.followees.by_model(model).limit(1).count * model.followers.by_model(self).limit(1).count
102
+ end
103
+
104
+ # get all the followees of this model, same with classmethod followees_of
105
+ #
106
+ # Example:
107
+ # >> @jim.all_followees
108
+ # => [@ruby]
109
+
110
+ def all_followees
111
+ rebuild_instances(self.followees)
112
+ end
113
+
114
+ # get all the followees of this model in certain type
115
+ #
116
+ # Example:
117
+ # >> @ruby.followees_by_type("group")
118
+ # => [@ruby]
119
+
120
+ def followees_by_type(type)
121
+ rebuild_instances(self.followees.by_type(type))
122
+ end
123
+
124
+ # follow some model
125
+
126
+ def follow(*models)
127
+ models.each do |model|
128
+ unless model == self or self.follower_of?(model) or model.followee_of?(self) or self.cannot_follow.include?(model.class.name) or model.cannot_followed.include?(self.class.name)
129
+ model.followers.create!(:f_type => self.class.name, :f_id => self.id.to_s)
130
+ model.followed_history << self.class.name + '_' + self.id.to_s
131
+ model.save
132
+ self.followees.create!(:f_type => model.class.name, :f_id => model.id.to_s)
133
+ self.follow_history << model.class.name + '_' + model.id.to_s
134
+ self.save
135
+ end
136
+ end
137
+ end
138
+
139
+ # unfollow some model
140
+
141
+ def unfollow(*models)
142
+ models.each do |model|
143
+ unless model == self or !self.follower_of?(model) or !model.followee_of?(self) or self.cannot_follow.include?(model.class.name) or model.cannot_followed.include?(self.class.name)
144
+ model.followers.by_model(self).first.destroy
145
+ self.followees.by_model(model).first.destroy
146
+ end
147
+ end
148
+ end
149
+
150
+ # get the number of followees
151
+ #
152
+ # Example:
153
+ # >> @jim.followers_count
154
+ # => 1
155
+
156
+ def followees_count
157
+ self.followees.count
158
+ end
159
+
160
+ # get the number of followers in certain type
161
+ #
162
+ # Example:
163
+ # >> @ruby.followers_count_by_type("user")
164
+ # => 1
165
+
166
+ def followees_count_by_type(type)
167
+ self.followees.by_type(type).count
168
+ end
169
+
170
+ # see user's follow history
171
+ #
172
+ # Example:
173
+ # >> @jim.ever_follow
174
+ # => [@ruby]
175
+
176
+ def ever_follow
177
+ follow = []
178
+ self.follow_history.each do |h|
179
+ follow << h.split('_')[0].constantize.find(h.split('_')[1])
180
+ end
181
+ follow
182
+ end
183
+
184
+ # return if there is any common followees
185
+ #
186
+ # Example:
187
+ # >> @jim.common_followees?(@tom)
188
+ # => true
189
+
190
+ def common_followees?(model)
191
+ 0 < (rebuild_instances(self.followees) & rebuild_instances(model.followees)).length
192
+ end
193
+
194
+ # get common followees with some model
195
+ #
196
+ # Example:
197
+ # >> @jim.common_followees_with(@tom)
198
+ # => [@ruby]
199
+
200
+ def common_followees_with(model)
201
+ rebuild_instances(self.followees) & rebuild_instances(model.followees)
202
+ end
203
+
204
+ private
205
+ def rebuild_instances(follows)
206
+ follow_list = []
207
+ follows.each do |follow|
208
+ follow_list << follow.f_type.capitalize.constantize.find(follow.f_id)
209
+ end
210
+ follow_list
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,3 @@
1
+ module MongoFollowable
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ #require "mongo_followable/followable"
2
+ #require "mongo_followable/follower"
3
+ #require "../app/models/follow"
4
+
5
+ require File.join(File.dirname(__FILE__), "mongo_followable/followable")
6
+ require File.join(File.dirname(__FILE__), "mongo_followable/follower")
7
+ require File.join(File.dirname(__FILE__), "../app/models/follow")
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "mongo_followable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "mongo_followable"
7
+ s.version = MongoFollowable::VERSION
8
+ s.authors = ["Jie Fan"]
9
+ s.email = ["ustc.flyingfox@gmail.com"]
10
+ s.homepage = "https://github.com/lastomato/mongo_followable"
11
+ s.summary = %q{ adds following feature to mongoid }
12
+ s.description = %q{ Mongo Followable adds following feature to mongoid }
13
+
14
+ s.rubyforge_project = "mongo_followable"
15
+
16
+ s.add_development_dependency('rspec', '~> 2.6')
17
+ s.add_development_dependency('mongoid', '~> 2.0')
18
+ s.add_development_dependency('mongo_mapper', '~> 0.9')
19
+ s.add_development_dependency('bson_ext', '~> 1.4')
20
+ s.add_development_dependency('database_cleaner', '~>0.6')
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Followable do
4
+
5
+ describe User do
6
+
7
+ let!(:u) { User.new }
8
+
9
+ context "begins" do
10
+
11
+ before do
12
+ u.save
13
+
14
+ @v = User.new
15
+ @v.save
16
+
17
+ @g = Group.new
18
+ @g.save
19
+ end
20
+
21
+ it "following a user" do
22
+ u.follow(@v)
23
+
24
+ u.follower_of?(@v).should be_true
25
+ @v.followee_of?(u).should be_true
26
+
27
+ u.all_followees.should == [@v]
28
+ @v.all_followers.should == [u]
29
+
30
+ u.followees_by_type("user").should == [@v]
31
+ @v.followers_by_type("user").should == [u]
32
+
33
+ u.followees_count.should == 1
34
+ @v.followers_count.should == 1
35
+
36
+ u.followees_count_by_type("user").should == 1
37
+ @v.followers_count_by_type("user").should == 1
38
+
39
+ u.ever_follow.should == [@v]
40
+ @v.ever_followed.should == [u]
41
+
42
+ u.common_followees?(@v).should be_false
43
+ @v.common_followers?(u).should be_false
44
+ u.common_followees_with(@v).should == []
45
+ @v.common_followers_with(u).should == []
46
+
47
+ User.with_max_followees.should == [u]
48
+ User.with_max_followers.should == [@v]
49
+ User.with_max_followees_by_type('user').should == [u]
50
+ User.with_max_followers_by_type('user').should == [@v]
51
+ end
52
+
53
+ it "unfollowing a user" do
54
+ u.unfollow(@v)
55
+
56
+ u.follower_of?(@v).should be_false
57
+ @v.followee_of?(u).should be_false
58
+
59
+ u.all_followees.should == []
60
+ @v.all_followers.should == []
61
+
62
+ u.followees_by_type("user").should == []
63
+ @v.followers_by_type("user").should == []
64
+
65
+ u.followees_count.should == 0
66
+ @v.followers_count.should == 0
67
+
68
+ u.followees_count_by_type("user").should == 0
69
+ @v.followers_count_by_type("user").should == 0
70
+ end
71
+
72
+ it "following a group" do
73
+ u.follow(@g)
74
+
75
+ u.follower_of?(@g).should be_true
76
+ @g.followee_of?(u).should be_true
77
+
78
+ u.all_followees.should == [@g]
79
+ @g.all_followers.should == [u]
80
+
81
+ u.followees_by_type("group").should == [@g]
82
+ @g.followers_by_type("user").should == [u]
83
+
84
+ u.followees_count.should == 1
85
+ @g.followers_count.should == 1
86
+
87
+ u.followees_count_by_type("group").should == 1
88
+ @g.followers_count_by_type("user").should == 1
89
+
90
+ u.follow(@v)
91
+
92
+ u.ever_follow.should == [@g, @v]
93
+ @g.ever_followed.should == [u]
94
+
95
+ u.common_followees?(@v).should be_false
96
+ @v.common_followers?(@g).should be_true
97
+ u.common_followees_with(@v).should == []
98
+ @v.common_followers_with(@g).should == [u]
99
+
100
+ User.with_max_followees.should == [u]
101
+ Group.with_max_followers.should == [@g]
102
+ User.with_max_followees_by_type('group').should == [u]
103
+ Group.with_max_followers_by_type('user').should == [@g]
104
+ end
105
+
106
+ it "unfollowing a group" do
107
+ u.unfollow(@g)
108
+
109
+ u.follower_of?(@g).should be_false
110
+ @g.followee_of?(u).should be_false
111
+
112
+ u.all_followees.should == []
113
+ @g.all_followers.should == []
114
+
115
+ u.followees_by_type("group").should == []
116
+ @g.followers_by_type("group").should == []
117
+
118
+ u.followees_count.should == 0
119
+ @g.followers_count.should == 0
120
+
121
+ u.followees_count_by_type("group").should == 0
122
+ @g.followers_count_by_type("group").should == 0
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,4 @@
1
+ class Group
2
+ include MongoMapper::Document
3
+ include Mongo::Followable
4
+ end
@@ -0,0 +1,5 @@
1
+ class User
2
+ include MongoMapper::Document
3
+ include Mongo::Followable
4
+ include Mongo::Follower
5
+ end
@@ -0,0 +1,4 @@
1
+ class Group
2
+ include Mongoid::Document
3
+ include Mongo::Followable
4
+ end
@@ -0,0 +1,5 @@
1
+ class User
2
+ include Mongoid::Document
3
+ include Mongo::Followable
4
+ include Mongo::Follower
5
+ end
@@ -0,0 +1,31 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require "database_cleaner"
5
+ require "rspec"
6
+
7
+ if rand > 0.5
8
+ puts 'Mongoid'
9
+ require 'mongoid'
10
+ require File.expand_path("../../lib/mongo_followable", __FILE__)
11
+ require File.expand_path("../mongoid/user", __FILE__)
12
+ require File.expand_path("../mongoid/group", __FILE__)
13
+ Mongoid.configure do |config|
14
+ name = 'voteable_mongo_test'
15
+ host = 'localhost'
16
+ config.master = Mongo::Connection.new.db(name)
17
+ config.autocreate_indexes = true
18
+ end
19
+ else
20
+ puts 'MongoMapper'
21
+ require 'mongo_mapper'
22
+ require File.expand_path("../../lib/mongo_followable", __FILE__)
23
+ require File.expand_path("../mongo_mapper/user", __FILE__)
24
+ require File.expand_path("../mongo_mapper/group", __FILE__)
25
+ MongoMapper.database = 'voteable_mongo_test'
26
+ end
27
+
28
+ RSpec.configure do |c|
29
+ c.before(:all) { DatabaseCleaner.strategy = :truncation }
30
+ c.before(:each) { DatabaseCleaner.clean }
31
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongo_followable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
+ platform: ruby
11
+ authors:
12
+ - Jie Fan
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-11-06 01:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 6
31
+ version: "2.6"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: mongoid
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 2
44
+ - 0
45
+ version: "2.0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: mongo_mapper
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 9
59
+ version: "0.9"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: bson_ext
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 1
72
+ - 4
73
+ version: "1.4"
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: database_cleaner
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ~>
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ - 6
87
+ version: "0.6"
88
+ type: :development
89
+ version_requirements: *id005
90
+ description: " Mongo Followable adds following feature to mongoid "
91
+ email:
92
+ - ustc.flyingfox@gmail.com
93
+ executables: []
94
+
95
+ extensions: []
96
+
97
+ extra_rdoc_files: []
98
+
99
+ files:
100
+ - .gitignore
101
+ - Gemfile
102
+ - LICENSE.txt
103
+ - README.rdoc
104
+ - Rakefile
105
+ - app/models/follow.rb
106
+ - lib/mongo_followable.rb
107
+ - lib/mongo_followable/followable.rb
108
+ - lib/mongo_followable/follower.rb
109
+ - lib/mongo_followable/version.rb
110
+ - mongo_followable.gemspec
111
+ - spec/mongo/followable_spec.rb
112
+ - spec/mongo_mapper/group.rb
113
+ - spec/mongo_mapper/user.rb
114
+ - spec/mongoid/group.rb
115
+ - spec/mongoid/user.rb
116
+ - spec/spec_helper.rb
117
+ has_rdoc: true
118
+ homepage: https://github.com/lastomato/mongo_followable
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project: mongo_followable
145
+ rubygems_version: 1.3.7
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: adds following feature to mongoid
149
+ test_files: []
150
+