acts_as_votable 0.12.0 → 0.13.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Code Climate](https://codeclimate.com/github/ryanto/acts_as_votable.png)](https://codeclimate.com/github/ryanto/acts_as_votable)
|
3
|
+
![Build status](https://github.com/ryanto/acts_as_votable/workflows/CI/badge.svg)
|
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
|
-
|