acts_as_followable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [Kristijan Sedlak]
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,86 @@
1
+ = ActsAsFollowable - Model following
2
+
3
+ This plugin is a Rails3 alternative of the plugin called {acts_as_follower}[https://github.com/tcocca/acts_as_follower]
4
+ by tcocca. It allows any model to follow other models and a model can be followed by other models.
5
+
6
+ Usually you will use this plugin when implementing a blog-style website where users will follow other users or for
7
+ users to follow Books, etc...
8
+
9
+ == Installation (Rails 3 ready)
10
+
11
+ Add this line to your Gemfile (and run bundle install):
12
+
13
+ gem 'acts_as_followable'
14
+
15
+ Run the generator which will generate a migration file.
16
+
17
+ script/generate acts_as_followable
18
+
19
+ The plugin comes with a Follow model file. You can override the default model definition by creating a new
20
+ app/models/follow.rb file with the content:
21
+
22
+ class Follow < ActiveRecord::Base
23
+ belongs_to :followable, :polymorphic => true
24
+ belongs_to :follower, :polymorphic => true
25
+ end
26
+
27
+ == Setup
28
+
29
+ If you would like a model to follow or to be followed by any other model, just add the mixin:
30
+ class User < ActiveRecord::Base
31
+ ...
32
+ acts_as_followable
33
+ ...
34
+ end
35
+
36
+ == Examples
37
+
38
+ To have an object start following another use the following:
39
+
40
+ book = Book.find(1)
41
+ user = User.find(1)
42
+ user.follow(book)
43
+
44
+ To stop following an object use the following
45
+
46
+ user.stop_following(book)
47
+
48
+ You can check to see if an object is following another object through the following:
49
+
50
+ user.following?(book)
51
+
52
+ You can check to see if an object is followed by another object through the following:
53
+
54
+ book.followed_by?(user)
55
+
56
+ To get a list of followers by a given type use the following (e.g. list of users that follow a book):
57
+
58
+ User.following(book)
59
+ or
60
+ book.followers_by_type('User')
61
+ or
62
+ book.user_followers
63
+
64
+ # Also
65
+
66
+ User.following(book).order('name').limit(2)
67
+ or
68
+ book.followers_by_type('User').limit(2)
69
+ or
70
+ book.user_followers.order('name')
71
+
72
+ To get a list of records of a particular type which this record is following (e.g. list of books followed by a user)
73
+
74
+ Book.followed_by(user)
75
+ or
76
+ user.following_by_type('Book')
77
+ or
78
+ user.following_book
79
+
80
+ # Also
81
+
82
+ Book.followed_by(user).order('title').limit(2)
83
+ or
84
+ user.following_by_type('Book').limit(2)
85
+ or
86
+ user.following_book('title')
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the acts_as_taggable_on_steroids plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the acts_as_taggable_on_steroids plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Acts As Follower'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ namespace :rcov do
25
+
26
+ desc "Generate a coverage report in coverage/"
27
+ task :gen do
28
+ sh "rcov --output coverage test/*_test.rb --exclude 'gems/*'"
29
+ end
30
+
31
+ desc "Remove generated coverage files."
32
+ task :clobber do
33
+ sh "rm -rdf coverage"
34
+ end
35
+
36
+ end
@@ -0,0 +1,84 @@
1
+ module ActsAsFollowable
2
+ module Followable
3
+
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def acts_as_followable
10
+ include ActsAsFollowable::Followable::InstanceMethods
11
+
12
+ scope :following, lambda{|followable| includes(:follows).where(['follows.followable_id=? AND follows.followable_type=?', followable.id, followable.class.name]) }
13
+ scope :followed_by, lambda{|follower| includes(:followings).where(['follows.follower_id=? AND follows.follower_type=?', follower.id, follower.class.name]) }
14
+
15
+ has_many :followings, :as => :followable, :dependent => :destroy, :class_name => 'Follow'
16
+ has_many :follows, :as => :follower, :dependent => :destroy
17
+ end
18
+ end
19
+
20
+ module InstanceMethods
21
+
22
+ # Returns the followers by a given type
23
+ def followers_by_type(type)
24
+ type.constantize.following(self)
25
+ end
26
+
27
+ # Returns the actual records of a particular type which this record is following.
28
+ def following_by_type(type)
29
+ type.constantize.followed_by(self)
30
+ end
31
+
32
+ # Allows magic names on followers_by_type
33
+ # e.g. followers_by_type('User') > user_followers
34
+ # e.g. following_by_type('User') > following_user
35
+ def method_missing(m, *args)
36
+ if m.to_s[/(.+)_followers/]
37
+ followers_by_type($1.singularize.classify)
38
+ elsif m.to_s[/following_(.+)/]
39
+ following_by_type($1.singularize.classify)
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ # Creates a new follow record for this instance to follow the passed object.
46
+ # Does not allow duplicate records to be created.
47
+ def follow(followable)
48
+ follow = follow_for_follawable(followable).first
49
+ if follow.blank? && self != followable
50
+ Follow.create(:followable => followable, :follower => self)
51
+ end
52
+ end
53
+
54
+ # Returns true if this instance is following the object passed as an argument.
55
+ def following?(followable)
56
+ 0 < follow_for_follawable(followable).limit(1).count
57
+ end
58
+
59
+ # Deletes the follow record if it exists.
60
+ def stop_following(followable)
61
+ if follow = follow_for_follawable(followable).first
62
+ follow.destroy
63
+ end
64
+ end
65
+
66
+ # Returns true if the current instance is followed by the passed record
67
+ def followed_by?(follower)
68
+ 0 < follow_for_follower(follower).limit(1).count
69
+ end
70
+
71
+ private
72
+
73
+ def follow_for_follawable(followable)
74
+ Follow.where(["follower_id = ? AND follower_type = ? AND followable_id = ? AND followable_type = ?", self.id, self.class.name, followable.id, followable.class.name])
75
+ end
76
+
77
+ def follow_for_follower(follower)
78
+ Follow.where(["follower_id = ? AND follower_type = ? AND followable_id = ? AND followable_type = ?", follower.id, follower.class.name, self.id, self.class.name])
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,9 @@
1
+ module ActsAsFollowable
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ %w( acts_as_followable/version
2
+ acts_as_followable/followable
3
+ ).each do |lib|
4
+ require File.join(File.dirname(__FILE__), lib)
5
+ end
6
+
7
+ ActiveRecord::Base.send(:include, ActsAsFollowable::Followable)
@@ -0,0 +1,5 @@
1
+ Description:
2
+ run ./script/generate acts_as_followable
3
+
4
+ no need to specify a name after acts_as_followable as you can not change the model name from Follow
5
+ the acts_as_followable_migration file will be created in db/migrate
@@ -0,0 +1,26 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class ActsAsFollowableGenerator < Rails::Generators::Base
5
+
6
+ include Rails::Generators::Migration
7
+
8
+ def self.source_root
9
+ @source_root ||= File.join(File.dirname(__FILE__), 'templates')
10
+ end
11
+
12
+ # Implement the required interface for Rails::Generators::Migration.
13
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
14
+ def self.next_migration_number(dirname)
15
+ if ActiveRecord::Base.timestamped_migrations
16
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
17
+ else
18
+ "%.3d" % (current_migration_number(dirname) + 1)
19
+ end
20
+ end
21
+
22
+ def create_migration_file
23
+ migration_template 'migration.rb', 'db/migrate/acts_as_followable_migration.rb'
24
+ end
25
+
26
+ end
@@ -0,0 +1,16 @@
1
+ class ActsAsFollowableMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :follows, :force => true do |t|
4
+ t.references :followable, :polymorphic => true, :null => false
5
+ t.references :follower, :polymorphic => true, :null => false
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :follows, ["follower_id", "follower_type"], :name => "fk_follows"
10
+ add_index :follows, ["followable_id", "followable_type"], :name => "fk_followables"
11
+ end
12
+
13
+ def self.down
14
+ drop_table :follows
15
+ end
16
+ end
data/test/TESTING ADDED
@@ -0,0 +1,48 @@
1
+ Testing
2
+ ==============
3
+
4
+ Tests are written with Shoulda on top of Test::Unit and Factory Girl is used instead of fixtures. Tests are run using rake.
5
+ Test can either be run against a MySQL database or the faster in-memory SQLite3.
6
+
7
+
8
+ MySQL
9
+ =======
10
+
11
+ 1. Create a new Rails app.
12
+ 2. Install acts_as_follower as a plugin.
13
+ 3. Copy the database config within the plugin:
14
+ cp test/database.yml.example test/database.yml
15
+ 4. Create a database as specified in test/database.yml.
16
+ 5. Run the tests:
17
+ rake test
18
+
19
+
20
+ SQLite3
21
+ =======
22
+
23
+ 1. Create a new Rails app.
24
+ 2. Install acts_as_follower as a plugin.
25
+ 3. Copy the database config within the plugin:
26
+ cp test/database.yml.example test/database.yml
27
+ 4. Install the sqlite3 library (if you don't have it already):
28
+ sudo gem install sqlite3-ruby
29
+ 5. Run the tests:
30
+ DB=sqlite3 rake test
31
+
32
+
33
+ Coverage
34
+ =======
35
+
36
+ Test coverage can be calculated using Rcov. Make sure you have the rcov gem installed.
37
+
38
+ Again in the acts_as_follower directory:
39
+
40
+ rake rcov:gen # For mysql
41
+
42
+ or:
43
+
44
+ rake rcov:gen DB=sqlite3 # For sqlite
45
+
46
+ The coverage will now be available in the test/coverage directory.
47
+
48
+ rake rcov:clobber will delete the coverage directory.
@@ -0,0 +1,241 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ActsAsFollowableTest < ActiveSupport::TestCase
4
+
5
+ context "instance methods" do
6
+ setup do
7
+ @sam = Factory(:sam)
8
+ end
9
+
10
+ should "be defined" do
11
+ assert @sam.respond_to?(:followers_count)
12
+ assert @sam.respond_to?(:followers)
13
+ assert @sam.respond_to?(:followed_by?)
14
+ end
15
+ end
16
+
17
+ context "acts_as_followable" do
18
+ setup do
19
+ @sam = Factory(:sam)
20
+ @jon = Factory(:jon)
21
+ @oasis = Factory(:oasis)
22
+ @metallica = Factory(:metallica)
23
+ @sam.follow(@jon)
24
+ end
25
+
26
+ context "followers_count" do
27
+ should "return the number of followers" do
28
+ assert_equal 0, @sam.followers_count
29
+ assert_equal 1, @jon.followers_count
30
+ end
31
+
32
+ should "return the proper number of multiple followers" do
33
+ @bob = Factory(:bob)
34
+ @sam.follow(@bob)
35
+ assert_equal 0, @sam.followers_count
36
+ assert_equal 1, @jon.followers_count
37
+ assert_equal 1, @bob.followers_count
38
+ end
39
+ end
40
+
41
+ context "followers" do
42
+ should "return users" do
43
+ assert_equal [], @sam.followers
44
+ assert_equal [@sam], @jon.followers
45
+ end
46
+
47
+ should "return users (multiple followers)" do
48
+ @bob = Factory(:bob)
49
+ @sam.follow(@bob)
50
+ assert_equal [], @sam.followers
51
+ assert_equal [@sam], @jon.followers
52
+ assert_equal [@sam], @bob.followers
53
+ end
54
+
55
+ should "return users (multiple followers, complex)" do
56
+ @bob = Factory(:bob)
57
+ @sam.follow(@bob)
58
+ @jon.follow(@bob)
59
+ assert_equal [], @sam.followers
60
+ assert_equal [@sam], @jon.followers
61
+ assert_equal [@sam, @jon], @bob.followers
62
+ end
63
+
64
+ should "accept AR options" do
65
+ @bob = Factory(:bob)
66
+ @bob.follow(@jon)
67
+ assert_equal 1, @jon.followers(:limit => 1).count
68
+ end
69
+ end
70
+
71
+ context "followed_by" do
72
+ should "return_follower_status" do
73
+ assert_equal true, @jon.followed_by?(@sam)
74
+ assert_equal false, @sam.followed_by?(@jon)
75
+ end
76
+ end
77
+
78
+ context "destroying a followable" do
79
+ setup do
80
+ @jon.destroy
81
+ end
82
+
83
+ should_change("follow count", :by => -1) { Follow.count }
84
+ should_change("@sam.all_following.size", :by => -1) { @sam.all_following.size }
85
+ end
86
+
87
+ context "blocks" do
88
+ setup do
89
+ @bob = Factory(:bob)
90
+ @jon.block(@sam)
91
+ @jon.block(@bob)
92
+ end
93
+
94
+ should "accept AR options" do
95
+ assert_equal 1, @jon.blocks(:limit => 1).count
96
+ end
97
+ end
98
+
99
+ context "blocking a follower" do
100
+ context "in my following list" do
101
+ setup do
102
+ @jon.block(@sam)
103
+ end
104
+
105
+ should "remove him from followers" do
106
+ assert_equal 0, @jon.followers_count
107
+ end
108
+
109
+ should "add him to the blocked followers" do
110
+ assert_equal 1, @jon.blocked_followers_count
111
+ end
112
+
113
+ should "not be able to follow again" do
114
+ @jon.follow(@sam)
115
+ assert_equal 0, @jon.followers_count
116
+ end
117
+
118
+ should "not be present when listing followers" do
119
+ assert_equal [], @jon.followers
120
+ end
121
+
122
+ should "be in the list of blocks" do
123
+ assert_equal [@sam], @jon.blocks
124
+ end
125
+ end
126
+
127
+ context "not in my following list" do
128
+ setup do
129
+ @sam.block(@jon)
130
+ end
131
+
132
+ should "add him to the blocked followers" do
133
+ assert_equal 1, @sam.blocked_followers_count
134
+ end
135
+
136
+ should "not be able to follow again" do
137
+ @sam.follow(@jon)
138
+ assert_equal 0, @sam.followers_count
139
+ end
140
+
141
+ should "not be present when listing followers" do
142
+ assert_equal [], @sam.followers
143
+ end
144
+
145
+ should "be in the list of blocks" do
146
+ assert_equal [@jon], @sam.blocks
147
+ end
148
+ end
149
+ end
150
+
151
+ context "unblocking a blocked follow" do
152
+ setup do
153
+ @jon.block(@sam)
154
+ @jon.unblock(@sam)
155
+ end
156
+
157
+ should "not include the unblocked user in the list of followers" do
158
+ assert_equal [], @jon.followers
159
+ end
160
+
161
+ should "remove him from the blocked followers" do
162
+ assert_equal 0, @jon.blocked_followers_count
163
+ assert_equal [], @jon.blocks
164
+ end
165
+ end
166
+
167
+ context "unblock a non-existent follow" do
168
+ setup do
169
+ @sam.stop_following(@jon)
170
+ @jon.unblock(@sam)
171
+ end
172
+
173
+ should "not be in the list of followers" do
174
+ assert_equal [], @jon.followers
175
+ end
176
+
177
+ should "not be in the blockked followers count" do
178
+ assert_equal 0, @jon.blocked_followers_count
179
+ end
180
+
181
+ should "not be in the blocks list" do
182
+ assert_equal [], @jon.blocks
183
+ end
184
+ end
185
+
186
+ context "followers_by_type" do
187
+ setup do
188
+ @sam.follow(@oasis)
189
+ @jon.follow(@oasis)
190
+ end
191
+
192
+ should "return the followers for given type" do
193
+ assert_equal [@sam], @jon.followers_by_type('User')
194
+ assert_equal [@sam,@jon], @oasis.followers_by_type('User')
195
+ end
196
+
197
+ should "not return block followers in the followers for a given type" do
198
+ @oasis.block(@jon)
199
+ assert_equal [@sam], @oasis.followers_by_type('User')
200
+ end
201
+
202
+ should "return the count for followers_by_type_count for a given type" do
203
+ assert_equal 1, @jon.followers_by_type_count('User')
204
+ assert_equal 2, @oasis.followers_by_type_count('User')
205
+ end
206
+
207
+ should "not count blocked follows in the count" do
208
+ @oasis.block(@sam)
209
+ assert_equal 1, @oasis.followers_by_type_count('User')
210
+ end
211
+ end
212
+
213
+ context "method_missing" do
214
+ setup do
215
+ @sam.follow(@oasis)
216
+ @jon.follow(@oasis)
217
+ end
218
+
219
+ should "return the followers for given type" do
220
+ assert_equal [@sam], @jon.user_followers
221
+ assert_equal [@sam,@jon], @oasis.user_followers
222
+ end
223
+
224
+ should "not return block followers in the followers for a given type" do
225
+ @oasis.block(@jon)
226
+ assert_equal [@sam], @oasis.user_followers
227
+ end
228
+
229
+ should "return the count for followers_by_type_count for a given type" do
230
+ assert_equal 1, @jon.count_user_followers
231
+ assert_equal 2, @oasis.count_user_followers
232
+ end
233
+
234
+ should "not count blocked follows in the count" do
235
+ @oasis.block(@sam)
236
+ assert_equal 1, @oasis.count_user_followers
237
+ end
238
+ end
239
+ end
240
+
241
+ end
@@ -0,0 +1,10 @@
1
+ mysql:
2
+ adapter: mysql
3
+ host: localhost
4
+ username: root
5
+ password:
6
+ database: rails_plugin_test
7
+
8
+ sqlite3:
9
+ adapter: sqlite3
10
+ database: ':memory:'
File without changes
File without changes
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class FollowTest < ActiveSupport::TestCase
4
+
5
+ # Replace with real tests
6
+ def test_assert_true_should_be_true
7
+ assert true
8
+ end
9
+
10
+ end
@@ -0,0 +1,4 @@
1
+ class Band < ActiveRecord::Base
2
+ validates_presence_of :name
3
+ acts_as_followable
4
+ end
@@ -0,0 +1,4 @@
1
+ class User < ActiveRecord::Base
2
+ validates_presence_of :name
3
+ acts_as_followable
4
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,21 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+
3
+ create_table :follows, :force => true do |t|
4
+ t.integer "followable_id", :null => false
5
+ t.string "followable_type", :null => false
6
+ t.integer "follower_id", :null => false
7
+ t.string "follower_type", :null => false
8
+ t.boolean "blocked", :default => false, :null => false
9
+ t.datetime "created_at"
10
+ t.datetime "updated_at"
11
+ end
12
+
13
+ create_table :users, :force => true do |t|
14
+ t.column :name, :string
15
+ end
16
+
17
+ create_table :bands, :force => true do |t|
18
+ t.column :name, :string
19
+ end
20
+
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'logger'
3
+ require 'active_record'
4
+
5
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
6
+ ActiveRecord::Base.configurations = YAML::load(File.open(File.dirname(__FILE__) + '/database.yml'))
7
+ ActiveRecord::Base.establish_connection(ENV['DB'] || 'mysql')
8
+
9
+ require File.dirname(__FILE__) + '/../init.rb'
10
+ require File.dirname(__FILE__) + '/models/band'
11
+ require File.dirname(__FILE__) + '/models/user'
12
+ require File.dirname(__FILE__) + '/../lib/generators/templates/model.rb'
13
+
14
+ require 'test/unit'
15
+ require 'active_support'
16
+ require 'shoulda'
17
+ require 'factory_girl'
18
+ Factory.find_definitions
19
+
20
+ load(File.dirname(__FILE__) + '/schema.rb')
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_followable
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Kristijan Sedlak
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-10 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Implements the following functionality where one model can be followed by other models and and vice versa.
23
+ email: xpepermint@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.rdoc
30
+ - MIT-LICENSE
31
+ files:
32
+ - Rakefile
33
+ - lib/acts_as_followable/followable.rb
34
+ - lib/acts_as_followable/version.rb
35
+ - lib/acts_as_followable.rb
36
+ - lib/generators/acts_as_followable_generator.rb
37
+ - lib/generators/templates/migration.rb
38
+ - lib/generators/USAGE
39
+ - test/acts_as_followable_test.rb
40
+ - test/database.yml.example
41
+ - test/factories/bands.rb
42
+ - test/factories/users.rb
43
+ - test/follow_test.rb
44
+ - test/models/band.rb
45
+ - test/models/user.rb
46
+ - test/schema.rb
47
+ - test/test_helper.rb
48
+ - test/TESTING
49
+ - README.rdoc
50
+ - MIT-LICENSE
51
+ has_rdoc: true
52
+ homepage: http://github.com/xpepermint/acts_as_followable
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README.rdoc
59
+ - --charset=UTF-8
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.7
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: ActsAsFollowable - Model following.
87
+ test_files: []
88
+