acts_as_votable 0.10.0 → 0.13.0

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.
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
@@ -0,0 +1,280 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples "a voter_model" do
4
+ let (:votable_klass) { votable.class }
5
+
6
+ it "should be voted on after a voter has voted" do
7
+ votable.vote_by voter: voter
8
+ expect(voter.voted_on?(votable)).to be true
9
+ expect(voter.voted_for?(votable)).to be true
10
+ end
11
+
12
+ it "should not be voted on if a voter has not voted" do
13
+ expect(voter.voted_on?(votable)).to be false
14
+ end
15
+
16
+ it "should be voted on after a voter has voted under scope" do
17
+ votable.vote_by voter: voter, vote_scope: "rank"
18
+ expect(voter.voted_on?(votable, vote_scope: "rank")).to be true
19
+ end
20
+
21
+ it "should not be voted on other scope after a voter has voted under one scope" do
22
+ votable.vote_by voter: voter, vote_scope: "rank"
23
+ expect(voter.voted_on?(votable)).to be false
24
+ end
25
+
26
+ it "should be voted as true when a voter has voted true" do
27
+ votable.vote_by voter: voter
28
+ expect(voter.voted_as_when_voted_on(votable)).to be true
29
+ expect(voter.voted_as_when_voted_for(votable)).to be true
30
+ end
31
+
32
+ it "should be voted as true when a voter has voted true under scope" do
33
+ votable.vote_by voter: voter, vote_scope: "rank"
34
+ expect(voter.voted_as_when_voted_for(votable, vote_scope: "rank")).to be true
35
+ end
36
+
37
+ it "should be voted as false when a voter has voted false" do
38
+ votable.vote_by voter: voter, vote: false
39
+ expect(voter.voted_as_when_voted_for(votable)).to be false
40
+ end
41
+
42
+ it "should be voted as false when a voter has voted false under scope" do
43
+ votable.vote_by voter: voter, vote: false, vote_scope: "rank"
44
+ expect(voter.voted_as_when_voted_for(votable, vote_scope: "rank")).to be false
45
+ end
46
+
47
+ it "should be voted as nil when a voter has never voted" do
48
+ expect(voter.voted_as_when_voting_on(votable)).to be nil
49
+ end
50
+
51
+ it "should be voted as nil when a voter has never voted under the scope" do
52
+ votable.vote_by voter: voter, vote: false, vote_scope: "rank"
53
+ expect(voter.voted_as_when_voting_on(votable)).to be nil
54
+ end
55
+
56
+ it "should return true if voter has voted true" do
57
+ votable.vote_by voter: voter
58
+ expect(voter.voted_up_on?(votable)).to be true
59
+ end
60
+
61
+ it "should return false if voter has not voted true" do
62
+ votable.vote_by voter: voter, vote: false
63
+ expect(voter.voted_up_on?(votable)).to be false
64
+ end
65
+
66
+ it "should return true if the voter has voted false" do
67
+ votable.vote_by voter: voter, vote: false
68
+ expect(voter.voted_down_on?(votable)).to be true
69
+ end
70
+
71
+ it "should return false if the voter has not voted false" do
72
+ votable.vote_by voter: voter, vote: true
73
+ expect(voter.voted_down_on?(votable)).to be false
74
+ end
75
+
76
+ it "should provide reserve functionality, voter can vote on votable" do
77
+ voter.vote votable: votable, vote: "bad"
78
+ expect(voter.voted_as_when_voting_on(votable)).to be false
79
+ end
80
+
81
+ it "should allow the voter to vote up a model" do
82
+ voter.vote_up_for votable
83
+ expect(votable.get_up_votes.first.voter).to eq(voter)
84
+ expect(votable.votes_for.up.first.voter).to eq(voter)
85
+ end
86
+
87
+ it "should allow the voter to vote down a model" do
88
+ voter.vote_down_for votable
89
+ expect(votable.get_down_votes.first.voter).to eq(voter)
90
+ expect(votable.votes_for.down.first.voter).to eq(voter)
91
+ end
92
+
93
+ it "should allow the voter to unvote a model" do
94
+ voter.vote_up_for votable
95
+ voter.unvote_for votable
96
+ expect(votable.find_votes_for.size).to eq(0)
97
+ expect(votable.votes_for.count).to eq(0)
98
+ end
99
+
100
+ it "should get all of the voters votes" do
101
+ voter.vote_up_for votable
102
+ expect(voter.find_votes.size).to eq(1)
103
+ expect(voter.votes.up.count).to eq(1)
104
+ end
105
+
106
+ it "should get all of the voters up votes" do
107
+ voter.vote_up_for votable
108
+ expect(voter.find_up_votes.size).to eq(1)
109
+ expect(voter.votes.up.count).to eq(1)
110
+ end
111
+
112
+ it "should get all of the voters down votes" do
113
+ voter.vote_down_for votable
114
+ expect(voter.find_down_votes.size).to eq(1)
115
+ expect(voter.votes.down.count).to eq(1)
116
+ end
117
+
118
+ it "should get all of the votes votes for a class" do
119
+ votable.vote_by voter: voter
120
+ votable2.vote_by voter: voter, vote: false
121
+ expect(voter.find_votes_for_class(votable_klass).size).to eq(2)
122
+ expect(voter.votes.for_type(votable_klass).count).to eq(2)
123
+ end
124
+
125
+ it "should get all of the voters up votes for a class" do
126
+ votable.vote_by voter: voter
127
+ votable2.vote_by voter: voter, vote: false
128
+ expect(voter.find_up_votes_for_class(votable_klass).size).to eq(1)
129
+ expect(voter.votes.up.for_type(votable_klass).count).to eq(1)
130
+ end
131
+
132
+ it "should get all of the voters down votes for a class" do
133
+ votable.vote_by voter: voter
134
+ votable2.vote_by voter: voter, vote: false
135
+ expect(voter.find_down_votes_for_class(votable_klass).size).to eq(1)
136
+ expect(voter.votes.down.for_type(votable_klass).count).to eq(1)
137
+ end
138
+
139
+ it "should be contained to instances" do
140
+ voter.vote votable: votable, vote: false
141
+ voter2.vote votable: votable
142
+
143
+ expect(voter.voted_as_when_voting_on(votable)).to be false
144
+ end
145
+
146
+ describe "#find_voted_items" do
147
+ it "returns objects that a user has upvoted for" do
148
+ votable.vote_by voter: voter
149
+ votable2.vote_by voter: voter2
150
+ expect(voter.find_voted_items).to include votable
151
+ expect(voter.find_voted_items.size).to eq(1)
152
+ end
153
+
154
+ it "returns objects that a user has upvoted for, using scope" do
155
+ votable.vote_by voter: voter, vote_scope: "rank"
156
+ votable2.vote_by voter: voter2, vote_scope: "rank"
157
+ expect(voter.find_voted_items(vote_scope: "rank")).to include votable
158
+ expect(voter.find_voted_items(vote_scope: "rank").size).to eq(1)
159
+ end
160
+
161
+ it "returns objects that a user has downvoted for" do
162
+ votable.vote_down voter
163
+ votable2.vote_down voter2
164
+ expect(voter.find_voted_items).to include votable
165
+ expect(voter.find_voted_items.size).to eq(1)
166
+ end
167
+
168
+ it "returns objects that a user has downvoted for, using scope" do
169
+ votable.vote_down voter, vote_scope: "rank"
170
+ votable2.vote_down voter2, vote_scope: "rank"
171
+ expect(voter.find_voted_items(vote_scope: "rank")).to include votable
172
+ expect(voter.find_voted_items(vote_scope: "rank").size).to eq(1)
173
+ end
174
+ end
175
+
176
+ describe "#find_up_voted_items" do
177
+ it "returns objects that a user has upvoted for" do
178
+ votable.vote_by voter: voter
179
+ votable2.vote_by voter: voter2
180
+ expect(voter.find_up_voted_items).to include votable
181
+ expect(voter.find_up_voted_items.size).to eq(1)
182
+ expect(voter.find_liked_items).to include votable
183
+ expect(voter.find_liked_items.size).to eq(1)
184
+ end
185
+
186
+ it "returns objects that a user has upvoted for, using scope" do
187
+ votable.vote_by voter: voter, vote_scope: "rank"
188
+ votable2.vote_by voter: voter2, vote_scope: "rank"
189
+ expect(voter.find_up_voted_items(vote_scope: "rank")).to include votable
190
+ expect(voter.find_up_voted_items(vote_scope: "rank").size).to eq(1)
191
+ end
192
+
193
+ it "does not return objects that a user has downvoted for" do
194
+ votable.vote_down voter
195
+ expect(voter.find_up_voted_items.size).to eq(0)
196
+ end
197
+
198
+ it "does not return objects that a user has downvoted for, using scope" do
199
+ votable.vote_down voter, vote_scope: "rank"
200
+ expect(voter.find_up_voted_items(vote_scope: "rank").size).to eq(0)
201
+ end
202
+ end
203
+
204
+ describe "#find_down_voted_items" do
205
+ it "does not return objects that a user has upvoted for" do
206
+ votable.vote_by voter: voter
207
+ expect(voter.find_down_voted_items.size).to eq(0)
208
+ end
209
+
210
+ it "does not return objects that a user has upvoted for, using scope" do
211
+ votable.vote_by voter: voter, vote_scope: "rank"
212
+ expect(voter.find_down_voted_items(vote_scope: "rank").size).to eq(0)
213
+ end
214
+
215
+ it "returns objects that a user has downvoted for" do
216
+ votable.vote_down voter
217
+ votable2.vote_down voter2
218
+ expect(voter.find_down_voted_items).to include votable
219
+ expect(voter.find_down_voted_items.size).to eq(1)
220
+ expect(voter.find_disliked_items).to include votable
221
+ expect(voter.find_disliked_items.size).to eq(1)
222
+ end
223
+
224
+ it "returns objects that a user has downvoted for, using scope" do
225
+ votable.vote_down voter, vote_scope: "rank"
226
+ votable2.vote_down voter2, vote_scope: "rank"
227
+ expect(voter.find_down_voted_items(vote_scope: "rank")).to include votable
228
+ expect(voter.find_down_voted_items(vote_scope: "rank").size).to eq(1)
229
+ end
230
+
231
+ end
232
+
233
+ describe "#get_voted" do
234
+ subject { voter.get_voted(votable.class) }
235
+
236
+ it "returns objects of a class that a voter has voted for" do
237
+ votable.vote_by voter: voter
238
+ votable2.vote_down voter
239
+ expect(subject).to include votable
240
+ expect(subject).to include votable2
241
+ expect(subject.size).to eq(2)
242
+ end
243
+
244
+ it "does not return objects of a class that a voter has voted for" do
245
+ votable.vote_by voter: voter2
246
+ votable2.vote_by voter: voter2
247
+ expect(subject.size).to eq(0)
248
+ end
249
+ end
250
+
251
+ describe "#get_up_voted" do
252
+ subject { voter.get_up_voted(votable.class) }
253
+
254
+ it "returns up voted items that a voter has voted for" do
255
+ votable.vote_by voter: voter
256
+ expect(subject).to include votable
257
+ expect(subject.size).to eq(1)
258
+ end
259
+
260
+ it "does not return down voted items a voter has voted for" do
261
+ votable.vote_down voter
262
+ expect(subject.size).to eq(0)
263
+ end
264
+ end
265
+
266
+ describe "#get_down_voted" do
267
+ subject { voter.get_down_voted(votable.class) }
268
+
269
+ it "does not return up voted items that a voter has voted for" do
270
+ votable.vote_by voter: voter
271
+ expect(subject.size).to eq(0)
272
+ end
273
+
274
+ it "returns down voted items a voter has voted for" do
275
+ votable.vote_down voter
276
+ expect(subject).to include votable
277
+ expect(subject.size).to eq(1)
278
+ end
279
+ end
280
+ end
@@ -1,15 +1,22 @@
1
- $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
- require 'sqlite3'
3
- require 'acts_as_votable'
1
+ # frozen_string_literal: true
4
2
 
