acts_as_votable 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -6
  3. data/.rubocop.yml +121 -0
  4. data/.travis.yml +12 -23
  5. data/Appraisals +13 -0
  6. data/Gemfile +3 -14
  7. data/README.markdown +80 -13
  8. data/Rakefile +6 -4
  9. data/acts_as_votable.gemspec +12 -5
  10. data/gemfiles/.bundle/config +2 -0
  11. data/gemfiles/rails_4.gemfile +7 -0
  12. data/gemfiles/rails_4.gemfile.lock +159 -0
  13. data/gemfiles/rails_5.gemfile +7 -0
  14. data/gemfiles/rails_5.gemfile.lock +166 -0
  15. data/gemfiles/rails_5_1.gemfile +7 -0
  16. data/gemfiles/rails_5_1.gemfile.lock +166 -0
  17. data/lib/acts_as_votable.rb +9 -9
  18. data/lib/acts_as_votable/cacheable.rb +174 -0
  19. data/lib/acts_as_votable/extenders/controller.rb +3 -4
  20. data/lib/acts_as_votable/extenders/votable.rb +17 -6
  21. data/lib/acts_as_votable/extenders/voter.rb +4 -6
  22. data/lib/acts_as_votable/helpers/words.rb +7 -10
  23. data/lib/acts_as_votable/version.rb +3 -1
  24. data/lib/acts_as_votable/votable.rb +50 -187
  25. data/lib/acts_as_votable/vote.rb +10 -12
  26. data/lib/acts_as_votable/voter.rb +52 -53
  27. data/lib/generators/acts_as_votable/migration/migration_generator.rb +19 -4
  28. data/lib/generators/acts_as_votable/migration/templates/active_record/{migration.rb → migration.erb} +1 -6
  29. data/spec/factories/votable.rb +6 -0
  30. data/spec/factories/votable_cache.rb +6 -0
  31. data/spec/factories/votable_cache_update_attributes.rb +6 -0
  32. data/spec/factories/votable_cache_update_columns.rb +6 -0
  33. data/spec/factories/votable_child_of_sti_not_votable.rb +6 -0
  34. data/spec/factories/votable_child_of_sti_votable.rb +6 -0
  35. data/spec/factories/votable_voter.rb +6 -0
  36. data/spec/factories/vote.rb +6 -0
  37. data/spec/factories/voter.rb +6 -0
  38. data/spec/generators/active_record_generator_spec.rb +13 -0
  39. data/spec/shared_example/votable_model.rb +506 -0
  40. data/spec/shared_example/voter_model.rb +280 -0
  41. data/spec/spec_helper.rb +28 -18
  42. data/spec/support/factory_girl.rb +10 -0
  43. data/spec/votable_spec.rb +10 -9
  44. data/spec/votable_voter_spec.rb +12 -12
  45. data/spec/voter_spec.rb +9 -10
  46. data/spec/words_spec.rb +9 -12
  47. metadata +98 -27
  48. data/spec/shared_example/votable_model_spec.rb +0 -421
  49. data/spec/shared_example/voter_model_spec.rb +0 -279
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c2beddd83fe6f3062fdfb1599953b34d942f6ac8
4
- data.tar.gz: 8bfb3b0bb95722935fb3eb315da58c619f583921
3
+ metadata.gz: ec62f24bb2a85474f561c476a47007e333dae16f
4
+ data.tar.gz: ab88ccd51c8d63225b05b7f6443056cd0defe2a5
5
5
  SHA512:
6
- metadata.gz: cbe9cba192df3d698531c14a10f8340b78642cd51288b582b064384ea48931345900c74a499598b541ca2662230d262be6acc0f26d2db9a3763539140ec08683
7
- data.tar.gz: 03948b37befab6d39cd621b63d6e32cb2404b4850f2d5b2e2bece1674bcbaa13bcc4aff7e023f30aeff3330c809fdf9eb28b7d28d5ae6d6685c287c5167a90c1
6
+ metadata.gz: be0133a6030a9c0d83a6753b82360c100ed998a608f98829fd97bc4cbbf27f61990fb1bbc9eac9b9b46b0d4d7e122556e3fce47eb59eb7bf5d42a71a1f895512
7
+ data.tar.gz: ec1ee10e398a40bb5b20a568265334194e29ca8b05b75a8e8f8c87076e9d187f72225124704af321ffa3b615853906b51daf96a4837074f97bdda4cbe27a28a2
data/.gitignore CHANGED
@@ -1,6 +1,9 @@
1
- pkg/*
2
- *.gem
3
- .bundle
4
- nbproject/*
5
- Gemfile.lock
6
- bin
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /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
@@ -1,25 +1,14 @@
1
1
  language: ruby
2
+
3
+ cache: bundler
4
+
2
5
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
- - 1.9.3
6
- - 2.0.0
7
- - 2.1.0
8
- env:
9
- - "RAILS_VERSION=3.0.0"
10
- - "RAILS_VERSION=3.1.0"
11
- - "RAILS_VERSION=3.2.0"
12
- - "RAILS_VERSION=4.0.0"
13
- - "RAILS_VERSION=4.1.0"
14
- matrix:
15
- exclude:
16
- - rvm: 1.8.7
17
- env: "RAILS_VERSION=4.0.0"
18
- - rvm: 1.9.2
19
- env: "RAILS_VERSION=4.0.0"
20
- - rvm: 1.8.7
21
- env: "RAILS_VERSION=4.1.0"
22
- - rvm: 1.9.2
23
- env: "RAILS_VERSION=4.1.0"
24
- - rvm: 1.9.3
25
- env: "RAILS_VERSION=4.1.0"
6
+ - 2.2.7
7
+ - 2.3.4
8
+ - 2.4.1
9
+
10
+ gemfile:
11
+ - gemfiles/rails_4.gemfile
12
+ - gemfiles/rails_5.gemfile
13
+ - gemfiles/rails_5_1.gemfile
14
+
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise "rails-4" do
4
+ gem "rails", "4.2.9"
5
+ end
6
+
7
+ appraise "rails-5" do
8
+ gem "rails", "5.0.5"
9
+ end
10
+
11
+ appraise "rails-5-1" do
12
+ gem "rails", "5.1.4"
13
+ 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,7 @@
1
1
  # Acts As Votable (aka Acts As Likeable)
2
2
 
3
3
  [![Build Status](https://travis-ci.org/ryanto/acts_as_votable.png)](https://travis-ci.org/ryanto/acts_as_votable)
4
+ [![Code Climate](https://codeclimate.com/github/ryanto/acts_as_votable.png)](https://codeclimate.com/github/ryanto/acts_as_votable)
4
5
 
5
6
  Acts As Votable is a Ruby Gem specifically written for Rails/ActiveRecord models.
6
7
  The main goals of this gem are:
@@ -15,14 +16,13 @@ The main goals of this gem are:
15
16
 
16
17
  ### Supported Ruby and Rails versions
17
18
 
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
19
+ * Ruby 2.2.0, 2.3.0 and 2.4.0
21
20
  * Rails 4.0, 4.1+
21
+ * Rails 5.0, 5.1
22
22
 
23
23
  ### Install
24
24
 
25
- Just add the following to your Gemfile.
25
+ Just add the following to your Gemfile to install the latest release.
26
26
 
27
27
  ```ruby
28
28
  gem 'acts_as_votable', '~> 0.10.0'
@@ -96,10 +96,12 @@ Revisiting the previous example of code.
96
96
 
97
97
  # tally them up!
98
98
  @post.votes_for.size # => 5
99
+ @post.weighted_total => 5
99
100
  @post.get_likes.size # => 3
100
101
  @post.get_upvotes.size # => 3
101
102
  @post.get_dislikes.size # => 2
102
103
  @post.get_downvotes.size # => 2
104
+ @post.weighted_score => 1
103
105
  ```
104
106
 
105
107
  Active Record scopes are provided to make life easier.
@@ -109,7 +111,7 @@ Active Record scopes are provided to make life easier.
109
111
  @post.votes_for.down
110
112
  @user1.votes.up
111
113
  @user1.votes.down
112
- @user1.votes.up.by_type(Post)
114
+ @user1.votes.up.for_type(Post)
113
115
  ```
114
116
 
115
117
  Once scoping is complete, you can also trigger a get for the
@@ -137,7 +139,7 @@ Unvoting works for both positive and negative votes.
137
139
 
138
140
  ### Examples with scopes
139
141
 
140
- You can add an scope to your vote
142
+ You can add a scope to your vote
141
143
 
142
144
  ```ruby
143
145
  # positive votes
@@ -215,9 +217,9 @@ check how the voter voted by using ``voted_as_when_voted_for``.
215
217
  @user.voted_for? @comment2 # => true
216
218
  @user.voted_for? @comment3 # => false
217
219
 
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
220
+ @user.voted_as_when_voted_for @comment1 # => true, user liked it
221
+ @user.voted_as_when_voted_for @comment2 # => false, user didnt like it
222
+ @user.voted_as_when_voted_for @comment3 # => nil, user has yet to vote
221
223
  ```
222
224
 
223
225
  You can also check whether the voter has voted up or down.
@@ -317,12 +319,14 @@ class AddCachedVotesToPosts < ActiveRecord::Migration
317
319
  add_column :posts, :cached_votes_down, :integer, :default => 0
318
320
  add_column :posts, :cached_weighted_score, :integer, :default => 0
319
321
  add_column :posts, :cached_weighted_total, :integer, :default => 0
322
+ add_column :posts, :cached_weighted_average, :float, :default => 0.0
320
323
  add_index :posts, :cached_votes_total
321
324
  add_index :posts, :cached_votes_score
322
325
  add_index :posts, :cached_votes_up
323
326
  add_index :posts, :cached_votes_down
324
327
  add_index :posts, :cached_weighted_score
325
328
  add_index :posts, :cached_weighted_total
329
+ add_index :posts, :cached_weighted_average
326
330
 
327
331
  # Uncomment this line to force caching of existing votes
328
332
  # Post.find_each(&:update_cached_votes)
@@ -335,10 +339,74 @@ class AddCachedVotesToPosts < ActiveRecord::Migration
335
339
  remove_column :posts, :cached_votes_down
336
340
  remove_column :posts, :cached_weighted_score
337
341
  remove_column :posts, :cached_weighted_total
342
+ remove_column :posts, :cached_weighted_average
338
343
  end
339
344
  end
340
345
  ```
341
346
 
347
+ If you have a scope for your vote, let's say `subscribe`, your migration will be slightly different like below:
348
+
349
+ ```ruby
350
+ class AddCachedVotesToPosts < ActiveRecord::Migration
351
+ def self.up
352
+ add_column :posts, :cached_scoped_subscribe_votes_total, :integer, :default => 0
353
+ add_column :posts, :cached_scoped_subscribe_votes_score, :integer, :default => 0
354
+ add_column :posts, :cached_scoped_subscribe_votes_up, :integer, :default => 0
355
+ add_column :posts, :cached_scoped_subscribe_votes_down, :integer, :default => 0
356
+ add_column :posts, :cached_weighted_subscribe_score, :integer, :default => 0
357
+ add_column :posts, :cached_weighted_subscribe_total, :integer, :default => 0
358
+ add_column :posts, :cached_weighted_subscribe_average, :float, :default => 0.0
359
+ add_index :posts, :cached_scoped_subscribe_votes_total
360
+ add_index :posts, :cached_scoped_subscribe_votes_score
361
+ add_index :posts, :cached_scoped_subscribe_votes_up
362
+ add_index :posts, :cached_scoped_subscribe_votes_down
363
+ add_index :posts, :cached_weighted_subscribe_score
364
+ add_index :posts, :cached_weighted_subscribe_total
365
+ add_index :posts, :cached_weighted_subscribe_average
366
+ end
367
+
368
+ def self.down
369
+ remove_column :posts, :cached_scoped_subscribe_votes_total
370
+ remove_column :posts, :cached_scoped_subscribe_votes_score
371
+ remove_column :posts, :cached_scoped_subscribe_votes_up
372
+ remove_column :posts, :cached_scoped_subscribe_votes_down
373
+ remove_column :posts, :cached_weighted_subscribe_score
374
+ remove_column :posts, :cached_weighted_subscribe_total
375
+ remove_column :posts, :cached_weighted_subscribe_average
376
+ end
377
+ end
378
+ ```
379
+
380
+ `cached_weighted_average` can be helpful for a rating system, e.g.:
381
+
382
+ Order by average rating:
383
+
384
+ ```ruby
385
+ Post.order(:cached_weighted_average => :desc)
386
+ ```
387
+
388
+ Display average rating:
389
+
390
+ ```erb
391
+ <%= post.weighted_average.round(2) %> / 5
392
+ <!-- 3.5 / 5 -->
393
+ ```
394
+ ## updated_at at Votable model
395
+
396
+ You can control whether `updated_at` column of votable model will be touched or
397
+ not by passing `cacheable_strategy` option to `acts_as_votable` method.
398
+
399
+ By default, `update_attributes` strategy is used. Pass `:update_columns` as
400
+ `cacheable_strategy` if you don't want to touch model's `updated_at` column.
401
+ ```ruby
402
+ class Post < ActiveRecord::Base
403
+ acts_as_votable cacheable_strategy: :update_columns
404
+ end
405
+ ```
406
+
407
+ NOTE: this option does not work for ActiveRecord < 3.1
408
+
409
+
342
410
  ## Testing
343
411
 
344
412
  All tests follow the RSpec format and are located in the spec directory.
@@ -352,7 +420,7 @@ rake spec
352
420
 
353
421
  ### Fixes for votable voter model
354
422
 
355
- In version 0.8.0, there is bugs for a model that is both votable and voter.
423
+ In version 0.8.0, there are bugs for a model that is both votable and voter.
356
424
  Some name-conflicting methods are renamed:
357
425
  + Renamed Votable.votes to votes_for
358
426
  + Renamed Votable.vote to vote_by,
@@ -370,7 +438,7 @@ Some name-conflicting methods are renamed:
370
438
  Acts as votable is released under the [MIT
371
439
  License](http://www.opensource.org/licenses/MIT).
372
440
 
373
- ## TODO
441
+ ## Next steps
374
442
 
375
443
  - Pass in a block of options when creating acts_as. Allow for things
376
444
  like disabling the aliasing
@@ -379,8 +447,7 @@ License](http://www.opensource.org/licenses/MIT).
379
447
  that the user likes, while `@user.likes @model` will cast a vote for @model by
380
448
  @user.
381
449
 
382
-
383
450
  - 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.
451
+ 'true/false'. Need to come up with guidelines for naming these methods.
385
452
 
386
453
  - Create more aliases. Specifically for counting votes and finding votes.
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require 'bundler'
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler"
2
4
  Bundler::GemHelper.install_tasks
3
5
 
4
- require 'rspec/core/rake_task'
6
+ require "rspec/core/rake_task"
5
7
 
6
8
  desc "Run specs"
7
9
  RSpec::Core::RakeTask.new(:spec)
8
10
 
9
- desc 'Default: run specs.'
10
- task :default => :spec
11
+ desc "Default: run specs."
12
+ task default: :spec
@@ -1,4 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  $:.push File.expand_path("../lib", __FILE__)
3
5
  require "acts_as_votable/version"
4
6
 
@@ -9,16 +11,21 @@ Gem::Specification.new do |s|
9
11
  s.authors = ["Ryan"]
10
12
  s.email = ["ryanto"]
11
13
  s.homepage = "http://rubygems.org/gems/acts_as_votable"
12
- s.summary = %q{Rails gem to allowing records to be votable}
13
- s.description = %q{Rails gem to allowing records to be votable}
14
+ s.summary = "Rails gem to allowing records to be votable"
15
+ s.description = "Rails gem to allowing records to be votable"
16
+ s.license = "MIT"
14
17
 
15
18
  s.rubyforge_project = "acts_as_votable"
16
19
 
17
20
  s.files = `git ls-files`.split("\n")
18
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
20
23
  s.require_paths = ["lib"]
21
24
 
22
- s.add_development_dependency "rspec"
23
- s.add_development_dependency "sqlite3", '1.3.7'
25
+ s.add_development_dependency "rspec", "~> 3.6"
26
+ s.add_development_dependency "sqlite3", "~> 1.3"
27
+ s.add_development_dependency "rubocop", "~> 0.49.1"
28
+ s.add_development_dependency "simplecov", "~> 0.15.0"
29
+ s.add_development_dependency "appraisal", "~> 2.2"
30
+ s.add_development_dependency "factory_girl", "~> 4.8"
24
31
  end