ballot 1.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 (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,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_config'
4
+
5
+ describe 'RailsGenerator' do
6
+ describe 'for Sequel' do
7
+ let(:orm_name) { 'sequel' }
8
+ let(:orm_version) { Sequel::VERSION }
9
+ let(:rails_version) { ActiveRecord::VERSION::STRING }
10
+
11
+ test_ballot_install(
12
+ generate: %r{create\s+db/migrate/\d+_install_ballot_vote_migration},
13
+ contents: /Sequel.migration.*create_table :ballot_votes do/m
14
+ )
15
+
16
+ test_ballot_summary_votable(
17
+ generate: %r{create\s+db/migrate/\d+_ballot_cache_for_votable},
18
+ contents: %r{
19
+ Sequel.migration.*
20
+ alter_table\s+:'votables'.*
21
+ add_column\s+:cached_ballot_summary,
22
+ }mx
23
+ )
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_config'
4
+
5
+ describe SequelVotableVoter do
6
+ describe_ballot_voter do
7
+ let(:voter) { SequelVotableVoter.create(name: 'I can vote!') }
8
+ let(:voter2) { SequelVotableVoter.create(name: 'I, too, can vote!') }
9
+ let(:votable) { voter2 }
10
+ let(:votable2) { voter }
11
+ end
12
+
13
+ describe_ballot_votable do
14
+ let(:voter) { SequelVotableVoter.create(name: 'I can vote!') }
15
+ let(:voter2) { SequelVotableVoter.create(name: 'I, too, can vote!') }
16
+ let(:votable) { voter2 }
17
+ let(:votable2) { voter }
18
+ end
19
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_config'
4
+
5
+ describe Ballot::Sequel::Vote do
6
+ before do
7
+ voter.cast_up_ballot_for votable
8
+ voter.cast_up_ballot_for votable2
9
+ voter.cast_up_ballot_for votable_cache
10
+ voter2.cast_down_ballot_for votable
11
+ voter2.cast_down_ballot_for votable2
12
+ voter2.cast_down_ballot_for votable_cache
13
+ expected_votes # Force the query now
14
+ end
15
+
16
+ let(:expected_votes) {
17
+ [
18
+ Ballot::Sequel::Vote[1],
19
+ Ballot::Sequel::Vote[2],
20
+ Ballot::Sequel::Vote[3],
21
+ Ballot::Sequel::Vote[4],
22
+ Ballot::Sequel::Vote[5],
23
+ Ballot::Sequel::Vote[6]
24
+ ]
25
+ }
26
+
27
+ describe 'dataset_module' do
28
+ it 'provides an up subset' do
29
+ assert_equal 3, Ballot::Sequel::Vote.dataset.up.count
30
+ assert_equal 3, Ballot::Sequel::Vote.up.count
31
+ end
32
+
33
+ it 'provides a down subset' do
34
+ assert_equal 3, Ballot::Sequel::Vote.dataset.down.count
35
+ assert_equal 3, Ballot::Sequel::Vote.down.count
36
+ end
37
+
38
+ it 'provides a for_type filter' do
39
+ assert_empty Ballot::Sequel::Vote.dataset.for_type('SequelNotVotable')
40
+ assert_empty Ballot::Sequel::Vote.for_type(SequelNotVotable)
41
+ refute_empty Ballot::Sequel::Vote.dataset.for_type('SequelVotable')
42
+ refute_empty Ballot::Sequel::Vote.for_type(SequelVotable)
43
+ end
44
+
45
+ it 'provides a by_type filter' do
46
+ assert_empty Ballot::Sequel::Vote.dataset.by_type('SequelNotVoter')
47
+ assert_empty Ballot::Sequel::Vote.by_type(SequelNotVoter)
48
+ refute_empty Ballot::Sequel::Vote.dataset.by_type('SequelVoter')
49
+ refute_empty Ballot::Sequel::Vote.by_type(SequelVoter)
50
+ end
51
+ end
52
+
53
+ describe 'votable association' do
54
+ it 'defines #votable= correctly' do
55
+ v = Ballot::Sequel::Vote.new
56
+ v.votable = votable
57
+ assert_equal votable.id, v.votable_id
58
+ assert_equal Ballot::Sequel.type_name(votable), v.votable_type
59
+ end
60
+
61
+ it 'defines votable_dataset correctly' do
62
+ assert_equal votable, voter.ballots_by.first.votable
63
+ end
64
+
65
+ it 'defines eager loading correctly' do
66
+ sqls = capture_sql {
67
+ actual = Ballot::Sequel::Vote.eager(:votable).all
68
+ assert_equal expected_votes, actual
69
+ assert_equal [ votable, votable2, votable_cache ], actual.shift(3).map(&:votable)
70
+ assert_equal [ votable, votable2, votable_cache ], actual.shift(3).map(&:votable)
71
+ }
72
+
73
+ assert_match(/SELECT \* FROM `ballot_votes`/, sqls.shift)
74
+ assert_match(/SELECT \* FROM `votables` WHERE \(`id` IN \(1, 2\)\)/, sqls.shift)
75
+ assert_match(/SELECT \* FROM `votable_caches` WHERE \(`id` IN \(1\)\)/, sqls.shift)
76
+ assert_empty sqls
77
+ end
78
+ end
79
+
80
+ describe 'voter association' do
81
+ it 'defines #voter= correctly' do
82
+ v = Ballot::Sequel::Vote.new
83
+ v.voter = voter
84
+ assert_equal voter.id, v.voter_id
85
+ assert_equal Ballot::Sequel.type_name(voter), v.voter_type
86
+ end
87
+
88
+ it 'defines voter_dataset correctly' do
89
+ assert_equal voter, votable.ballots_for_dataset.first.voter
90
+ end
91
+
92
+ it 'defines eager loading correctly' do
93
+ sqls = capture_sql {
94
+ actual = Ballot::Sequel::Vote.eager(:voter).all
95
+ assert_equal expected_votes, actual
96
+ assert_equal [ voter ] * 3, actual.shift(3).map(&:voter)
97
+ assert_equal [ voter2 ] * 3, actual.shift(3).map(&:voter)
98
+ }
99
+
100
+ assert_match(/SELECT \* FROM `ballot_votes`/, sqls.shift)
101
+ assert_match(/SELECT \* FROM `voters` WHERE \(`id` IN \(1, 2\)\)/, sqls.shift)
102
+ assert_empty sqls
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record'
4
+
5
+ if RUBY_ENGINE == 'jruby'
6
+ require 'activerecord-jdbcsqlite3-adapter'
7
+ else
8
+ require 'sqlite3'
9
+ end
10
+
11
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
12
+
13
+ ActiveRecord::Schema.verbose = false
14
+ ActiveRecord::Schema.define(version: 1) do
15
+ create_table :ballot_votes do |t|
16
+ t.references :votable, polymorphic: true
17
+ t.references :voter, polymorphic: true
18
+
19
+ t.boolean :vote
20
+ t.string :scope
21
+ t.integer :weight
22
+
23
+ t.timestamps null: false, default: 'now()'
24
+ end
25
+
26
+ add_index :ballot_votes, %i(voter_id voter_type scope)
27
+ add_index :ballot_votes, %i(votable_id votable_type scope)
28
+
29
+ %i(voters not_voters votables not_votables votable_voters).each do |table|
30
+ create_table table do |t|
31
+ t.string :name
32
+ end
33
+ end
34
+
35
+ %i(sti_votables sti_not_votables).each do |table|
36
+ create_table table do |t|
37
+ t.string :name
38
+ t.string :type
39
+ end
40
+ end
41
+
42
+ create_table :votable_caches do |t|
43
+ t.string :name
44
+
45
+ if t.respond_to?(:jsonb)
46
+ t.jsonb :cached_ballot_summary
47
+ else
48
+ t.string :cached_ballot_summary
49
+ end
50
+ end
51
+ end
52
+
53
+ require 'ballot/active_record'
54
+ Ballot::ActiveRecord.inject!
55
+
56
+ class ARVoter < ActiveRecord::Base
57
+ self.table_name = 'voters'
58
+ acts_as_ballot :voter
59
+ end
60
+
61
+ class ARNotVoter < ActiveRecord::Base
62
+ self.table_name = 'not_voters'
63
+ end
64
+
65
+ class ARVotable < ActiveRecord::Base
66
+ self.table_name = 'votables'
67
+ acts_as_ballot :votable
68
+ end
69
+
70
+ class ARNotVotable < ActiveRecord::Base
71
+ self.table_name = 'not_votables'
72
+ end
73
+
74
+ class ARVotableVoter < ActiveRecord::Base
75
+ self.table_name = 'votable_voters'
76
+ acts_as_ballot :voter
77
+ acts_as_ballot :votable
78
+ end
79
+
80
+ class ARStiVotable < ActiveRecord::Base
81
+ self.table_name = 'sti_votables'
82
+ acts_as_ballot :votable
83
+ end
84
+
85
+ class ARChildOfStiVotable < ARStiVotable
86
+ end
87
+
88
+ class ARStiNotVotable < ActiveRecord::Base
89
+ self.table_name = 'sti_not_votables'
90
+ end
91
+
92
+ class ARVotableChildOfStiNotVotable < ARStiNotVotable
93
+ acts_as_ballot :votable
94
+ end
95
+
96
+ class ARVotableCache < ActiveRecord::Base
97
+ self.table_name = 'votable_caches'
98
+ acts_as_ballot :votable
99
+ end
100
+
101
+ class ARABoringClass
102
+ end
103
+
104
+ class Minitest::ActiveRecordSpec < Minitest::HooksSpec
105
+ register_spec_type(/ActiveRecord|\AAR/, self)
106
+
107
+ AbortTransaction = Class.new(StandardError)
108
+
109
+ def around
110
+ ActiveRecord::Base.connection.transaction do
111
+ super
112
+ fail AbortTransaction
113
+ end
114
+ rescue AbortTransaction
115
+ true # This transaction has been deliberately aborted.
116
+ end
117
+
118
+ def votable_dataset(votable)
119
+ votable.ballots_for
120
+ end
121
+
122
+ def voter_dataset(voter)
123
+ voter.ballots_by
124
+ end
125
+
126
+ def ballot_type_name(item)
127
+ Ballot::ActiveRecord.type_name(item)
128
+ end
129
+
130
+ let(:voter) { ARVoter.create(name: 'I can vote!') }
131
+ let(:voter2) { ARVoter.create(name: 'I, too, can vote!') }
132
+ let(:not_voter) { ARNotVoter.create(name: 'I cannot vote!') }
133
+
134
+ let(:votable) { ARVotable.create(name: 'a votable model') }
135
+ let(:votable2) { ARVotable.create(name: 'a second votable model') }
136
+ let(:votable_cache) { ARVotableCache.create(name: 'a votable model with caching') }
137
+ let(:sti_votable) { ARStiVotable.create(name: 'a votable STI model') }
138
+ let(:child_of_sti_votable) {
139
+ ARChildOfStiVotable.create(name: 'a votable STI child model')
140
+ }
141
+ let(:votable_child_of_sti_not_votable) {
142
+ ARVotableChildOfStiNotVotable.create(name: 'a votable STI child of a non-votable')
143
+ }
144
+ let(:not_votable) { ARNotVotable.create(name: 'a non-votable model') }
145
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Minitest::RailsGeneratorSpec < Minitest::HooksSpec
4
+ register_spec_type(/RailsGenerator/, self)
5
+
6
+ let(:app_path) { "test/generators/rails-#{orm_name}" }
7
+
8
+ def around
9
+ ENV['RAILS_VERSION'] = rails_version
10
+ ENV['ORM_VERSION'] = orm_version
11
+ gemfile = File.join(File.expand_path(app_path), 'Gemfile')
12
+
13
+ Dir.chdir(app_path) do
14
+ without_current_bundler do
15
+ ENV['BUNDLE_GEMFILE'] = gemfile
16
+ system! 'git clean -fdx .'
17
+ system! 'gem install bundler'
18
+ if ENV['TRAVIS']
19
+ system! 'bundle --version'
20
+ system! 'bundle install'
21
+ end
22
+ system! 'bundle exec rake db:create'
23
+ system! 'bundle exec rails g model votable name'
24
+ run_migrations!
25
+
26
+ yield
27
+ end
28
+ end
29
+ ensure
30
+ ENV.delete('ORM_VERSION')
31
+ ENV.delete('RAILS_VERSION')
32
+ ENV.delete('BUNDLE_GEMFILE')
33
+ end
34
+
35
+ def without_current_bundler(&block)
36
+ if defined?(::Bundler)
37
+ Bundler.with_clean_env(&block)
38
+ else
39
+ yield
40
+ end
41
+ end
42
+
43
+ def assert_subprocess_output(stdout = nil, stderr = nil)
44
+ out, err = capture_subprocess_io { yield }
45
+
46
+ err_msg = stderr.kind_of?(Regexp) ? :assert_match : :assert_equal if stderr
47
+ out_msg = stdout.kind_of?(Regexp) ? :assert_match : :assert_equal if stdout
48
+
49
+ y = send err_msg, stderr, err, 'In stderr' if err_msg
50
+ x = send out_msg, stdout, out, 'In stdout' if out_msg
51
+
52
+ (!stdout || x) && (!stderr || y)
53
+ end
54
+
55
+ def assert_contents(contents, filename)
56
+ contents_msg = contents.kind_of?(Regexp) ? :assert_match : :assert_equal
57
+ send contents_msg, contents, File.read(filename), 'In contents'
58
+ end
59
+
60
+ def run_migrations
61
+ system 'bundle exec rake db:migrate'
62
+ end
63
+
64
+ def run_migrations!
65
+ system! 'bundle exec rake db:migrate'
66
+ end
67
+
68
+ def system!(command)
69
+ output = capture_subprocess_io { system command }
70
+ fail output.join("\n") unless $?.success?
71
+ end
72
+
73
+ def rails_generate(*args)
74
+ system "bundle exec rails g #{args.join(' ')}"
75
+ end
76
+
77
+ class << self
78
+ def focus!
79
+ @focussed = true
80
+ end
81
+
82
+ def focussed?
83
+ !!@focussed
84
+ end
85
+
86
+ def test_ballot_install(generate: nil, migrate: nil, contents: nil)
87
+ return unless ENV['CI'] || ENV['TEST_GENERATORS']
88
+
89
+ fail 'Contents must be provided' unless contents
90
+
91
+ focus if focussed?
92
+ it 'installs the ballot_votes table' do
93
+ assert_subprocess_output generate || '' do
94
+ rails_generate 'ballot:install'
95
+ end
96
+
97
+ assert_subprocess_output migrate || '' do
98
+ run_migrations
99
+ end
100
+
101
+ assert_contents contents,
102
+ Dir['db/migrate/*_install_ballot_vote_migration.rb'].first
103
+ end
104
+ end
105
+
106
+ def test_ballot_summary_votable(generate: nil, migrate: nil, contents: nil)
107
+ return unless ENV['CI'] || ENV['TEST_GENERATORS']
108
+
109
+ fail 'Contents must be provided' unless contents
110
+
111
+ focus if focussed?
112
+ it 'adds the summary column to the votable table' do
113
+ assert_nil File.read('db/schema.rb').match(/cached_ballot_summary/)
114
+
115
+ assert_subprocess_output generate || '' do
116
+ rails_generate 'ballot:summary', 'votable'
117
+ end
118
+
119
+ assert_subprocess_output migrate || '' do
120
+ run_migrations
121
+ end
122
+
123
+ assert_contents contents,
124
+ Dir['db/migrate/*_ballot_cache_for_votable.rb'].first
125
+ assert_contents(/cached_ballot_summary/, 'db/schema.rb')
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+
5
+ DB = if RUBY_ENGINE == 'jruby'
6
+ Sequel.connect('jdbc:sqlite::memory:')
7
+ else
8
+ Sequel.sqlite
9
+ end
10
+
11
+ class SQLLogger
12
+ class << self
13
+ def sqls
14
+ Thread.current['sqls'] ||= []
15
+ end
16
+
17
+ def method_missing(_, msg)
18
+ sqls << msg
19
+ end
20
+
21
+ def clear
22
+ sqls.clear
23
+ end
24
+ end
25
+ end
26
+
27
+ DB.loggers << SQLLogger
28
+
29
+ DB.create_table? :ballot_votes do
30
+ primary_key :id
31
+ Integer :votable_id
32
+ String :votable_type
33
+
34
+ Integer :voter_id
35
+ String :voter_type
36
+
37
+ Boolean :vote
38
+ String :scope
39
+ Integer :weight
40
+
41
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
42
+ DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
43
+ end
44
+
45
+ %i(voters not_voters votables not_votables votable_voters).each do |table|
46
+ DB.create_table? table do
47
+ primary_key :id
48
+ String :name
49
+ end
50
+ end
51
+
52
+ %i(sti_votables sti_not_votables).each do |table|
53
+ DB.create_table? table do
54
+ primary_key :id
55
+ String :name
56
+ String :type
57
+ end
58
+ end
59
+
60
+ DB.create_table? :votable_caches do
61
+ primary_key :id
62
+
63
+ String :name
64
+
65
+ if Sequel.respond_to?(:pg_json)
66
+ if respond_to?(:jsonb)
67
+ jsonb :cached_ballot_summary
68
+ else
69
+ json :cached_ballot_summary
70
+ end
71
+ else
72
+ String :cached_ballot_summary
73
+ end
74
+ end
75
+
76
+ require 'ballot/sequel'
77
+
78
+ class SequelVoter < Sequel::Model(:voters)
79
+ plugin :ballot_voter
80
+ end
81
+
82
+ class SequelNotVoter < Sequel::Model(:not_voters)
83
+ end
84
+
85
+ class SequelVotable < Sequel::Model(:votables)
86
+ plugin :ballot_votable
87
+ end
88
+
89
+ class SequelNotVotable < Sequel::Model(:not_votables)
90
+ end
91
+
92
+ class SequelVotableVoter < Sequel::Model(:votable_voters)
93
+ plugin :ballot_voter
94
+ plugin :ballot_votable
95
+ end
96
+
97
+ class SequelStiVotable < Sequel::Model(:sti_votables)
98
+ plugin :single_table_inheritance, :type
99
+ plugin :ballot_votable
100
+ end
101
+
102
+ class SequelChildOfStiVotable < SequelStiVotable
103
+ end
104
+
105
+ class SequelStiNotVotable < Sequel::Model(:sti_not_votables)
106
+ plugin :single_table_inheritance, :type
107
+ end
108
+
109
+ class SequelVotableChildOfStiNotVotable < SequelStiNotVotable
110
+ plugin :ballot_votable
111
+ end
112
+
113
+ class SequelVotableCache < Sequel::Model(:votable_caches)
114
+ plugin :ballot_votable
115
+ end
116
+
117
+ class SequelABoringClass
118
+ end
119
+
120
+ class Minitest::SequelSpec < Minitest::HooksSpec
121
+ parallelize_me! unless RUBY_ENGINE == 'jruby'
122
+
123
+ register_spec_type(/Sequel/, self)
124
+
125
+ def around
126
+ Sequel::Model.db.transaction(rollback: :always, auto_savepoint: true) { super }
127
+ end
128
+
129
+ def capture_sql
130
+ SQLLogger.clear
131
+ yield
132
+ SQLLogger.sqls.dup
133
+ ensure
134
+ SQLLogger.clear
135
+ end
136
+
137
+ def votable_dataset(votable)
138
+ votable.ballots_for_dataset
139
+ end
140
+
141
+ def voter_dataset(voter)
142
+ voter.ballots_by_dataset
143
+ end
144
+
145
+ def ballot_type_name(item)
146
+ Ballot::Sequel.type_name(item)
147
+ end
148
+
149
+ let(:voter) { SequelVoter.create(name: 'I can vote!') }
150
+ let(:voter2) { SequelVoter.create(name: 'I, too, can vote!') }
151
+ let(:not_voter) { SequelNotVoter.create(name: 'I cannot vote!') }
152
+
153
+ let(:votable) { SequelVotable.create(name: 'a votable model') }
154
+ let(:votable2) { SequelVotable.create(name: 'a second votable model') }
155
+ let(:votable_cache) { SequelVotableCache.create(name: 'a votable model with caching') }
156
+ let(:sti_votable) { SequelStiVotable.create(name: 'a votable STI model') }
157
+ let(:child_of_sti_votable) {
158
+ SequelChildOfStiVotable.create(name: 'a votable STI child model')
159
+ }
160
+ let(:votable_child_of_sti_not_votable) {
161
+ SequelVotableChildOfStiNotVotable.create(name: 'a votable STI child of a non-votable')
162
+ }
163
+ let(:not_votable) { SequelNotVotable.create(name: 'a non-votable model') }
164
+ end