5
- Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
4
+ require "sqlite3"
5
+ require "simplecov"
6
+ require "acts_as_votable"
7
+ require "factory_bot"
6
8
 
7
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
+ Dir["./spec/shared_example/**/*.rb"].sort.each { |f| require f }
10
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
8
11
 
9
- ActiveRecord::Schema.define(:version => 1) do
12
+ SimpleCov.start
13
+
14
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
15
+
16
+ ActiveRecord::Schema.define(version: 1) do
10
17
  create_table :votes do |t|
11
- t.references :votable, :polymorphic => true
12
- t.references :voter, :polymorphic => true
18
+ t.references :votable, polymorphic: true
19
+ t.references :voter, polymorphic: true
13
20
 
14
21
  t.boolean :vote_flag
15
22
  t.string :vote_scope
@@ -61,6 +68,7 @@ ActiveRecord::Schema.define(:version => 1) do
61
68
  t.integer :cached_votes_down
62
69
  t.integer :cached_weighted_total
63
70
  t.integer :cached_weighted_score
71
+ t.float :cached_weighted_average
64
72
 
65
73
  t.integer :cached_scoped_test_votes_total
66
74
  t.integer :cached_scoped_test_votes_score
@@ -68,6 +76,9 @@ ActiveRecord::Schema.define(:version => 1) do
68
76
  t.integer :cached_scoped_test_votes_down
