acts_as_votable 0.10.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +44 -0
  3. data/.gitignore +10 -6
  4. data/.rubocop.yml +121 -0
  5. data/.ruby-version +1 -0
  6. data/Appraisals +23 -0
  7. data/Gemfile +3 -14
  8. data/{README.markdown → README.md} +87 -52
  9. data/Rakefile +6 -4
  10. data/acts_as_votable.gemspec +12 -7
  11. data/gemfiles/.bundle/config +2 -0
  12. data/gemfiles/rails_4.gemfile +7 -0
  13. data/gemfiles/rails_5.gemfile +7 -0
  14. data/gemfiles/rails_5_1.gemfile +7 -0
  15. data/gemfiles/rails_5_2.gemfile +7 -0
  16. data/gemfiles/rails_6.gemfile +8 -0
  17. data/gemfiles/rails_6_1.gemfile +8 -0
  18. data/gemfiles/rails_6_rc1.gemfile +8 -0
  19. data/lib/acts_as_votable.rb +9 -9
  20. data/lib/acts_as_votable/cacheable.rb +174 -0
  21. data/lib/acts_as_votable/extenders/controller.rb +3 -4
  22. data/lib/acts_as_votable/extenders/votable.rb +17 -6
  23. data/lib/acts_as_votable/extenders/voter.rb +4 -6
  24. data/lib/acts_as_votable/helpers/words.rb +7 -10
  25. data/lib/acts_as_votable/version.rb +3 -1
  26. data/lib/acts_as_votable/votable.rb +74 -194
  27. data/lib/acts_as_votable/vote.rb +10 -12
  28. data/lib/acts_as_votable/voter.rb +55 -56
  29. data/lib/generators/acts_as_votable/migration/migration_generator.rb +25 -4
  30. data/lib/generators/acts_as_votable/migration/templates/active_record/{migration.rb → migration.erb} +1 -6
  31. data/spec/factories/votable.rb +6 -0
  32. data/spec/factories/votable_cache.rb +6 -0
  33. data/spec/factories/votable_cache_update_attributes.rb +6 -0
  34. data/spec/factories/votable_cache_update_columns.rb +6 -0
  35. data/spec/factories/votable_child_of_sti_not_votable.rb +6 -0
  36. data/spec/factories/votable_child_of_sti_votable.rb +6 -0
  37. data/spec/factories/votable_voter.rb +6 -0
  38. data/spec/factories/vote.rb +6 -0
  39. data/spec/factories/voter.rb +6 -0
  40. data/spec/generators/active_record_generator_spec.rb +13 -0
  41. data/spec/shared_example/votable_model.rb +542 -0
  42. data/spec/shared_example/voter_model.rb +280 -0
  43. data/spec/spec_helper.rb +28 -18
  44. data/spec/support/factory_bot.rb +9 -0
  45. data/spec/votable_spec.rb +10 -9
  46. data/spec/votable_voter_spec.rb +12 -12
  47. data/spec/voter_spec.rb +9 -10
  48. data/spec/words_spec.rb +9 -12
  49. metadata +116 -26
  50. data/.travis.yml +0 -25
  51. data/spec/shared_example/votable_model_spec.rb +0 -421
  52. data/spec/shared_example/voter_model_spec.rb +0 -279
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c2beddd83fe6f3062fdfb1599953b34d942f6ac8
4
- data.tar.gz: 8bfb3b0bb95722935fb3eb315da58c619f583921
2
+ SHA256:
3
+ metadata.gz: b1843c2e0892abc19c5ecc63dd48e38fe8d48e1cdb7affc3c90d67b0419725e1
4
+ data.tar.gz: b05a72a3a7310c362233e9d54301a695a03fb72c9fb6068b2fde8e58d1e238bb
5
5
  SHA512:
6
- metadata.gz: cbe9cba192df3d698531c14a10f8340b78642cd51288b582b064384ea48931345900c74a499598b541ca2662230d262be6acc0f26d2db9a3763539140ec08683
7
- data.tar.gz: 03948b37befab6d39cd621b63d6e32cb2404b4850f2d5b2e2bece1674bcbaa13bcc4aff7e023f30aeff3330c809fdf9eb28b7d28d5ae6d6685c287c5167a90c1
6
+ metadata.gz: a125832f11dd75fa540f90791b5bdc092b92ade7c2a34218947fa1621aae21487eb38d8664636d1113885bb878927805a10f0db5edb786c48a8339832859bd68
7
+ data.tar.gz: 23bb31cc323d1173f982b2d12895b834e26b1ede7a6293cc1343538140f2fe3f7f9c0c89daf4de4ea67d72a69b4b4bbca2c4ec53555500ec965f26ca8fb1f475
@@ -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/.gitignore CHANGED
@@ -1,6 +1,10 @@
1
- pkg/*
2
- *.gem
3
- .bundle
4
- nbproject/*
5
- Gemfile.lock
6
- bin
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /gemfiles/*.gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
@@ -0,0 +1,121 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.2
3
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
4
+ # to ignore them, so only the ones explicitly set in this file are enabled.
5
+ DisabledByDefault: true
6
+
7
+ # Prefer &&/|| over and/or.
8
+ Style/AndOr:
9
+ Enabled: true
10
+
11
+ # Do not use braces for hash literals when they are the last argument of a
12
+ # method call.
13
+ Style/BracesAroundHashParameters:
14
+ Enabled: true
15
+ EnforcedStyle: context_dependent
16
+
17
+ # Align `when` with `case`.
18
+ Layout/CaseIndentation:
19
+ Enabled: true
20
+
21
+ # Align comments with method definitions.
22
+ Layout/CommentIndentation:
23
+ Enabled: true
24
+
25
+ Layout/EmptyLineAfterMagicComment:
26
+ Enabled: true
27
+
28
+ # In a regular class definition, no empty lines around the body.
29
+ Layout/EmptyLinesAroundClassBody:
30
+ Enabled: true
31
+
32
+ # In a regular method definition, no empty lines around the body.
33
+ Layout/EmptyLinesAroundMethodBody:
34
+ Enabled: true
35
+
36
+ # In a regular module definition, no empty lines around the body.
37
+ Layout/EmptyLinesAroundModuleBody:
38
+ Enabled: true
39
+
40
+ Layout/FirstParameterIndentation:
41
+ Enabled: true
42
+
43
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
44
+ Style/HashSyntax:
45
+ Enabled: true
46
+
47
+ # Two spaces, no tabs (for indentation).
48
+ Layout/IndentationWidth:
49
+ Enabled: true
50
+
51
+ Layout/SpaceAfterColon:
52
+ Enabled: true
53
+
54
+ Layout/SpaceAfterComma:
55
+ Enabled: true
56
+
57
+ Layout/SpaceAroundEqualsInParameterDefault:
58
+ Enabled: true
59
+
60
+ Layout/SpaceAroundKeyword:
61
+ Enabled: true
62
+
63
+ Layout/SpaceAroundOperators:
64
+ Enabled: true
65
+
66
+ Layout/SpaceBeforeFirstArg:
67
+ Enabled: true
68
+
69
+ # Defining a method with parameters needs parentheses.
70
+ Style/MethodDefParentheses:
71
+ Enabled: true
72
+
73
+ Style/FrozenStringLiteralComment:
74
+ Enabled: true
75
+ EnforcedStyle: always
76
+
77
+ # Use `foo {}` not `foo{}`.
78
+ Layout/SpaceBeforeBlockBraces:
79
+ Enabled: true
80
+
81
+ # Use `foo { bar }` not `foo {bar}`.
82
+ Layout/SpaceInsideBlockBraces:
83
+ Enabled: true
84
+
85
+ # Use `{ a: 1 }` not `{a:1}`.
86
+ Layout/SpaceInsideHashLiteralBraces:
87
+ Enabled: true
88
+
89
+ Layout/SpaceInsideParens:
90
+ Enabled: true
91
+
92
+ # Check quotes usage according to lint rule below.
93
+ Style/StringLiterals:
94
+ Enabled: true
95
+ EnforcedStyle: double_quotes
96
+
97
+ # Detect hard tabs, no hard tabs.
98
+ Layout/Tab:
99
+ Enabled: true
100
+
101
+ # Blank lines should not have any spaces.
102
+ Layout/TrailingBlankLines:
103
+ Enabled: true
104
+
105
+ # No trailing whitespace.
106
+ Layout/TrailingWhitespace:
107
+ Enabled: true
108
+
109
+ # Use quotes for string literals when they are enough.
110
+ Style/UnneededPercentQ:
111
+ Enabled: true
112
+
113
+ # Align `end` with the matching keyword or starting expression except for
114
+ # assignments, where it should be aligned with the LHS.
115
+ Lint/EndAlignment:
116
+ Enabled: true
117
+ EnforcedStyleAlignWith: variable
118
+
119
+ # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
120
+ Lint/RequireParentheses:
121
+ Enabled: true
@@ -0,0 +1 @@
1
+ 2.5.3
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise "rails-4" do
4
+ gem "rails", "4.2.11"
5
+ end
6
+
7
+ appraise "rails-5-1" do
8
+ gem "rails", "5.1.7"
9
+ end
10
+
11
+ appraise "rails-5-2" do
12
+ gem "rails", "5.2.4"
13
+ end
14
+
15
+ appraise "rails-6" do
16
+ gem "rails", "6.0.3"
17
+ gem "sqlite3", "~> 1.4"
18
+ end
19
+
20
+ appraise "rails-6-1" do
21
+ gem "rails", "6.1.0"
22
+ gem "sqlite3", "~> 1.4"
23
+ end
data/Gemfile CHANGED
@@ -1,17 +1,6 @@
1
- source 'https://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
2
4
 
3
5
  # Specify your gem's dependencies in acts_as_votable.gemspec
4
6
  gemspec
5
-
6
- rails_version = ENV['RAILS_VERSION'] || 'default'
7
-
8
- rails = case rails_version
9
- when 'master'
10
- { :github => 'rails/rails'}
11
- when 'default'
12
- '~> 3.2.0'
13
- else
14
- "~> #{rails_version}"
15
- end
16
-
17
- gem 'rails', rails
@@ -1,6 +1,6 @@
1
1
  # Acts As Votable (aka Acts As Likeable)
2
2
 
3
- [![Build Status](https://travis-ci.org/ryanto/acts_as_votable.png)](https://travis-ci.org/ryanto/acts_as_votable)
3
+ ![Build status](https://github.com/ryanto/acts_as_votable/workflows/CI/badge.svg)
4
4
 
5
5
  Acts As Votable is a Ruby Gem specifically written for Rails/ActiveRecord models.
6
6
  The main goals of this gem are:
@@ -15,17 +15,15 @@ The main goals of this gem are:
15
15
 
16
16
  ### Supported Ruby and Rails versions
17
17
 
18
- * Ruby 1.8.7, 1.9.2, 1.9.3
19
- * Ruby 2.0.0, 2.1.0
20
- * Rails 3.0, 3.1, 3.2
21
- * Rails 4.0, 4.1+
18
+ * Ruby >= 2.3.0
19
+ * Rails >= 4
22
20
 
23
21
  ### Install
24
22
 
25
- Just add the following to your Gemfile.
23
+ Just add the following to your Gemfile to install the latest release.
26
24
 
27
25
  ```ruby
28
- gem 'acts_as_votable', '~> 0.10.0'
26
+ gem 'acts_as_votable'
29
27
  ```
30
28
 
31
29
  And follow that up with a ``bundle install``.
@@ -36,7 +34,7 @@ Acts As Votable uses a votes table to store all voting information. To
36
34
  generate and run the migration just use.
37
35
 
38
36
  rails generate acts_as_votable:migration
39
- rake db:migrate
37
+ rails db:migrate
40
38
 
41
39
  You will get a performance increase by adding in cached columns to your model's
42
40
  tables. You will have to do this manually through your own migrations. See the
@@ -47,7 +45,7 @@ caching section of this document for more information.
47
45
  ### Votable Models
48
46
 
49
47
  ```ruby
50
- class Post < ActiveRecord::Base
48
+ class Post < ApplicationRecord
51
49
  acts_as_votable
52
50
  end
53
51
 
@@ -96,10 +94,12 @@ Revisiting the previous example of code.
96
94
 
97
95
  # tally them up!
98
96
  @post.votes_for.size # => 5
97
+ @post.weighted_total => 5
99
98
  @post.get_likes.size # => 3
100
99
  @post.get_upvotes.size # => 3
101
100
  @post.get_dislikes.size # => 2
102
101
  @post.get_downvotes.size # => 2
102
+ @post.weighted_score => 1
103
103
  ```
104
104
 
105
105
  Active Record scopes are provided to make life easier.
@@ -109,7 +109,7 @@ Active Record scopes are provided to make life easier.
109
109
  @post.votes_for.down
110
110
  @user1.votes.up
111
111
  @user1.votes.down
112
- @user1.votes.up.by_type(Post)
112
+ @user1.votes.up.for_type(Post)
113
113
  ```
114
114
 
115
115
  Once scoping is complete, you can also trigger a get for the
@@ -137,7 +137,7 @@ Unvoting works for both positive and negative votes.
137
137
 
138
138
  ### Examples with scopes
139
139
 
140
- You can add an scope to your vote
140
+ You can add a scope to your vote
141
141
 
142
142
  ```ruby
143
143
  # positive votes
@@ -192,15 +192,15 @@ You can add weight to your vote. The default value is 1.
192
192
  You can have your voters `acts_as_voter` to provide some reserve functionality.
193
193
 
194
194
  ```ruby
195
- class User < ActiveRecord::Base
195
+ class User < ApplicationRecord
196
196
  acts_as_voter
197
197
  end
198
198
 
199
199
  @user.likes @article
200
200
 
201
- @article.votes.size # => 1
202
- @article.likes.size # => 1
203
- @article.dislikes.size # => 0
201
+ @article.votes_for.size # => 1
202
+ @article.get_likes.size # => 1
203
+ @article.get_dislikes.size # => 0
204
204
  ```
205
205
 
206
206
  To check if a voter has voted on a model, you can use ``voted_for?``. You can
@@ -215,9 +215,9 @@ check how the voter voted by using ``voted_as_when_voted_for``.
215
215
  @user.voted_for? @comment2 # => true
216
216
  @user.voted_for? @comment3 # => false
217
217
 
218
- @user.voted_as_when_voted_for @comment1 # => true, he liked it
219
- @user.voted_as_when_voted_for @comment2 # => false, he didnt like it
220
- @user.voted_as_when_voted_for @comment3 # => nil, he has yet to vote
218
+ @user.voted_as_when_voted_for @comment1 # => true, user liked it
219
+ @user.voted_as_when_voted_for @comment2 # => false, user didnt like it
220
+ @user.voted_as_when_voted_for @comment3 # => nil, user has yet to vote
221
221
  ```
222
222
 
223
223
  You can also check whether the voter has voted up or down.
@@ -273,8 +273,8 @@ because `@user` has already voted for `@shoe`.
273
273
  @user.likes @shoe
274
274
  @user.likes @shoe
275
275
 
276
- @shoe.votes # => 1
277
- @shoe.likes # => 1
276
+ @shoe.votes_for.size # => 1
277
+ @shoe.get_likes.size # => 1
278
278
  ```
279
279
 
280
280
  To check if a vote counted, or registered, use `vote_registered?` on your model
@@ -290,9 +290,9 @@ after voting. For example:
290
290
  @hat.disliked_by @user
291
291
  @hat.vote_registered? # => true, because user changed their vote
292
292
 
293
- @hat.votes.size # => 1
294
- @hat.positives.size # => 0
295
- @hat.negatives.size # => 1
293
+ @hat.votes_for.size # => 1
294
+ @hat.get_positives.size # => 0
295
+ @hat.get_negatives.size # => 1
296
296
  ```
297
297
 
298
298
  To permit duplicates entries of a same voter, use option duplicate. Also notice that this
@@ -310,35 +310,71 @@ to speed up @post we would use the following migration:
310
310
 
311
311
  ```ruby
312
312
  class AddCachedVotesToPosts < ActiveRecord::Migration
313
- def self.up
314
- add_column :posts, :cached_votes_total, :integer, :default => 0
315
- add_column :posts, :cached_votes_score, :integer, :default => 0
316
- add_column :posts, :cached_votes_up, :integer, :default => 0
317
- add_column :posts, :cached_votes_down, :integer, :default => 0
318
- add_column :posts, :cached_weighted_score, :integer, :default => 0
319
- add_column :posts, :cached_weighted_total, :integer, :default => 0
320
- add_index :posts, :cached_votes_total
321
- add_index :posts, :cached_votes_score
322
- add_index :posts, :cached_votes_up
323
- add_index :posts, :cached_votes_down
324
- add_index :posts, :cached_weighted_score
325
- add_index :posts, :cached_weighted_total
313
+ def change
314
+ change_table :posts do |t|
315
+ t.integer :cached_votes_total, default: 0
316
+ t.integer :cached_votes_score, default: 0
317
+ t.integer :cached_votes_up, default: 0
318
+ t.integer :cached_votes_down, default: 0
319
+ t.integer :cached_weighted_score, default: 0
320
+ t.integer :cached_weighted_total, default: 0
321
+ t.float :cached_weighted_average, default: 0.0
322
+ end
326
323
 
327
324
  # Uncomment this line to force caching of existing votes
328
325
  # Post.find_each(&:update_cached_votes)
329
326
  end
327
+ end
328
+ ```
329
+
330
+ If you have a scope for your vote, let's say `subscribe`, your migration will be slightly different like below:
330
331
 
331
- def self.down
332
- remove_column :posts, :cached_votes_total
333
- remove_column :posts, :cached_votes_score
334
- remove_column :posts, :cached_votes_up
335
- remove_column :posts, :cached_votes_down
336
- remove_column :posts, :cached_weighted_score
337
- remove_column :posts, :cached_weighted_total
332
+ ```ruby
333
+ class AddCachedVotesToPosts < ActiveRecord::Migration
334
+ def change
335
+ change_table :posts do |t|
336
+ t.integer :cached_scoped_subscribe_votes_total, default: 0
337
+ t.integer :cached_scoped_subscribe_votes_score, default: 0
338
+ t.integer :cached_scoped_subscribe_votes_up, default: 0
339
+ t.integer :cached_scoped_subscribe_votes_down, default: 0
340
+ t.integer :cached_weighted_subscribe_score, default: 0
341
+ t.integer :cached_weighted_subscribe_total, default: 0
342
+ t.float :cached_weighted_subscribe_average, default: 0.0
343
+ end
338
344
  end
339
345
  end
340
346
  ```
341
347
 
348
+ `cached_weighted_average` can be helpful for a rating system, e.g.:
349
+
350
+ Order by average rating:
351
+
352
+ ```ruby
353
+ Post.order(:cached_weighted_average => :desc)
354
+ ```
355
+
356
+ Display average rating:
357
+
358
+ ```erb
359
+ <%= post.weighted_average.round(2) %> / 5
360
+ <!-- 3.5 / 5 -->
361
+ ```
362
+ ## updated_at at Votable model
363
+
364
+ You can control whether `updated_at` column of votable model will be touched or
365
+ not by passing `cacheable_strategy` option to `acts_as_votable` method.
366
+
367
+ By default, `update` strategy is used. Pass `:update_columns` as
368
+ `cacheable_strategy` if you don't want to touch model's `updated_at` column.
369
+ ```ruby
370
+ class Post < ApplicationRecord
371
+ acts_as_votable cacheable_strategy: :update_columns
372
+ end
373
+ ```
374
+
375
+ NOTE: this option does not work for ActiveRecord < 3.1
376
+
377
+
342
378
  ## Testing
343
379
 
344
380
  All tests follow the RSpec format and are located in the spec directory.
@@ -348,20 +384,20 @@ They can be run with:
348
384
  rake spec
349
385
  ```
350
386
 
351
- ## Changes
387
+ ## Changes
352
388
 
353
- ### Fixes for votable voter model
389
+ ### Fixes for votable voter model
354
390
 
355
- In version 0.8.0, there is bugs for a model that is both votable and voter.
391
+ In version 0.8.0, there are bugs for a model that is both votable and voter.
356
392
  Some name-conflicting methods are renamed:
357
- + Renamed Votable.votes to votes_for
393
+ + Renamed Votable.votes to votes_for
358
394
  + Renamed Votable.vote to vote_by,
359
395
  + Removed Votable.vote_by alias (was an alias for :vote_up)
360
396
  + Renamed Votable.unvote_for to unvote_by
361
397
  + Renamed Votable.find_votes to find_votes_for
362
- + Renamed Votable.up_votes to get_upvotes
398
+ + Renamed Votable.up_votes to get_upvotes
363
399
  + and its aliases :get_true_votes, :get_ups, :get_upvotes, :get_likes, :get_positives, :get_for_votes
364
- + Renamed Votable.down_votes to get_downvotes
400
+ + Renamed Votable.down_votes to get_downvotes
365
401
  + and its aliases :get_false_votes, :get_downs, :get_downvotes, :get_dislikes, :get_negatives
366
402
 
367
403
 
@@ -370,7 +406,7 @@ Some name-conflicting methods are renamed:
370
406
  Acts as votable is released under the [MIT
371
407
  License](http://www.opensource.org/licenses/MIT).
372
408
 
373
- ## TODO
409
+ ## Next steps
374
410
 
375
411
  - Pass in a block of options when creating acts_as. Allow for things
376
412
  like disabling the aliasing
@@ -379,8 +415,7 @@ License](http://www.opensource.org/licenses/MIT).
379
415
  that the user likes, while `@user.likes @model` will cast a vote for @model by
380
416
  @user.
381
417
 
382
-
383
418
  - The aliased methods are referred to by using the terms 'up/down' and/or
384
- 'true/false'. Need to come up with guidelines for naming these methods.
419
+ 'true/false'. Need to come up with guidelines for naming these methods.
385
420
 
386
421
  - Create more aliases. Specifically for counting votes and finding votes.