ballot 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/Contributing.md +68 -0
  3. data/History.md +5 -0
  4. data/Licence.md +27 -0
  5. data/Manifest.txt +68 -0
  6. data/README.rdoc +264 -0
  7. data/Rakefile +71 -0
  8. data/bin/ballot_generator +9 -0
  9. data/lib/ballot.rb +25 -0
  10. data/lib/ballot/action_controller.rb +32 -0
  11. data/lib/ballot/active_record.rb +152 -0
  12. data/lib/ballot/active_record/votable.rb +145 -0
  13. data/lib/ballot/active_record/vote.rb +35 -0
  14. data/lib/ballot/active_record/voter.rb +99 -0
  15. data/lib/ballot/railtie.rb +19 -0
  16. data/lib/ballot/sequel.rb +170 -0
  17. data/lib/ballot/sequel/vote.rb +99 -0
  18. data/lib/ballot/votable.rb +445 -0
  19. data/lib/ballot/vote.rb +129 -0
  20. data/lib/ballot/voter.rb +320 -0
  21. data/lib/ballot/words.rb +32 -0
  22. data/lib/generators/ballot.rb +40 -0
  23. data/lib/generators/ballot/install/install_generator.rb +27 -0
  24. data/lib/generators/ballot/install/templates/active_record/migration.rb +19 -0
  25. data/lib/generators/ballot/install/templates/sequel/migration.rb +25 -0
  26. data/lib/generators/ballot/standalone.rb +89 -0
  27. data/lib/generators/ballot/standalone/support.rb +70 -0
  28. data/lib/generators/ballot/summary/summary_generator.rb +27 -0
  29. data/lib/generators/ballot/summary/templates/active_record/migration.rb +15 -0
  30. data/lib/generators/ballot/summary/templates/sequel/migration.rb +20 -0
  31. data/lib/sequel/plugins/ballot_votable.rb +180 -0
  32. data/lib/sequel/plugins/ballot_voter.rb +125 -0
  33. data/test/active_record/ballot_votable_test.rb +16 -0
  34. data/test/active_record/ballot_voter_test.rb +13 -0
  35. data/test/active_record/rails_generator_test.rb +28 -0
  36. data/test/active_record/votable_voter_test.rb +19 -0
  37. data/test/generators/rails-activerecord/Rakefile +2 -0
  38. data/test/generators/rails-activerecord/app/.keep +0 -0
  39. data/test/generators/rails-activerecord/bin/rails +5 -0
  40. data/test/generators/rails-activerecord/config/application.rb +17 -0
  41. data/test/generators/rails-activerecord/config/boot.rb +3 -0
  42. data/test/generators/rails-activerecord/config/database.yml +12 -0
  43. data/test/generators/rails-activerecord/config/environment.rb +3 -0
  44. data/test/generators/rails-activerecord/config/routes.rb +3 -0
  45. data/test/generators/rails-activerecord/config/secrets.yml +5 -0
  46. data/test/generators/rails-activerecord/db/seeds.rb +1 -0
  47. data/test/generators/rails-activerecord/log/.keep +0 -0
  48. data/test/generators/rails-sequel/Rakefile +2 -0
  49. data/test/generators/rails-sequel/app/.keep +0 -0
  50. data/test/generators/rails-sequel/bin/rails +5 -0
  51. data/test/generators/rails-sequel/config/application.rb +14 -0
  52. data/test/generators/rails-sequel/config/boot.rb +3 -0
  53. data/test/generators/rails-sequel/config/database.yml +12 -0
  54. data/test/generators/rails-sequel/config/environment.rb +3 -0
  55. data/test/generators/rails-sequel/config/routes.rb +3 -0
  56. data/test/generators/rails-sequel/config/secrets.yml +5 -0
  57. data/test/generators/rails-sequel/db/seeds.rb +1 -0
  58. data/test/generators/rails-sequel/log/.keep +0 -0
  59. data/test/minitest_config.rb +14 -0
  60. data/test/sequel/ballot_votable_test.rb +45 -0
  61. data/test/sequel/ballot_voter_test.rb +42 -0
  62. data/test/sequel/rails_generator_test.rb +25 -0
  63. data/test/sequel/votable_voter_test.rb +19 -0
  64. data/test/sequel/vote_test.rb +105 -0
  65. data/test/support/active_record_setup.rb +145 -0
  66. data/test/support/generators_setup.rb +129 -0
  67. data/test/support/sequel_setup.rb +164 -0
  68. data/test/support/shared_examples/votable_examples.rb +630 -0
  69. data/test/support/shared_examples/voter_examples.rb +600 -0
  70. metadata +333 -0