69
77
  t.integer :cached_scoped_weighted_total
70
78
  t.integer :cached_scoped_weighted_score
79
+ t.float :cached_scoped_weighted_average
80
+
81
+ t.timestamps
71
82
  end
72
83
 
73
84
  end
@@ -78,7 +89,6 @@ class Voter < ActiveRecord::Base
78
89
  end
79
90
 
80
91
  class NotVoter < ActiveRecord::Base
81
-
82
92
  end
83
93
 
84
94
  class Votable < ActiveRecord::Base
@@ -102,7 +112,7 @@ class StiNotVotable < ActiveRecord::Base
102
112
  validates_presence_of :name
103
113
  end
104
114
 
105
- class VotableChildOfStiNotVotable < StiNotVotable
115
+ class ChildOfStiNotVotable < StiNotVotable
106
116
  acts_as_votable
107
117
  end
108
118
 
@@ -114,16 +124,16 @@ class VotableCache < ActiveRecord::Base
114
124
  validates_presence_of :name
115
125
  end
116
126
 
117
- class ABoringClass
118
- def self.hw
119
- 'hello world'
120
- end
127
+ class VotableCacheUpdate < VotableCache
128
+ acts_as_votable cacheable_strategy: :update
121
129
  end
122
130
 
131
+ class VotableCacheUpdateColumns < VotableCache
132
+ acts_as_votable cacheable_strategy: :update_columns
133
+ end
123
134
 
