partisan 0.1.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +49 -1
- data/lib/generators/partisan/templates/migration.rb +2 -2
- data/lib/partisan.rb +12 -1
- data/lib/partisan/follow.rb +28 -0
- data/lib/partisan/followable.rb +5 -0
- data/lib/partisan/follower.rb +5 -1
- data/lib/partisan/railtie.rb +1 -9
- data/lib/partisan/version.rb +1 -1
- data/spec/follower_spec.rb +106 -0
- data/spec/spec_helper.rb +2 -1
- metadata +4 -6
- data/spec/support/extensions/active_record.rb +0 -9
data/README.md
CHANGED
@@ -11,7 +11,7 @@ It’s heavily inspired by `acts_as_follower`. However, it’s not 100% compatib
|
|
11
11
|
But I also added awesome new ones:
|
12
12
|
|
13
13
|
* You can use `following_team_ids` but also `following_team_names` (basically any `following_team_<column>s`). It takes advantage of the `pluck` method, so it doesn’t create an instance of each follower, it just return the relevant column values. (Go check `pluck` documentation, it’s simply awesome).
|
14
|
-
* The `followers` and `followings`
|
14
|
+
* The `followers` and `followings` methods now return an `ActiveRecord::Relation` for easy chaining, scoping, counting, pagination, etc.
|
15
15
|
|
16
16
|
## Installation
|
17
17
|
|
@@ -65,6 +65,8 @@ fan.following?(band)
|
|
65
65
|
# => false
|
66
66
|
```
|
67
67
|
|
68
|
+
### Cache counters
|
69
|
+
|
68
70
|
Most of the times, you would want to get a quick look at about how many fans follow a certain resource. That could be an expensive operation.
|
69
71
|
|
70
72
|
However, if the *followed* record has a `followers_count` column, Partisan will populate its value with how many followers the record has.
|
@@ -81,6 +83,52 @@ band.followers_count
|
|
81
83
|
|
82
84
|
The same concept applies to `followable` with a `following_count` column.
|
83
85
|
|
86
|
+
### Callbacks
|
87
|
+
|
88
|
+
You can define callbacks that will be triggered before or after a following relationship is created.
|
89
|
+
|
90
|
+
If a `before_follow` callback returns `false`, it will halt the call and the relationship will be not be saved (much like `ActiveRecords`’s `before_save` callbacks).
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
class Fan < ActiveRecord::Base
|
94
|
+
acts_as_follower
|
95
|
+
after_follow :send_notification
|
96
|
+
|
97
|
+
def send_notification
|
98
|
+
puts "#{self} is now following #{self.just_followed}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class Band < ActiveRecord::Base
|
103
|
+
acts_as_followable
|
104
|
+
before_follow :ensure_active_fan
|
105
|
+
|
106
|
+
def ensure_active_fan
|
107
|
+
self.about_to_be_followed_by.active?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
The available callbacks are:
|
113
|
+
|
114
|
+
#### Follower
|
115
|
+
|
116
|
+
| Callback | Reference to the followable |
|
117
|
+
| ------------------|-----------------------------|
|
118
|
+
| `before_follow` | `self.about_to_follow` |
|
119
|
+
| `after_follow` | `self.just_followed` |
|
120
|
+
| `before_unfollow` | `self.about_to_unfollow` |
|
121
|
+
| `after_unfollow` | `self.just_unfollowed` |
|
122
|
+
|
123
|
+
#### Followable
|
124
|
+
|
125
|
+
| Callback | Reference to the follower |
|
126
|
+
| ------------------|----------------------------------|
|
127
|
+
| `before_follow` | `self.about_to_be_followed_by` |
|
128
|
+
| `after_follow` | `self.just_followed_by` |
|
129
|
+
| `before_unfollow` | `self.about_to_by_unfollowed_by` |
|
130
|
+
| `after_unfollow` | `self.just_unfollowed_by` |
|
131
|
+
|
84
132
|
## License
|
85
133
|
|
86
134
|
`Partisan` is © 2013 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/partisan/blob/master/LICENSE.md) file.
|
@@ -7,8 +7,8 @@ class AddFollowsMigration < ActiveRecord::Migration
|
|
7
7
|
t.timestamps
|
8
8
|
end
|
9
9
|
|
10
|
-
add_index :follows, [
|
11
|
-
add_index :follows, [
|
10
|
+
add_index :follows, ['follower_id', 'follower_type'], name: 'index_partisan_followers'
|
11
|
+
add_index :follows, ['followable_id', 'followable_type'], name: 'index_partisan_followables'
|
12
12
|
end
|
13
13
|
|
14
14
|
def down
|
data/lib/partisan.rb
CHANGED
@@ -8,8 +8,19 @@ require "partisan/follower"
|
|
8
8
|
require "partisan/followable"
|
9
9
|
|
10
10
|
module Partisan
|
11
|
-
|
12
11
|
include Partisan::FollowHelper
|
12
|
+
|
13
|
+
def self.inject_into_active_record
|
14
|
+
@inject_into_active_record ||= Proc.new do
|
15
|
+
def self.acts_as_follower
|
16
|
+
self.send :include, Partisan::Follower
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.acts_as_followable
|
20
|
+
self.send :include, Partisan::Followable
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
15
26
|
require 'partisan/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
data/lib/partisan/follow.rb
CHANGED
@@ -14,6 +14,34 @@ module Partisan
|
|
14
14
|
after_create :update_follow_counter
|
15
15
|
after_destroy :update_follow_counter
|
16
16
|
|
17
|
+
# Follower's :follow callbacks
|
18
|
+
around_create do |follow, blk|
|
19
|
+
self.follower.about_to_follow = self.follower.just_followed = self.followable
|
20
|
+
self.follower.run_callbacks :follow, &blk
|
21
|
+
self.follower.about_to_follow = self.follower.just_followed = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
# Followable's :follow callbacks
|
25
|
+
around_create do |follow, blk|
|
26
|
+
self.followable.about_to_be_followed_by = self.followable.just_followed_by = self.follower
|
27
|
+
self.followable.run_callbacks :follow, &blk
|
28
|
+
self.followable.about_to_be_followed_by = self.followable.just_followed_by = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Follower's :unfollow callbacks
|
32
|
+
around_destroy do |follow, blk|
|
33
|
+
self.follower.about_to_unfollow = self.follower.just_unfollowed = self.followable
|
34
|
+
self.follower.run_callbacks :unfollow, &blk
|
35
|
+
self.follower.about_to_unfollow = self.follower.just_unfollowed = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# Followable's :unfollow callbacks
|
39
|
+
around_destroy do |follow, blk|
|
40
|
+
self.followable.about_to_be_unfollowed_by = self.followable.just_unfollowed_by = self.follower
|
41
|
+
self.followable.run_callbacks :unfollow, &blk
|
42
|
+
self.followable.about_to_be_unfollowed_by = self.followable.just_unfollowed_by = nil
|
43
|
+
end
|
44
|
+
|
17
45
|
protected
|
18
46
|
|
19
47
|
def update_follow_counter
|
data/lib/partisan/followable.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
module Partisan
|
2
2
|
module Followable
|
3
3
|
extend ActiveSupport::Concern
|
4
|
+
extend ActiveModel::Callbacks
|
5
|
+
|
4
6
|
include Partisan::FollowHelper
|
5
7
|
|
6
8
|
included do
|
7
9
|
has_many :followings, as: :followable, class_name: 'Partisan::Follow', dependent: :destroy
|
10
|
+
define_model_callbacks :follow
|
11
|
+
define_model_callbacks :unfollow
|
12
|
+
attr_accessor :about_to_be_followed_by, :just_followed_by, :about_to_be_unfollowed_by, :just_unfollowed_by
|
8
13
|
end
|
9
14
|
|
10
15
|
# Return true or false if the resource is following another
|
data/lib/partisan/follower.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
module Partisan
|
2
2
|
module Follower
|
3
3
|
extend ActiveSupport::Concern
|
4
|
+
extend ActiveModel::Callbacks
|
4
5
|
include Partisan::FollowHelper
|
5
6
|
|
6
7
|
included do
|
7
8
|
has_many :follows, as: :follower, class_name: 'Partisan::Follow', dependent: :destroy
|
9
|
+
define_model_callbacks :follow
|
10
|
+
define_model_callbacks :unfollow
|
11
|
+
attr_accessor :about_to_follow, :just_followed, :about_to_unfollow, :just_unfollowed
|
8
12
|
end
|
9
13
|
|
10
14
|
# Add follow record if it doesn’t exist
|
@@ -47,7 +51,7 @@ module Partisan
|
|
47
51
|
def following?(resource)
|
48
52
|
return false if self == resource
|
49
53
|
|
50
|
-
fetch_follows(resource).exists?
|
54
|
+
!!fetch_follows(resource).exists?
|
51
55
|
end
|
52
56
|
|
53
57
|
# Get all follows record related to a resource
|
data/lib/partisan/railtie.rb
CHANGED
@@ -4,15 +4,7 @@ require 'rails'
|
|
4
4
|
module Partisan
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
initializer "follows.active_record" do |app|
|
7
|
-
ActiveSupport.on_load :active_record
|
8
|
-
def self.acts_as_follower
|
9
|
-
self.send :include, Partisan::Follower
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.acts_as_followable
|
13
|
-
self.send :include, Partisan::Followable
|
14
|
-
end
|
15
|
-
end
|
7
|
+
ActiveSupport.on_load :active_record, {}, &Partisan.inject_into_active_record
|
16
8
|
end
|
17
9
|
end
|
18
10
|
end
|
data/lib/partisan/version.rb
CHANGED
data/spec/follower_spec.rb
CHANGED
@@ -80,6 +80,112 @@ describe Partisan::Follower do
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
+
describe :Callbacks do
|
84
|
+
before do
|
85
|
+
class Buffer
|
86
|
+
def self.tmp_value=(tmp_value)
|
87
|
+
@tmp_value = tmp_value
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.tmp_value
|
91
|
+
@tmp_value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'Follower callbacks' do
|
97
|
+
describe :before_follow do
|
98
|
+
before do
|
99
|
+
follower 'User' do
|
100
|
+
before_follow { Buffer.tmp_value = self.about_to_follow }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it { expect{ user.follow(band) }.to change{ Buffer.tmp_value }.to(band) }
|
105
|
+
end
|
106
|
+
|
107
|
+
describe :after_follow do
|
108
|
+
before do
|
109
|
+
follower 'User' do
|
110
|
+
after_follow { Buffer.tmp_value = self.just_followed }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it { expect{ user.follow(band) }.to change{ Buffer.tmp_value }.to(band) }
|
115
|
+
end
|
116
|
+
|
117
|
+
describe :before_unfollow do
|
118
|
+
before do
|
119
|
+
follower 'User' do
|
120
|
+
before_unfollow { Buffer.tmp_value = self.about_to_unfollow }
|
121
|
+
end
|
122
|
+
|
123
|
+
user.follow(band)
|
124
|
+
end
|
125
|
+
|
126
|
+
it { expect{ user.unfollow(band) }.to change{ Buffer.tmp_value }.to(band) }
|
127
|
+
end
|
128
|
+
|
129
|
+
describe :after_unfollow do
|
130
|
+
before do
|
131
|
+
follower 'User' do
|
132
|
+
after_unfollow { Buffer.tmp_value = self.about_to_unfollow }
|
133
|
+
end
|
134
|
+
|
135
|
+
user.follow(band)
|
136
|
+
end
|
137
|
+
|
138
|
+
it { expect{ user.unfollow(band) }.to change{ Buffer.tmp_value }.to(band) }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'Followable callbacks' do
|
143
|
+
describe :before_follow do
|
144
|
+
before do
|
145
|
+
followable 'Band' do
|
146
|
+
before_follow { Buffer.tmp_value = self.about_to_be_followed_by }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it { expect{ user.follow(band) }.to change{ Buffer.tmp_value }.to(user) }
|
151
|
+
end
|
152
|
+
|
153
|
+
describe :after_follow do
|
154
|
+
before do
|
155
|
+
followable 'Band' do
|
156
|
+
after_follow { Buffer.tmp_value = self.just_followed_by }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
it { expect{ user.follow(band) }.to change{ Buffer.tmp_value }.to(user) }
|
161
|
+
end
|
162
|
+
|
163
|
+
describe :before_unfollow do
|
164
|
+
before do
|
165
|
+
followable 'Band' do
|
166
|
+
before_unfollow { Buffer.tmp_value = self.about_to_be_unfollowed_by }
|
167
|
+
end
|
168
|
+
|
169
|
+
user.follow(band)
|
170
|
+
end
|
171
|
+
|
172
|
+
it { expect{ user.unfollow(band) }.to change{ Buffer.tmp_value }.to(user) }
|
173
|
+
end
|
174
|
+
|
175
|
+
describe :after_unfollow do
|
176
|
+
before do
|
177
|
+
followable 'Band' do
|
178
|
+
after_unfollow { Buffer.tmp_value = self.just_unfollowed_by }
|
179
|
+
end
|
180
|
+
|
181
|
+
user.follow(band)
|
182
|
+
end
|
183
|
+
|
184
|
+
it { expect{ user.unfollow(band) }.to change{ Buffer.tmp_value }.to(user) }
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
83
189
|
describe :AliasMethods do
|
84
190
|
subject { User.create }
|
85
191
|
|
data/spec/spec_helper.rb
CHANGED
@@ -7,8 +7,9 @@ require 'partisan'
|
|
7
7
|
|
8
8
|
# Require our macros and extensions
|
9
9
|
Dir[File.expand_path('../../spec/support/macros/*.rb', __FILE__)].map(&method(:require))
|
10
|
-
Dir[File.expand_path('../../spec/support/extensions/*.rb', __FILE__)].map(&method(:require))
|
11
10
|
|
11
|
+
# Inject our methods into ActiveRecord (like our railtie does)
|
12
|
+
ActiveRecord::Base.class_eval(&Partisan.inject_into_active_record)
|
12
13
|
|
13
14
|
RSpec.configure do |config|
|
14
15
|
# Include our macros
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: partisan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -120,7 +120,6 @@ files:
|
|
120
120
|
- spec/followable_spec.rb
|
121
121
|
- spec/follower_spec.rb
|
122
122
|
- spec/spec_helper.rb
|
123
|
-
- spec/support/extensions/active_record.rb
|
124
123
|
- spec/support/macros/database_macros.rb
|
125
124
|
- spec/support/macros/model_macros.rb
|
126
125
|
homepage: https://github.com/simonprev/partisan
|
@@ -138,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
137
|
version: '0'
|
139
138
|
segments:
|
140
139
|
- 0
|
141
|
-
hash: -
|
140
|
+
hash: -352093583781721099
|
142
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
142
|
none: false
|
144
143
|
requirements:
|
@@ -147,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
146
|
version: '0'
|
148
147
|
segments:
|
149
148
|
- 0
|
150
|
-
hash: -
|
149
|
+
hash: -352093583781721099
|
151
150
|
requirements: []
|
152
151
|
rubyforge_project:
|
153
152
|
rubygems_version: 1.8.23
|
@@ -159,6 +158,5 @@ test_files:
|
|
159
158
|
- spec/followable_spec.rb
|
160
159
|
- spec/follower_spec.rb
|
161
160
|
- spec/spec_helper.rb
|
162
|
-
- spec/support/extensions/active_record.rb
|
163
161
|
- spec/support/macros/database_macros.rb
|
164
162
|
- spec/support/macros/model_macros.rb
|