@@ -0,0 +1,600 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VoterExamples
4
+ def describe_voter_models(models, focus: false)
5
+ describe '.ballot_voter?' do
6
+ models.each do |model|
7
+ self.focus if focus && respond_to?(:focus)
8
+ it "#{model}.ballot_voter? is true" do
9
+ assert_true model.ballot_voter?
10
+ end
11
+
12
+ self.focus if focus && respond_to?(:focus)
13
+ it "#{model}#ballot_voter? is true" do
14
+ assert_true model.new.ballot_voter?
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def describe_non_voter_models(models, focus: false)
21
+ describe '.ballot_voter?' do
22
+ models.each do |model|
23
+ self.focus if focus && respond_to?(:focus)
24
+ it "#{model}.ballot_voter? is false" do
25
+ assert_false model.ballot_voter?
26
+ end
27
+
28
+ self.focus if focus && respond_to?(:focus)
29
+ it "#{model}.ballot_voter? is false" do
30
+ assert_false model.new.ballot_voter?
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def describe_ballot_voter(klass = nil, focus: false, &block)
37
+ msg = 'a voter model'
38
+ klass && msg = "#{klass} is #{msg}"
39
+
40
+ describe msg do
41
+ instance_exec(&block) if block
42
+
43
+ describe '#cast_ballot_for' do
44
+ self.focus if focus
45
+ it 'is false when no votable is provided' do
46
+ assert_false voter.cast_ballot_for
47
+ end
48
+
49
+ self.focus if focus
50
+ it 'is false when the votable is not a model' do
51
+ assert_false voter.cast_ballot_for Class.new
52
+ end
53
+
54
+ self.focus if focus
55
+ it 'is false when the votable is not a votable' do
56
+ assert_false voter.cast_ballot_for not_votable
57
+ end
58
+
59
+ self.focus if focus
60
+ it 'is true when a vote succeeds' do
61
+ assert_true voter.cast_ballot_for votable
62
+ end
63
+
64
+ self.focus if focus
65
+ it 'adds a vote' do
66
+ assert_true voter.cast_ballot_for votable
67
+ assert_true voter_dataset(voter).any?
68
+ assert_equal 1, voter_dataset(voter).count
69
+ end
70
+
71
+ self.focus if focus
72
+ it 'creates only one vote per item' do
73
+ voter.cast_ballot_for votable: votable
74
+
75
+ assert_true(
76
+ voter.cast_ballot_for(
77
+ votable_id: votable.id,
78
+ votable_type: ballot_type_name(votable),
79
+ vote: 'no'
80
+ )
81
+ )
82
+
83
+ assert_equal 1, votable_dataset(votable).count
84
+ end
85
+
86
+ self.focus if focus
87
+ it 'creates only one vote per item, unless duplicates are allowed' do
88
+ voter.cast_ballot_for votable: votable
89
+ assert_true voter.cast_ballot_for votable: votable, duplicate: true
90
+ assert_equal 2, votable_dataset(votable).count
91
+ end
92
+
93
+ self.focus if focus
94
+ it 'creates a scoped vote' do
95
+ voter.cast_ballot_for votable: votable, scope: 'rank'
96
+ assert_true votable_dataset(votable).where(scope: 'rank').any?
97
+ end
98
+
99
+ self.focus if focus
100
+ it 'creates only one scoped vote per person' do
101
+ voter.cast_ballot_for votable: votable, scope: 'rank'
102
+ voter.cast_ballot_for votable: votable, scope: 'rank', vote: 'no'
103
+ assert_equal 1, votable_dataset(votable).where(scope: 'rank').count
104
+ end
105
+
106
+ self.focus if focus
107
+ it 'creates only one scoped vote per person, unless duplicates are allowed' do
108
+ voter.cast_ballot_for votable: votable, scope: 'rank'
109
+ assert_true(
110
+ voter.cast_ballot_for(
111
+ votable: votable, scope: 'rank', vote: 'no', duplicate: true
112
+ )
113
+ )
114
+ assert_equal 2, votable_dataset(votable).where(scope: 'rank').count
115
+ end
116
+
117
+ self.focus if focus
118
+ it 'creates multiple votes with different scopes' do
119
+ assert_true voter.cast_ballot_for votable: votable, scope: 'weekly_rank'
120
+ assert_true voter.cast_ballot_for votable: votable, scope: 'monthly_rank'
121
+ assert_equal 2, votable_dataset(votable).count
122
+ end
123
+
124
+ self.focus if focus
125
+ it 'records separate votes for separate voters' do
126
+ assert_true voter.cast_ballot_for votable: votable
127
+ assert_true voter2.cast_ballot_for votable: votable
128
+ assert_equal 2, votable_dataset(votable).count
129
+ end
130
+
131
+ self.focus if focus
132
+ it 'uses a default vote weight of 1' do
133
+ voter.cast_ballot_for votable
134
+ assert_equal 1, votable_dataset(votable).first.weight
135
+ end
136
+ end
137
+
138
+ describe '#cast_up_ballot_for' do
139
+ self.focus if focus
140
+ it 'is false when the votable is not a model' do
141
+ assert_false voter.cast_up_ballot_for Class.new
142
+ end
143
+
144
+ self.focus if focus
145
+ it 'is false when the votable is not a votable' do
146
+ assert_false voter.cast_up_ballot_for not_votable
147
+ end
148
+
149
+ self.focus if focus
150
+ it 'is true when a vote succeeds' do
151
+ assert_true voter.cast_up_ballot_for votable
152
+ end
153
+
154
+ self.focus if focus
155
+ it 'adds a vote' do
156
+ assert_true voter.cast_up_ballot_for votable
157
+ assert_true voter_dataset(voter).any?
158
+ assert_equal 1, votable_dataset(votable).count
159
+ end
160
+
161
+ self.focus if focus
162
+ it 'creates only one vote per item' do
163
+ voter.cast_up_ballot_for votable
164
+ assert_false voter.cast_up_ballot_for votable, vote: 'no'
165
+ assert_equal 1, votable_dataset(votable).count
166
+ end
167
+
168
+ self.focus if focus
169
+ it 'creates only one vote per item, unless duplicates are allowed' do
170
+ voter.cast_up_ballot_for votable
171
+ assert_true voter.cast_up_ballot_for votable, duplicate: true
172
+ assert_equal 2, votable_dataset(votable).count
173
+ end
174
+
175
+ self.focus if focus
176
+ it 'creates a scoped vote' do
177
+ voter.cast_up_ballot_for votable, scope: 'rank'
178
+ assert_true votable_dataset(votable).where(scope: 'rank').any?
179
+ end
180
+
181
+ self.focus if focus
182
+ it 'creates only one scoped vote per person' do
183
+ voter.cast_up_ballot_for votable, scope: 'rank'
184
+ voter.cast_up_ballot_for votable, scope: 'rank', vote: 'no'
185
+ assert_equal 1, votable_dataset(votable).where(scope: 'rank').count
186
+ end
187
+
188
+ self.focus if focus
189
+ it 'creates only one scoped vote per person, unless duplicates are allowed' do
190
+ voter.cast_up_ballot_for votable, scope: 'rank'
191
+ assert_true(
192
+ voter.cast_up_ballot_for(votable, scope: 'rank', vote: 'no', duplicate: true)
193
+ )
194
+ assert_equal 2, votable_dataset(votable).where(scope: 'rank').count
195
+ end
196
+
197
+ self.focus if focus
198
+ it 'creates multiple votes with different scopes' do
199
+ assert_true voter.cast_up_ballot_for votable, scope: 'weekly_rank'
200
+ assert_true voter.cast_up_ballot_for votable, scope: 'monthly_rank'
201
+ assert_equal 2, votable_dataset(votable).count
202
+ end
203
+
204
+ self.focus if focus
205
+ it 'records separate votes for separate voters' do
206
+ assert_true voter.cast_up_ballot_for votable
207
+ assert_true voter2.cast_up_ballot_for votable
208
+ assert_equal 2, votable_dataset(votable).count
209
+ end
210
+
211
+ self.focus if focus
212
+ it 'uses a default vote weight of 1' do
213
+ voter.cast_up_ballot_for votable
214
+ assert_equal 1, votable_dataset(votable).first.weight
215
+ end
216
+ end
217
+
218
+ describe '#cast_down_ballot_for' do
219
+ self.focus if focus
220
+ it 'is false when the votable is not a model' do
221
+ assert_false voter.cast_down_ballot_for Class.new
222
+ end
223
+
224
+ self.focus if focus
225
+ it 'is false when the votable is not a votable' do
226
+ assert_false voter.cast_down_ballot_for not_votable
227
+ end
228
+
229
+ self.focus if focus
230
+ it 'is true when a vote succeeds' do
231
+ assert_true voter.cast_down_ballot_for votable
232
+ end
233
+
234
+ self.focus if focus
235
+ it 'adds a vote' do
236
+ assert_true voter.cast_down_ballot_for votable
237
+ assert_true voter_dataset(voter).any?
238
+ assert_equal 1, votable_dataset(votable).count
239
+ end
240
+
241
+ self.focus if focus
242
+ it 'creates only one vote per item' do
243
+ voter.cast_down_ballot_for votable
244
+ assert_false voter.cast_down_ballot_for votable, vote: 'no'
245
+ assert_equal 1, votable_dataset(votable).count
246
+ end
247
+
248
+ self.focus if focus
249
+ it 'creates only one vote per item, unless duplicates are allowed' do
250
+ voter.cast_down_ballot_for votable
251
+ assert_true voter.cast_down_ballot_for votable, duplicate: true
252
+ assert_equal 2, votable_dataset(votable).count
253
+ end
254
+
255
+ self.focus if focus
256
+ it 'creates a scoped vote' do
257
+ voter.cast_down_ballot_for votable, scope: 'rank'
258
+ assert_true votable_dataset(votable).where(scope: 'rank').any?
259
+ end
260
+
261
+ self.focus if focus
262
+ it 'creates only one scoped vote per person' do
263
+ voter.cast_down_ballot_for votable, scope: 'rank'
264
+ voter.cast_down_ballot_for votable, scope: 'rank', vote: 'no'
265
+ assert_equal 1, votable_dataset(votable).where(scope: 'rank').count
266
+ end
267
+
268
+ self.focus if focus
269
+ it 'creates only one scoped vote per person, unless duplicates are allowed' do
270
+ voter.cast_down_ballot_for votable, scope: 'rank'
271
+ assert_true(
272
+ voter.cast_down_ballot_for(votable, scope: 'rank', vote: 'no', duplicate: true)
273
+ )
274
+ assert_equal 2, votable_dataset(votable).where(scope: 'rank').count
275
+ end
276
+
277
+ self.focus if focus
278
+ it 'creates multiple votes with different scopes' do
279
+ assert_true voter.cast_down_ballot_for votable, scope: 'weekly_rank'
280
+ assert_true voter.cast_down_ballot_for votable, scope: 'monthly_rank'
281
+ assert_equal 2, votable_dataset(votable).count
282
+ end
283
+
284
+ self.focus if focus
285
+ it 'records separate votes for separate voters' do
286
+ assert_true voter.cast_down_ballot_for votable
287
+ assert_true voter2.cast_down_ballot_for votable
288
+ assert_equal 2, votable_dataset(votable).count
289
+ end
290
+
291
+ self.focus if focus
292
+ it 'uses a default vote weight of 1' do
293
+ voter.cast_down_ballot_for votable
294
+ assert_equal 1, votable_dataset(votable).first.weight
295
+ end
296
+ end
297
+
298
+ describe '#remove_ballot_for' do
299
+ self.focus if focus
300
+ it 'removes an up vote' do
301
+ voter.cast_up_ballot_for votable
302
+ assert_true voter.remove_ballot_for votable
303
+ assert_true votable_dataset(votable).none?
304
+ end
305
+
306
+ self.focus if focus
307
+ it 'removes a down vote' do
308
+ voter.cast_down_ballot_for votable
309
+ assert_true voter.remove_ballot_for votable
310
+ assert_true votable_dataset(votable).none?
311
+ end
312
+
313
+ self.focus if focus
314
+ it 'sets ballot_registered? to false' do
315
+ voter.cast_ballot_for votable
316
+ assert_true voter.remove_ballot_for votable
317
+ assert_false votable.ballot_registered?
318
+ end
319
+
320
+ self.focus if focus
321
+ it 'removes only a single vote' do
322
+ voter.cast_up_ballot_for votable
323
+ voter2.cast_up_ballot_for votable
324
+ voter.remove_ballot_for votable
325
+ assert_true votable_dataset(votable).any?
326
+ assert_true votable_dataset(votable).where(
327
+ voter_id: voter.id,
328
+ voter_type: voter.class.name
329
+ ).none?
330
+ assert_true votable_dataset(votable).where(
331
+ voter_id: voter2.id,
332
+ voter_type: voter2.class.name
333
+ ).any?
334
+ end
335
+ end
336
+
337
+ describe '#cast_ballot_for?' do
338
+ self.focus if focus
339
+ it 'is true if the user voted up' do
340
+ voter.cast_up_ballot_for votable
341
+ assert_true voter.cast_ballot_for?(votable)
342
+ end
343
+
344
+ self.focus if focus
345
+ it 'is true if the user voted down' do
346
+ voter.cast_down_ballot_for votable
347
+ assert_true voter.cast_ballot_for?(votable)
348
+ end
349
+
350
+ self.focus if focus
351
+ it 'is false if the user has not voted' do
352
+ assert_false voter.cast_ballot_for?(votable)
353
+ end
354
+
355
+ self.focus if focus
356
+ it 'is true if the user voted in scope' do
357
+ voter.cast_up_ballot_for votable, scope: 'rank'
358
+ assert_false voter.cast_ballot_for?(votable)
359
+ assert_true voter.cast_ballot_for?(votable, scope: 'rank')
360
+ end
361
+ end
362
+
363
+ describe '#cast_up_ballot_for?, #cast_down_ballot_for?' do
364
+ self.focus if focus
365
+ it 'is up if the user voted up' do
366
+ voter.cast_up_ballot_for votable
367
+ assert_true voter.cast_up_ballot_for?(votable)
368
+ assert_false voter.cast_down_ballot_for?(votable)
369
+ end
370
+
371
+ self.focus if focus
372
+ it 'is true if the user voted down' do
373
+ voter.cast_down_ballot_for votable
374
+ assert_false voter.cast_up_ballot_for?(votable)
375
+ assert_true voter.cast_down_ballot_for?(votable)
376
+ end
377
+
378
+ self.focus if focus
379
+ it 'is false if the user has not voted' do
380
+ assert_false voter.cast_up_ballot_for?(votable)
381
+ assert_false voter.cast_down_ballot_for?(votable)
382
+ end
383
+
384
+ self.focus if focus
385
+ it 'is true if the user voted in scope' do
386
+ voter.cast_up_ballot_for votable, scope: 'rank'
387
+ assert_false voter.cast_up_ballot_for?(votable)
388
+ assert_false voter.cast_down_ballot_for?(votable)
389
+ assert_true voter.cast_up_ballot_for?(votable, scope: 'rank')
390
+ assert_false voter.cast_down_ballot_for?(votable, scope: 'rank')
391
+ end
392
+ end
393
+
394
+ describe '#ballot_as_cast_for' do
395
+ self.focus if focus
396
+ it 'is true when voted up' do
397
+ voter.cast_up_ballot_for votable
398
+ assert_true voter.ballot_as_cast_for(votable)
399
+ end
400
+
401
+ self.focus if focus
402
+ it 'is false when voted down' do
403
+ voter.cast_down_ballot_for votable
404
+ assert_false voter.ballot_as_cast_for(votable)
405
+ end
406
+
407
+ self.focus if focus
408
+ it 'is nil when not voted' do
409
+ assert_nil voter.ballot_as_cast_for(votable)
410
+ end
411
+
412
+ self.focus if focus
413
+ it 'is true when voted up with a scope' do
414
+ voter.cast_up_ballot_for votable, scope: 'rank'
415
+ assert_true voter.ballot_as_cast_for(votable, scope: 'rank')
416
+ assert_nil voter.ballot_as_cast_for(votable)
417
+ end
418
+
419
+ self.focus if focus
420
+ it 'is false when voted down' do
421
+ voter.cast_down_ballot_for votable, scope: 'rank'
422
+ assert_false voter.ballot_as_cast_for(votable, scope: 'rank')
423
+ assert_nil voter.ballot_as_cast_for(votable)
424
+ end
425
+
426
+ self.focus if focus
427
+ it 'is nil when not voted' do
428
+ assert_nil voter.ballot_as_cast_for(votable, scope: 'rank')
429
+ end
430
+
431
+ self.focus if focus
432
+ it 'applies only to the voter' do
433
+ voter.cast_down_ballot_for votable
434
+ voter2.cast_up_ballot_for votable
435
+ assert_false voter.ballot_as_cast_for(votable)
436
+ end
437
+ end
438
+
439
+ describe '#up_ballots_by' do
440
+ self.focus if focus
441
+ it 'returns the set of up votes' do
442
+ voter.cast_up_ballot_for votable
443
+ voter.cast_up_ballot_for sti_votable
444
+ voter.cast_down_ballot_for child_of_sti_votable
445
+ voter.cast_down_ballot_for votable_child_of_sti_not_votable
446
+
447
+ assert_equal [
448
+ votable_dataset(votable).first,
449
+ votable_dataset(sti_votable).first
450
+ ], voter.up_ballots_by.all
451
+ end
452
+ end
453
+
454
+ describe '#down_ballots_by' do
455
+ self.focus if focus
456
+ it 'returns the set of down votes' do
457
+ voter.cast_up_ballot_for votable
458
+ voter.cast_up_ballot_for sti_votable
459
+ voter.cast_down_ballot_for child_of_sti_votable
460
+ voter.cast_down_ballot_for votable_child_of_sti_not_votable
461
+
462
+ assert_equal [
463
+ votable_dataset(child_of_sti_votable).first,
464
+ votable_dataset(votable_child_of_sti_not_votable).first
465
+ ], voter.down_ballots_by.all
466
+ end
467
+ end
468
+
469
+ describe '#ballots_for_class' do
470
+ self.focus if focus
471
+ it 'returns the set of votes for this class' do
472
+ voter.cast_up_ballot_for votable
473
+ voter.cast_down_ballot_for votable2
474
+
475
+ assert_equal [ votable_dataset(votable).first, votable_dataset(votable2).first ],
476
+ voter.ballots_for_class(votable.class).all
477
+ end
478
+ end
479
+
480
+ describe '#up_ballots_for_class' do
481
+ self.focus if focus
482
+ it 'returns the set of up votes for this class' do
483
+ voter.cast_up_ballot_for votable
484
+ voter.cast_down_ballot_for votable2
485
+
486
+ assert_equal [ votable_dataset(votable).first ],
487
+ voter.up_ballots_for_class(votable.class).all
488
+ end
489
+ end
490
+
491
+ describe '#down_ballots_for_class' do
492
+ self.focus if focus
493
+ it 'returns the set of down votes for this class' do
494
+ voter.cast_up_ballot_for votable
495
+ voter.cast_down_ballot_for votable2
496
+
497
+ assert_equal [ votable_dataset(votable2).first ],
498
+ voter.down_ballots_for_class(votable.class).all
499
+ end
500
+ end
501
+
502
+ describe '#ballot_votables' do
503
+ self.focus if focus
504
+ it 'returns the set of items voted on' do
505
+ voter.cast_up_ballot_for votable
506
+ voter.cast_down_ballot_for votable2
507
+
508
+ assert_equal [ votable, votable2 ], voter.ballot_votables
509
+ end
510
+ end
511
+
512
+ describe '#ballot_up_votables' do
513
+ self.focus if focus
514
+ it 'returns the set of items up voted' do
515
+ voter.cast_up_ballot_for votable
516
+ voter.cast_down_ballot_for votable2
517
+
518
+ assert_equal [ votable ], voter.ballot_up_votables
519
+ end
520
+ end
521
+
522
+ describe '#ballot_down_votables' do
523
+ self.focus if focus
524
+ it 'returns the set of items down voted' do
525
+ voter.cast_up_ballot_for votable
526
+ voter.cast_down_ballot_for votable2
527
+
528
+ assert_equal [ votable2 ], voter.ballot_down_votables
529
+ end
530
+ end
531
+ end
532
+ end
533
+
534
+ def describe_ballot_voter_sti_votable_support(focus: false)
535
+ describe 'with STI' do
536
+ describe '#vote' do
537
+ self.focus if focus && respond_to?(:focus)
538
+ it 'works with STI models' do
539
+ voter.cast_ballot_for sti_votable
540
+ assert_true votable_dataset(sti_votable).any?
541
+ end
542
+
543
+ self.focus if focus && respond_to?(:focus)
544
+ it 'works with Child STI models' do
545
+ voter.cast_ballot_for child_of_sti_votable
546
+ assert_true votable_dataset(child_of_sti_votable).any?
547
+ end
548
+
549
+ self.focus if focus && respond_to?(:focus)
550
+ it 'works with votable children of non-votable STI models' do
551
+ voter.cast_ballot_for votable_child_of_sti_not_votable
552
+ assert_true votable_dataset(votable_child_of_sti_not_votable).any?
553
+ end
554
+ end
555
+
556
+ describe '#cast_up_ballot_for' do
557
+ self.focus if focus && respond_to?(:focus)
558
+ it 'works with STI models' do
559
+ voter.cast_up_ballot_for sti_votable
560
+ assert_true votable_dataset(sti_votable).any?
561
+ end
562
+
563
+ self.focus if focus && respond_to?(:focus)
564
+ it 'works with Child STI models' do
565
+ voter.cast_up_ballot_for child_of_sti_votable
566
+ assert_true votable_dataset(child_of_sti_votable).any?
567
+ end
568
+
569
+ self.focus if focus && respond_to?(:focus)
570
+ it 'works with votable children of non-votable STI models' do
571
+ voter.cast_up_ballot_for votable_child_of_sti_not_votable
572
+ assert_true votable_dataset(votable_child_of_sti_not_votable).any?
573
+ end
574
+ end
575
+
576
+ describe '#cast_down_ballot_for' do
577
+ self.focus if focus && respond_to?(:focus)
578
+ it 'works with STI models' do
579
+ voter.cast_down_ballot_for sti_votable
580
+ assert_true votable_dataset(sti_votable).any?
581
+ end
582
+
583
+ self.focus if focus && respond_to?(:focus)
584
+ it 'works with Child STI models' do
585
+ voter.cast_down_ballot_for child_of_sti_votable
586
+ assert_true votable_dataset(child_of_sti_votable).any?
587
+ end
588
+
589
+ self.focus if focus && respond_to?(:focus)
590
+ it 'works with votable children of non-votable STI models' do
591
+ voter.cast_down_ballot_for votable_child_of_sti_not_votable
592
+ assert_true votable_dataset(votable_child_of_sti_not_votable).any?
593
+ end
594
+ end
595
+ end
596
+ end
597
+
598
+ ::Minitest::SequelSpec.extend self
599
+ ::Minitest::ActiveRecordSpec.extend self
600
+ end