124
- def clean_database
125
- models = [ActsAsVotable::Vote, Voter, NotVoter, Votable, NotVotable, VotableCache]
126
- models.each do |model|
127
- ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
135
+ class ABoringClass
136
+ def self.hw
137
+ "hello world"
128
138
  end
129
139
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.include FactoryBot::Syntax::Methods
5
+
6
+ config.before(:suite) do
7
+ FactoryBot.find_definitions
8
+ end
9
+ end
@@ -1,20 +1,21 @@
1
- require 'acts_as_votable'
2
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
3
4
 
4
5
  describe ActsAsVotable::Votable do
5
6
  it "should not be votable" do
6
- NotVotable.should_not be_votable
7
+ expect(NotVotable).not_to be_votable
7
8
  end
8
9
 
9
10
  it "should be votable" do
10
- Votable.should be_votable
11
+ expect(Votable).to be_votable
11
12
  end
12
13
 
13
14
  it_behaves_like "a votable_model" do
14
- # TODO Replace with factories
15
- let (:voter) { Voter.create(:name =>'i can vote!') }
16
- let (:voter2) { Voter.create(:name => 'a new person') }
17
- let (:votable) { Votable.create(:name =>'a voting model') }
18
- let (:votable_cache) { VotableCache.create(:name => 'voting model with cache') }
15
+ let (:voter) { create(:voter, name: "i can vote!") }
16
+ let (:voter2) { create(:voter, name: "a new person") }
17
+ let (:voter3) { create(:voter, name: "another person") }
18
+ let (:votable) { create(:votable, name: "a voting model") }
19
+ let (:votable_cache) { create(:votable_cache, name: "voting model with cache") }
19
20
  end
