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
@@ -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_girl"
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 VotableCacheUpdateAttributes < VotableCache
128
+ acts_as_votable cacheable_strategy: :update_attributes
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,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # spec/support/factory_girl.rb
4
+ RSpec.configure do |config|
5
+ config.include FactoryGirl::Syntax::Methods
6
+
7
+ config.before(:suite) do
8
+ FactoryGirl.find_definitions
9
+ end
10
+ 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