acts_as_votable 0.12.0 → 0.13.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.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +44 -0
- data/.ruby-version +1 -0
- data/Appraisals +11 -9
- data/README.md +59 -91
- data/acts_as_votable.gemspec +1 -3
- data/gemfiles/rails_4.gemfile +1 -1
- data/gemfiles/rails_5_1.gemfile +1 -1
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_6.gemfile +8 -0
- data/gemfiles/rails_6_1.gemfile +8 -0
- data/gemfiles/rails_6_rc1.gemfile +8 -0
- data/lib/acts_as_votable/cacheable.rb +15 -11
- data/lib/acts_as_votable/extenders/votable.rb +2 -2
- data/lib/acts_as_votable/version.rb +1 -1
- data/lib/acts_as_votable/votable.rb +12 -11
- data/lib/acts_as_votable/voter.rb +1 -1
- data/lib/generators/acts_as_votable/migration/migration_generator.rb +12 -0
- data/lib/generators/acts_as_votable/migration/templates/active_record/migration.erb +2 -2
- data/spec/factories/votable_cache_update_attributes.rb +1 -1
- data/spec/shared_example/votable_model.rb +4 -4
- data/spec/spec_helper.rb +2 -2
- metadata +13 -10
- data/.travis.yml +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6493d9c06d86a52dc314e405d87f1cb571d5af56d5e2a0b143e700f864d2ba24
|
4
|
+
data.tar.gz: e832c7530a935db303318540558b8de0c7992e6be33c31efc6dd69fecdd56092
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ba57359f7c30c08272f97a5c066a8b0f9ec8eb01c12966abf589a7d005542910a3b7fb3162bdd7eb3924f38bd081bafb174e73038a107448d7c1da7c7b1299b
|
7
|
+
data.tar.gz: f63bc1fbca5eb2fca9bd8a9182eb9ae669975f01edaa2e6beb0cc82399ff26ccb18e89c71e4659eea2a29532f6003d8c48748b1ea4be1f88fad3de5e7f3e978b
|
@@ -0,0 +1,44 @@
|
|
1
|
+
name: CI
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
pull_request:
|
7
|
+
branches:
|
8
|
+
- master
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
tests:
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
os:
|
16
|
+
- ubuntu
|
17
|
+
ruby:
|
18
|
+
- 2.5
|
19
|
+
- 2.6
|
20
|
+
- 2.7
|
21
|
+
gemfile:
|
22
|
+
- gemfiles/rails_5_1.gemfile
|
23
|
+
- gemfiles/rails_5_2.gemfile
|
24
|
+
- gemfiles/rails_6.gemfile
|
25
|
+
- gemfiles/rails_6_1.gemfile
|
26
|
+
continue-on-error:
|
27
|
+
- false
|
28
|
+
|
29
|
+
env:
|
30
|
+
BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
|
31
|
+
runs-on: ${{ matrix.os }}-latest
|
32
|
+
continue-on-error: ${{ matrix.continue-on-error }}
|
33
|
+
steps:
|
34
|
+
- name: Checkout
|
35
|
+
uses: actions/checkout@v2
|
36
|
+
- name: Setup Ruby
|
37
|
+
uses: ruby/setup-ruby@v1
|
38
|
+
with:
|
39
|
+
ruby-version: ${{ matrix.ruby }}
|
40
|
+
bundler-cache: true
|
41
|
+
- name: Test
|
42
|
+
run: bundle exec rake spec
|
43
|
+
|
44
|
+
# use this
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.3
|
data/Appraisals
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
appraise "rails-
|
4
|
-
gem "rails", "
|
3
|
+
appraise "rails-5-1" do
|
4
|
+
gem "rails", "5.1.7"
|
5
5
|
end
|
6
6
|
|
7
|
-
appraise "rails-5" do
|
8
|
-
gem "rails", "5.
|
7
|
+
appraise "rails-5-2" do
|
8
|
+
gem "rails", "5.2.4"
|
9
9
|
end
|
10
10
|
|
11
|
-
appraise "rails-
|
12
|
-
gem "rails", "
|
11
|
+
appraise "rails-6" do
|
12
|
+
gem "rails", "6.0.3"
|
13
|
+
gem "sqlite3", "~> 1.4"
|
13
14
|
end
|
14
15
|
|
15
|
-
appraise "rails-
|
16
|
-
gem "rails", "
|
17
|
-
|
16
|
+
appraise "rails-6-1" do
|
17
|
+
gem "rails", "6.1.0"
|
18
|
+
gem "sqlite3", "~> 1.4"
|
19
|
+
end
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Acts As Votable (aka Acts As Likeable)
|
2
2
|
|
3
|
-
|
4
|
-
[](https://codeclimate.com/github/ryanto/acts_as_votable)
|
3
|
+

|
5
4
|
|
6
5
|
Acts As Votable is a Ruby Gem specifically written for Rails/ActiveRecord models.
|
7
6
|
The main goals of this gem are:
|
@@ -16,15 +15,15 @@ The main goals of this gem are:
|
|
16
15
|
|
17
16
|
### Supported Ruby and Rails versions
|
18
17
|
|
19
|
-
|
20
|
-
|
18
|
+
- Ruby >= 2.5.0
|
19
|
+
- Rails >= 5.1
|
21
20
|
|
22
21
|
### Install
|
23
22
|
|
24
23
|
Just add the following to your Gemfile to install the latest release.
|
25
24
|
|
26
25
|
```ruby
|
27
|
-
gem 'acts_as_votable'
|
26
|
+
gem 'acts_as_votable'
|
28
27
|
```
|
29
28
|
|
30
29
|
And follow that up with a ``bundle install``.
|
@@ -34,8 +33,10 @@ And follow that up with a ``bundle install``.
|
|
34
33
|
Acts As Votable uses a votes table to store all voting information. To
|
35
34
|
generate and run the migration just use.
|
36
35
|
|
37
|
-
|
38
|
-
|
36
|
+
```bash
|
37
|
+
rails generate acts_as_votable:migration
|
38
|
+
rails db:migrate
|
39
|
+
```
|
39
40
|
|
40
41
|
You will get a performance increase by adding in cached columns to your model's
|
41
42
|
tables. You will have to do this manually through your own migrations. See the
|
@@ -46,11 +47,11 @@ caching section of this document for more information.
|
|
46
47
|
### Votable Models
|
47
48
|
|
48
49
|
```ruby
|
49
|
-
class Post <
|
50
|
+
class Post < ApplicationRecord
|
50
51
|
acts_as_votable
|
51
52
|
end
|
52
53
|
|
53
|
-
@post = Post.new(:
|
54
|
+
@post = Post.new(name: 'my post!')
|
54
55
|
@post.save
|
55
56
|
|
56
57
|
@post.liked_by @user
|
@@ -65,9 +66,9 @@ more natural calls are the first few examples.
|
|
65
66
|
```ruby
|
66
67
|
@post.liked_by @user1
|
67
68
|
@post.downvote_from @user2
|
68
|
-
@post.vote_by :
|
69
|
-
@post.vote_by :
|
70
|
-
@post.vote_by :
|
69
|
+
@post.vote_by voter: @user3
|
70
|
+
@post.vote_by voter: @user4, vote: 'bad'
|
71
|
+
@post.vote_by voter: @user5, vote: 'like'
|
71
72
|
```
|
72
73
|
|
73
74
|
By default all votes are positive, so `@user3` has cast a 'good' vote for `@post`.
|
@@ -76,7 +77,6 @@ By default all votes are positive, so `@user3` has cast a 'good' vote for `@post
|
|
76
77
|
|
77
78
|
`@user2` and `@user4` on the other had has voted against `@post`.
|
78
79
|
|
79
|
-
|
80
80
|
Just about any word works for casting a vote in favor or against post. Up/Down,
|
81
81
|
Like/Dislike, Positive/Negative... the list goes on-and-on. Boolean flags `true` and
|
82
82
|
`false` are also applicable.
|
@@ -86,12 +86,12 @@ Revisiting the previous example of code.
|
|
86
86
|
```ruby
|
87
87
|
# positive votes
|
88
88
|
@post.liked_by @user1
|
89
|
-
@post.vote_by :
|
90
|
-
@post.vote_by :
|
89
|
+
@post.vote_by voter: @user3
|
90
|
+
@post.vote_by voter: @user5, vote: 'like'
|
91
91
|
|
92
92
|
# negative votes
|
93
93
|
@post.downvote_from @user2
|
94
|
-
@post.vote_by :
|
94
|
+
@post.vote_by voter: @user2, vote: 'bad'
|
95
95
|
|
96
96
|
# tally them up!
|
97
97
|
@post.votes_for.size # => 5
|
@@ -142,50 +142,51 @@ You can add a scope to your vote
|
|
142
142
|
|
143
143
|
```ruby
|
144
144
|
# positive votes
|
145
|
-
@post.liked_by @user1, :
|
146
|
-
@post.vote_by :
|
147
|
-
@post.vote_by :
|
145
|
+
@post.liked_by @user1, vote_scope: 'rank'
|
146
|
+
@post.vote_by voter: @user3, vote_scope: 'rank'
|
147
|
+
@post.vote_by voter: @user5, vote: 'like', vote_scope: 'rank'
|
148
148
|
|
149
149
|
# negative votes
|
150
|
-
@post.downvote_from @user2, :
|
151
|
-
@post.vote_by :
|
150
|
+
@post.downvote_from @user2, vote_scope: 'rank'
|
151
|
+
@post.vote_by voter: @user2, vote: 'bad', vote_scope: 'rank'
|
152
152
|
|
153
153
|
# tally them up!
|
154
|
-
@post.find_votes_for(:
|
155
|
-
@post.get_likes(:
|
156
|
-
@post.get_upvotes(:
|
157
|
-
@post.get_dislikes(:
|
158
|
-
@post.get_downvotes(:
|
154
|
+
@post.find_votes_for(vote_scope: 'rank').size # => 5
|
155
|
+
@post.get_likes(vote_scope: 'rank').size # => 3
|
156
|
+
@post.get_upvotes(vote_scope: 'rank').size # => 3
|
157
|
+
@post.get_dislikes(vote_scope: 'rank').size # => 2
|
158
|
+
@post.get_downvotes(vote_scope: 'rank').size # => 2
|
159
159
|
|
160
160
|
# votable model can be voted under different scopes
|
161
161
|
# by the same user
|
162
|
-
@post.vote_by :
|
163
|
-
@post.vote_by :
|
162
|
+
@post.vote_by voter: @user1, vote_scope: 'week'
|
163
|
+
@post.vote_by voter: @user1, vote_scope: 'month'
|
164
164
|
|
165
165
|
@post.votes_for.size # => 2
|
166
|
-
@post.find_votes_for(:
|
167
|
-
@post.find_votes_for(:
|
166
|
+
@post.find_votes_for(vote_scope: 'week').size # => 1
|
167
|
+
@post.find_votes_for(vote_scope: 'month').size # => 1
|
168
168
|
```
|
169
|
+
|
169
170
|
### Adding weights to your votes
|
170
171
|
|
171
172
|
You can add weight to your vote. The default value is 1.
|
172
173
|
|
173
174
|
```ruby
|
174
175
|
# positive votes
|
175
|
-
@post.liked_by @user1, :
|
176
|
-
@post.vote_by :
|
177
|
-
@post.vote_by :
|
176
|
+
@post.liked_by @user1, vote_weight: 1
|
177
|
+
@post.vote_by voter: @user3, vote_weight: 2
|
178
|
+
@post.vote_by voter: @user5, vote: 'like', vote_scope: 'rank', vote_weight: 3
|
178
179
|
|
179
180
|
# negative votes
|
180
|
-
@post.downvote_from @user2, :
|
181
|
-
@post.vote_by :
|
181
|
+
@post.downvote_from @user2, vote_scope: 'rank', vote_weight: 1
|
182
|
+
@post.vote_by voter: @user2, vote: 'bad', vote_scope: 'rank', vote_weight: 3
|
182
183
|
|
183
184
|
# tally them up!
|
184
|
-
@post.find_votes_for(:
|
185
|
-
@post.get_likes(:
|
186
|
-
@post.get_upvotes(:
|
187
|
-
@post.get_dislikes(:
|
188
|
-
@post.get_downvotes(:
|
185
|
+
@post.find_votes_for(vote_scope: 'rank').sum(:vote_weight) # => 6
|
186
|
+
@post.get_likes(vote_scope: 'rank').sum(:vote_weight) # => 6
|
187
|
+
@post.get_upvotes(vote_scope: 'rank').sum(:vote_weight) # => 6
|
188
|
+
@post.get_dislikes(vote_scope: 'rank').sum(:vote_weight) # => 4
|
189
|
+
@post.get_downvotes(vote_scope: 'rank').sum(:vote_weight) # => 4
|
189
190
|
```
|
190
191
|
|
191
192
|
### The Voter
|
@@ -193,15 +194,15 @@ You can add weight to your vote. The default value is 1.
|
|
193
194
|
You can have your voters `acts_as_voter` to provide some reserve functionality.
|
194
195
|
|
195
196
|
```ruby
|
196
|
-
class User <
|
197
|
+
class User < ApplicationRecord
|
197
198
|
acts_as_voter
|
198
199
|
end
|
199
200
|
|
200
201
|
@user.likes @article
|
201
202
|
|
202
|
-
@article.
|
203
|
-
@article.
|
204
|
-
@article.
|
203
|
+
@article.votes_for.size # => 1
|
204
|
+
@article.get_likes.size # => 1
|
205
|
+
@article.get_dislikes.size # => 0
|
205
206
|
```
|
206
207
|
|
207
208
|
To check if a voter has voted on a model, you can use ``voted_for?``. You can
|
@@ -274,8 +275,8 @@ because `@user` has already voted for `@shoe`.
|
|
274
275
|
@user.likes @shoe
|
275
276
|
@user.likes @shoe
|
276
277
|
|
277
|
-
@shoe.
|
278
|
-
@shoe.
|
278
|
+
@shoe.votes_for.size # => 1
|
279
|
+
@shoe.get_likes.size # => 1
|
279
280
|
```
|
280
281
|
|
281
282
|
To check if a vote counted, or registered, use `vote_registered?` on your model
|
@@ -291,16 +292,16 @@ after voting. For example:
|
|
291
292
|
@hat.disliked_by @user
|
292
293
|
@hat.vote_registered? # => true, because user changed their vote
|
293
294
|
|
294
|
-
@hat.
|
295
|
-
@hat.
|
296
|
-
@hat.
|
295
|
+
@hat.votes_for.size # => 1
|
296
|
+
@hat.get_positives.size # => 0
|
297
|
+
@hat.get_negatives.size # => 1
|
297
298
|
```
|
298
299
|
|
299
300
|
To permit duplicates entries of a same voter, use option duplicate. Also notice that this
|
300
301
|
will limit some other methods that didn't deal with multiples votes, in this case, the last vote will be considered.
|
301
302
|
|
302
303
|
```ruby
|
303
|
-
@hat.vote_by voter: @user, :
|
304
|
+
@hat.vote_by voter: @user, duplicate: true
|
304
305
|
```
|
305
306
|
|
306
307
|
## Caching
|
@@ -351,7 +352,7 @@ end
|
|
351
352
|
Order by average rating:
|
352
353
|
|
353
354
|
```ruby
|
354
|
-
Post.order(:
|
355
|
+
Post.order(cached_weighted_average: :desc)
|
355
356
|
```
|
356
357
|
|
357
358
|
Display average rating:
|
@@ -360,63 +361,30 @@ Display average rating:
|
|
360
361
|
<%= post.weighted_average.round(2) %> / 5
|
361
362
|
<!-- 3.5 / 5 -->
|
362
363
|
```
|
363
|
-
|
364
|
+
|
365
|
+
## Votable model's `updated_at`
|
364
366
|
|
365
367
|
You can control whether `updated_at` column of votable model will be touched or
|
366
368
|
not by passing `cacheable_strategy` option to `acts_as_votable` method.
|
367
369
|
|
368
|
-
By default, `
|
370
|
+
By default, `update` strategy is used. Pass `:update_columns` as
|
369
371
|
`cacheable_strategy` if you don't want to touch model's `updated_at` column.
|
372
|
+
|
370
373
|
```ruby
|
371
|
-
class Post <
|
374
|
+
class Post < ApplicationRecord
|
372
375
|
acts_as_votable cacheable_strategy: :update_columns
|
373
376
|
end
|
374
377
|
```
|
375
378
|
|
376
|
-
NOTE: this option does not work for ActiveRecord < 3.1
|
377
|
-
|
378
|
-
|
379
379
|
## Testing
|
380
380
|
|
381
381
|
All tests follow the RSpec format and are located in the spec directory.
|
382
382
|
They can be run with:
|
383
383
|
|
384
|
-
```
|
384
|
+
```bash
|
385
385
|
rake spec
|
386
386
|
```
|
387
387
|
|
388
|
-
## Changes
|
389
|
-
|
390
|
-
### Fixes for votable voter model
|
391
|
-
|
392
|
-
In version 0.8.0, there are bugs for a model that is both votable and voter.
|
393
|
-
Some name-conflicting methods are renamed:
|
394
|
-
+ Renamed Votable.votes to votes_for
|
395
|
-
+ Renamed Votable.vote to vote_by,
|
396
|
-
+ Removed Votable.vote_by alias (was an alias for :vote_up)
|
397
|
-
+ Renamed Votable.unvote_for to unvote_by
|
398
|
-
+ Renamed Votable.find_votes to find_votes_for
|
399
|
-
+ Renamed Votable.up_votes to get_upvotes
|
400
|
-
+ and its aliases :get_true_votes, :get_ups, :get_upvotes, :get_likes, :get_positives, :get_for_votes
|
401
|
-
+ Renamed Votable.down_votes to get_downvotes
|
402
|
-
+ and its aliases :get_false_votes, :get_downs, :get_downvotes, :get_dislikes, :get_negatives
|
403
|
-
|
404
|
-
|
405
388
|
## License
|
406
389
|
|
407
|
-
Acts as votable is released under the [MIT
|
408
|
-
License](http://www.opensource.org/licenses/MIT).
|
409
|
-
|
410
|
-
## Next steps
|
411
|
-
|
412
|
-
- Pass in a block of options when creating acts_as. Allow for things
|
413
|
-
like disabling the aliasing
|
414
|
-
|
415
|
-
- Smarter language syntax. Example: `@user.likes` will return all of the votables
|
416
|
-
that the user likes, while `@user.likes @model` will cast a vote for @model by
|
417
|
-
@user.
|
418
|
-
|
419
|
-
- The aliased methods are referred to by using the terms 'up/down' and/or
|
420
|
-
'true/false'. Need to come up with guidelines for naming these methods.
|
421
|
-
|
422
|
-
- Create more aliases. Specifically for counting votes and finding votes.
|
390
|
+
Acts as votable is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/acts_as_votable.gemspec
CHANGED
@@ -15,15 +15,13 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.description = "Rails gem to allowing records to be votable"
|
16
16
|
s.license = "MIT"
|
17
17
|
|
18
|
-
s.rubyforge_project = "acts_as_votable"
|
19
|
-
|
20
18
|
s.files = `git ls-files`.split("\n")
|
21
19
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
23
21
|
s.require_paths = ["lib"]
|
24
22
|
|
25
23
|
s.add_development_dependency "rspec", "~> 3.6"
|
26
|
-
s.add_development_dependency "sqlite3", "~> 1.3"
|
24
|
+
s.add_development_dependency "sqlite3", "~> 1.3.6"
|
27
25
|
s.add_development_dependency "rubocop", "~> 0.49.1"
|
28
26
|
s.add_development_dependency "simplecov", "~> 0.15.0"
|
29
27
|
s.add_development_dependency "appraisal", "~> 2.2"
|
data/gemfiles/rails_4.gemfile
CHANGED
data/gemfiles/rails_5_1.gemfile
CHANGED
data/gemfiles/rails_5_2.gemfile
CHANGED
@@ -40,10 +40,6 @@ module ActsAsVotable
|
|
40
40
|
def update_cached_votes(vote_scope = nil)
|
41
41
|
updates = {}
|
42
42
|
|
43
|
-
if self.respond_to?(:cached_votes_total=)
|
44
|
-
updates[:cached_votes_total] = count_votes_total(true)
|
45
|
-
end
|
46
|
-
|
47
43
|
if self.respond_to?(:cached_votes_up=)
|
48
44
|
updates[:cached_votes_up] = count_votes_up(true)
|
49
45
|
end
|
@@ -52,6 +48,13 @@ module ActsAsVotable
|
|
52
48
|
updates[:cached_votes_down] = count_votes_down(true)
|
53
49
|
end
|
54
50
|
|
51
|
+
if self.respond_to?(:cached_votes_total=)
|
52
|
+
updates[:cached_votes_total] = (
|
53
|
+
(updates[:cached_votes_up] || count_votes_up(true)) +
|
54
|
+
(updates[:cached_votes_down] || count_votes_down(true))
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
55
58
|
if self.respond_to?(:cached_votes_score=)
|
56
59
|
updates[:cached_votes_score] = (
|
57
60
|
(updates[:cached_votes_up] || count_votes_up(true)) -
|
@@ -72,10 +75,6 @@ module ActsAsVotable
|
|
72
75
|
end
|
73
76
|
|
74
77
|
if vote_scope
|
75
|
-
if self.respond_to?(scope_cache_field :cached_votes_total=, vote_scope)
|
76
|
-
updates[scope_cache_field :cached_votes_total, vote_scope] = count_votes_total(true, vote_scope)
|
77
|
-
end
|
78
|
-
|
79
78
|
if self.respond_to?(scope_cache_field :cached_votes_up=, vote_scope)
|
80
79
|
updates[scope_cache_field :cached_votes_up, vote_scope] = count_votes_up(true, vote_scope)
|
81
80
|
end
|
@@ -84,6 +83,13 @@ module ActsAsVotable
|
|
84
83
|
updates[scope_cache_field :cached_votes_down, vote_scope] = count_votes_down(true, vote_scope)
|
85
84
|
end
|
86
85
|
|
86
|
+
if self.respond_to?(scope_cache_field :cached_votes_total=, vote_scope)
|
87
|
+
updates[scope_cache_field :cached_votes_total, vote_scope] = (
|
88
|
+
(updates[scope_cache_field :cached_votes_up, vote_scope] || count_votes_up(true, vote_scope)) +
|
89
|
+
(updates[scope_cache_field :cached_votes_down, vote_scope] || count_votes_down(true, vote_scope))
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
87
93
|
if self.respond_to?(scope_cache_field :cached_weighted_total=, vote_scope)
|
88
94
|
updates[scope_cache_field :cached_weighted_total, vote_scope] = weighted_total(true, vote_scope)
|
89
95
|
end
|
@@ -136,9 +142,7 @@ module ActsAsVotable
|
|
136
142
|
|
137
143
|
def weighted_total(skip_cache = false, vote_scope = nil)
|
138
144
|
from_cache(skip_cache, :cached_weighted_total, vote_scope) do
|
139
|
-
|
140
|
-
downs = get_down_votes(vote_scope: vote_scope).sum(:vote_weight)
|
141
|
-
ups + downs
|
145
|
+
find_votes_for(scope_or_empty_hash(vote_scope)).sum(:vote_weight)
|
142
146
|
end
|
143
147
|
end
|
144
148
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActsAsVotable
|
4
4
|
module Extenders
|
5
5
|
module Votable
|
6
|
-
ALLOWED_CACHEABLE_STRATEGIES = %i[
|
6
|
+
ALLOWED_CACHEABLE_STRATEGIES = %i[update update_columns]
|
7
7
|
|
8
8
|
def votable?
|
9
9
|
false
|
@@ -23,7 +23,7 @@ module ActsAsVotable
|
|
23
23
|
|
24
24
|
class_eval do
|
25
25
|
@acts_as_votable_options = {
|
26
|
-
cacheable_strategy: :
|
26
|
+
cacheable_strategy: :update
|
27
27
|
}.merge(args)
|
28
28
|
|
29
29
|
def self.votable?
|
@@ -35,7 +35,7 @@ module ActsAsVotable
|
|
35
35
|
}
|
36
36
|
|
37
37
|
base.class_eval do
|
38
|
-
has_many :votes_for, class_name: "ActsAsVotable::Vote", as: :votable, dependent: :
|
38
|
+
has_many :votes_for, class_name: "ActsAsVotable::Vote", as: :votable, dependent: :delete_all do
|
39
39
|
def voters
|
40
40
|
includes(:voter).map(&:voter)
|
41
41
|
end
|
@@ -74,7 +74,7 @@ module ActsAsVotable
|
|
74
74
|
# find the vote
|
75
75
|
votes = find_votes_by(options[:voter], options[:vote_scope])
|
76
76
|
|
77
|
-
if
|
77
|
+
if options[:duplicate] || !votes.exists?
|
78
78
|
# this voter has never voted
|
79
79
|
vote = ActsAsVotable::Vote.new(
|
80
80
|
votable: self,
|
@@ -93,26 +93,27 @@ module ActsAsVotable
|
|
93
93
|
#Allowing for a vote_weight to be associated with every vote. Could change with every voter object
|
94
94
|
vote.vote_weight = (options[:vote_weight].to_i if options[:vote_weight].present?) || 1
|
95
95
|
|
96
|
+
vote_saved = false
|
96
97
|
ActiveRecord::Base.transaction do
|
97
98
|
self.vote_registered = false
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
99
|
+
vote_saved = vote.save
|
100
|
+
if vote_saved
|
101
|
+
self.vote_registered = true if last_update != vote.updated_at
|
102
|
+
update_cached_votes(options[:vote_scope])
|
103
|
+
end
|
103
104
|
end
|
105
|
+
vote_saved
|
104
106
|
end
|
105
107
|
|
106
108
|
def unvote(args = {})
|
107
109
|
return false if args[:voter].nil?
|
108
110
|
votes = find_votes_by(args[:voter], args[:vote_scope])
|
109
111
|
|
110
|
-
return true if votes.empty?
|
111
112
|
ActiveRecord::Base.transaction do
|
112
|
-
votes.
|
113
|
-
update_cached_votes
|
113
|
+
deleted_count = votes.delete_all
|
114
|
+
update_cached_votes(args[:vote_scope]) if deleted_count > 0
|
114
115
|
end
|
115
|
-
self.vote_registered = false
|
116
|
+
self.vote_registered = false
|
116
117
|
return true
|
117
118
|
end
|
118
119
|
|
@@ -18,7 +18,7 @@ module ActsAsVotable
|
|
18
18
|
|
19
19
|
base.class_eval do
|
20
20
|
|
21
|
-
has_many :votes, class_name: "ActsAsVotable::Vote", as: :voter, dependent: :
|
21
|
+
has_many :votes, class_name: "ActsAsVotable::Vote", as: :voter, dependent: :delete_all do
|
22
22
|
def votables
|
23
23
|
includes(:votable).map(&:votable)
|
24
24
|
end
|
@@ -36,11 +36,23 @@ module ActsAsVotable
|
|
36
36
|
def migration_version
|
37
37
|
if rails5?
|
38
38
|
"[4.2]"
|
39
|
+
elsif rails6?
|
40
|
+
"[6.0]"
|
41
|
+
elsif rails7?
|
42
|
+
"[7.0]"
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
46
|
def rails5?
|
43
47
|
Rails.version.start_with? "5"
|
44
48
|
end
|
49
|
+
|
50
|
+
def rails6?
|
51
|
+
Rails.version.start_with? "6"
|
52
|
+
end
|
53
|
+
|
54
|
+
def rails7?
|
55
|
+
Rails.version.start_with? "7"
|
56
|
+
end
|
45
57
|
end
|
46
58
|
end
|
@@ -2,8 +2,8 @@ class ActsAsVotableMigration < ActiveRecord::Migration<%= migration_version %>
|
|
2
2
|
def self.up
|
3
3
|
create_table :votes do |t|
|
4
4
|
|
5
|
-
t.references :votable, :
|
6
|
-
t.references :voter, :
|
5
|
+
t.references :votable, polymorphic: true
|
6
|
+
t.references :voter, polymorphic: true
|
7
7
|
|
8
8
|
t.boolean :vote_flag
|
9
9
|
t.string :vote_scope
|
@@ -411,12 +411,12 @@ shared_examples "a votable_model" do
|
|
411
411
|
|
412
412
|
before { votable_cache.vote_by voter: voter }
|
413
413
|
|
414
|
-
context "
|
415
|
-
let(:votable_cache) { create(:
|
414
|
+
context "update" do
|
415
|
+
let(:votable_cache) { create(:votable_cache_update, name: "voting model with cache", updated_at: updated_at) }
|
416
416
|
|
417
417
|
it do
|
418
418
|
expect(votable_cache.cached_votes_total).to eq(1)
|
419
|
-
expect(votable_cache.updated_at).to_not eq updated_at
|
419
|
+
expect(votable_cache.updated_at.to_i).to_not eq updated_at.to_i
|
420
420
|
end
|
421
421
|
end
|
422
422
|
|
@@ -425,7 +425,7 @@ shared_examples "a votable_model" do
|
|
425
425
|
|
426
426
|
it do
|
427
427
|
expect(votable_cache.cached_votes_total).to eq(1)
|
428
|
-
expect(votable_cache.updated_at).to eq updated_at
|
428
|
+
expect(votable_cache.updated_at.to_i).to eq updated_at.to_i
|
429
429
|
end
|
430
430
|
end
|
431
431
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -124,8 +124,8 @@ class VotableCache < ActiveRecord::Base
|
|
124
124
|
validates_presence_of :name
|
125
125
|
end
|
126
126
|
|
127
|
-
class
|
128
|
-
acts_as_votable cacheable_strategy: :
|
127
|
+
class VotableCacheUpdate < VotableCache
|
128
|
+
acts_as_votable cacheable_strategy: :update
|
129
129
|
end
|
130
130
|
|
131
131
|
class VotableCacheUpdateColumns < VotableCache
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_votable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.3.6
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.3.6
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,9 +101,10 @@ executables: []
|
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
|
+
- ".github/workflows/main.yml"
|
104
105
|
- ".gitignore"
|
105
106
|
- ".rubocop.yml"
|
106
|
-
- ".
|
107
|
+
- ".ruby-version"
|
107
108
|
- Appraisals
|
108
109
|
- Gemfile
|
109
110
|
- README.md
|
@@ -114,6 +115,9 @@ files:
|
|
114
115
|
- gemfiles/rails_5.gemfile
|
115
116
|
- gemfiles/rails_5_1.gemfile
|
116
117
|
- gemfiles/rails_5_2.gemfile
|
118
|
+
- gemfiles/rails_6.gemfile
|
119
|
+
- gemfiles/rails_6_1.gemfile
|
120
|
+
- gemfiles/rails_6_rc1.gemfile
|
117
121
|
- lib/acts_as_votable.rb
|
118
122
|
- lib/acts_as_votable/cacheable.rb
|
119
123
|
- lib/acts_as_votable/extenders/controller.rb
|
@@ -148,7 +152,7 @@ homepage: http://rubygems.org/gems/acts_as_votable
|
|
148
152
|
licenses:
|
149
153
|
- MIT
|
150
154
|
metadata: {}
|
151
|
-
post_install_message:
|
155
|
+
post_install_message:
|
152
156
|
rdoc_options: []
|
153
157
|
require_paths:
|
154
158
|
- lib
|
@@ -163,9 +167,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
167
|
- !ruby/object:Gem::Version
|
164
168
|
version: '0'
|
165
169
|
requirements: []
|
166
|
-
|
167
|
-
|
168
|
-
signing_key:
|
170
|
+
rubygems_version: 3.2.2
|
171
|
+
signing_key:
|
169
172
|
specification_version: 4
|
170
173
|
summary: Rails gem to allowing records to be votable
|
171
174
|
test_files:
|
data/.travis.yml
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
|
3
|
-
cache: bundler
|
4
|
-
|
5
|
-
rvm:
|
6
|
-
- 2.3.4
|
7
|
-
- 2.4.2
|
8
|
-
- 2.5.1
|
9
|
-
|
10
|
-
before_install:
|
11
|
-
- gem update --system
|
12
|
-
|
13
|
-
gemfile:
|
14
|
-
- gemfiles/rails_4.gemfile
|
15
|
-
- gemfiles/rails_5.gemfile
|
16
|
-
- gemfiles/rails_5_1.gemfile
|
17
|
-
- gemfiles/rails_5_2.gemfile
|
18
|
-
|