20
21
  end
@@ -1,20 +1,20 @@
1
- require 'acts_as_votable'
2
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
3
4
 
4
5
  describe VotableVoter do
5
6
  it_behaves_like "a votable_model" do
6
- # TODO Replace with factories
7
- let (:voter) { VotableVoter.create(:name => 'i can vote!') }
8
- let (:voter2) { VotableVoter.create(:name => 'a new person') }
9
- let (:votable) { VotableVoter.create(:name => 'a voting model') }
10
- let (:votable_cache) { VotableCache.create(:name => 'voting model with cache') }
7
+ let (:voter) { create(:votable_voter, name: "i can vote!") }
8
+ let (:voter2) { create(:votable_voter, name: "a new person") }
9
+ let (:voter3) { create(:voter, name: "another person") }
10
+ let (:votable) { create(:votable_voter, name: "a voting model") }
11
+ let (:votable_cache) { create(:votable_cache, name: "voting model with cache") }
11
12
  end
12
13
 
13
14
  it_behaves_like "a voter_model" do
14
- # TODO Replace with factories
15
- let (:voter) { VotableVoter.create(:name => 'i can vote!') }
16
- let (:voter2) { VotableVoter.create(:name => 'a new person') }
17
- let (:votable) { VotableVoter.create(:name => 'a voting model') }
18
- let (:votable2) { VotableVoter.create(:name => 'a 2nd voting model') }
15
+ let (:voter) { create(:votable_voter, name: "i can vote!") }
16
+ let (:voter2) { create(:votable_voter, name: "a new person") }
17
+ let (:votable) { create(:votable_voter, name: "a voting model") }
18
+ let (:votable2) { create(:votable_voter, name: "a 2nd voting model") }
19
19
  end
20
20
  end
@@ -1,21 +1,20 @@
1
- require 'acts_as_votable'
2
- require 'spec_helper'
1
+ # frozen_string_literal: true
3
2
 
4
- describe ActsAsVotable::Voter do
3
+ require "spec_helper"
5
4
 
5
+ describe ActsAsVotable::Voter do
6
6
  it "should not be a voter" do
7
- NotVotable.should_not be_votable
7
+ expect(NotVotable).not_to be_votable
8
8
  end
9
9
 
10
10
  it "should be a voter" do
11
- Votable.should be_votable
11
+ expect(Votable).to be_votable
12
12
  end
13
13
 
14
14
  it_behaves_like "a voter_model" do
15
- # TODO Replace with factories
16
- let (:voter) { Voter.create(:name => 'i can vote!') }
17
- let (:voter2) { Voter.create(:name => 'a new person') }
18
- let (:votable) { Votable.create(:name => 'a voting model') }
19
- let (:votable2) { Votable.create(:name => 'a 2nd voting model') }
15
+ let (:voter) { create(:voter, name: "i can vote!") }
16
+ let (:voter2) { create(:voter, name: "a new person") }
17
+ let (:votable) { create(:votable, name: "a voting model") }
18
+ let (:votable2) { create(:votable, name: "a 2nd voting model") }
20
19
  end
21
20
  end