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.
- checksums.yaml +7 -0
- data/Contributing.md +68 -0
- data/History.md +5 -0
- data/Licence.md +27 -0
- data/Manifest.txt +68 -0
- data/README.rdoc +264 -0
- data/Rakefile +71 -0
- data/bin/ballot_generator +9 -0
- data/lib/ballot.rb +25 -0
- data/lib/ballot/action_controller.rb +32 -0
- data/lib/ballot/active_record.rb +152 -0
- data/lib/ballot/active_record/votable.rb +145 -0
- data/lib/ballot/active_record/vote.rb +35 -0
- data/lib/ballot/active_record/voter.rb +99 -0
- data/lib/ballot/railtie.rb +19 -0
- data/lib/ballot/sequel.rb +170 -0
- data/lib/ballot/sequel/vote.rb +99 -0
- data/lib/ballot/votable.rb +445 -0
- data/lib/ballot/vote.rb +129 -0
- data/lib/ballot/voter.rb +320 -0
- data/lib/ballot/words.rb +32 -0
- data/lib/generators/ballot.rb +40 -0
- data/lib/generators/ballot/install/install_generator.rb +27 -0
- data/lib/generators/ballot/install/templates/active_record/migration.rb +19 -0
- data/lib/generators/ballot/install/templates/sequel/migration.rb +25 -0
- data/lib/generators/ballot/standalone.rb +89 -0
- data/lib/generators/ballot/standalone/support.rb +70 -0
- data/lib/generators/ballot/summary/summary_generator.rb +27 -0
- data/lib/generators/ballot/summary/templates/active_record/migration.rb +15 -0
- data/lib/generators/ballot/summary/templates/sequel/migration.rb +20 -0
- data/lib/sequel/plugins/ballot_votable.rb +180 -0
- data/lib/sequel/plugins/ballot_voter.rb +125 -0
- data/test/active_record/ballot_votable_test.rb +16 -0
- data/test/active_record/ballot_voter_test.rb +13 -0
- data/test/active_record/rails_generator_test.rb +28 -0
- data/test/active_record/votable_voter_test.rb +19 -0
- data/test/generators/rails-activerecord/Rakefile +2 -0
- data/test/generators/rails-activerecord/app/.keep +0 -0
- data/test/generators/rails-activerecord/bin/rails +5 -0
- data/test/generators/rails-activerecord/config/application.rb +17 -0
- data/test/generators/rails-activerecord/config/boot.rb +3 -0
- data/test/generators/rails-activerecord/config/database.yml +12 -0
- data/test/generators/rails-activerecord/config/environment.rb +3 -0
- data/test/generators/rails-activerecord/config/routes.rb +3 -0
- data/test/generators/rails-activerecord/config/secrets.yml +5 -0
- data/test/generators/rails-activerecord/db/seeds.rb +1 -0
- data/test/generators/rails-activerecord/log/.keep +0 -0
- data/test/generators/rails-sequel/Rakefile +2 -0
- data/test/generators/rails-sequel/app/.keep +0 -0
- data/test/generators/rails-sequel/bin/rails +5 -0
- data/test/generators/rails-sequel/config/application.rb +14 -0
- data/test/generators/rails-sequel/config/boot.rb +3 -0
- data/test/generators/rails-sequel/config/database.yml +12 -0
- data/test/generators/rails-sequel/config/environment.rb +3 -0
- data/test/generators/rails-sequel/config/routes.rb +3 -0
- data/test/generators/rails-sequel/config/secrets.yml +5 -0
- data/test/generators/rails-sequel/db/seeds.rb +1 -0
- data/test/generators/rails-sequel/log/.keep +0 -0
- data/test/minitest_config.rb +14 -0
- data/test/sequel/ballot_votable_test.rb +45 -0
- data/test/sequel/ballot_voter_test.rb +42 -0
- data/test/sequel/rails_generator_test.rb +25 -0
- data/test/sequel/votable_voter_test.rb +19 -0
- data/test/sequel/vote_test.rb +105 -0
- data/test/support/active_record_setup.rb +145 -0
- data/test/support/generators_setup.rb +129 -0
- data/test/support/sequel_setup.rb +164 -0
- data/test/support/shared_examples/votable_examples.rb +630 -0
- data/test/support/shared_examples/voter_examples.rb +600 -0
- metadata +333 -0
data/lib/ballot/vote.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#--
|
4
|
+
# This file exists for documentation purposes only. Ballot::Vote is an optional
|
5
|
+
# constant, and may be one of these values:
|
6
|
+
#
|
7
|
+
# * Ballot::Sequel::Vote (when using *only* Sequel in an application);
|
8
|
+
# * Ballot::ActiveRecord::Vote (when using *only* ActiveRecord in an application)
|
9
|
+
#++
|
10
|
+
unless defined?(Ballot::Sequel::Vote) || defined?(Ballot::ActiveRecord::Vote)
|
11
|
+
fail 'ballot/vote cannot be required directly'
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
module Ballot
|
16
|
+
# A Vote represents the votes stored in the +ballot_votes+ table, holding
|
17
|
+
# votes for Votable objects by Voter objects.
|
18
|
+
#
|
19
|
+
# \ActiveRecord:: This is implemented as the Ballot::ActiveRecord::Vote
|
20
|
+
# class.
|
21
|
+
# \Sequel:: This is implemented as the Ballot::Sequel::Vote class.
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# NOTE:: Ballot::Vote is implemented as a method returning the primary
|
25
|
+
# implementation of the vote class. If _only_ Ballot::Sequel::Vote is
|
26
|
+
# defined, it will be returned. If _only_ Ballot::ActiveRecord::Vote
|
27
|
+
# is defined, it will be returned. If _both_ are defined, +nil+ will
|
28
|
+
# be returned.
|
29
|
+
class Vote
|
30
|
+
#-----
|
31
|
+
# :section: Scope / Dataset Methods
|
32
|
+
#-----
|
33
|
+
|
34
|
+
##
|
35
|
+
# Returns all positive votes.
|
36
|
+
#
|
37
|
+
# \ActiveRecord:: This is a scope.
|
38
|
+
# \Sequel:: This is a dataset module subset.
|
39
|
+
def self.up; end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Returns all negative votes.
|
43
|
+
#
|
44
|
+
# \ActiveRecord:: This is a scope.
|
45
|
+
# \Sequel:: This is a dataset module subset.
|
46
|
+
def self.down; end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Returns all votes for Votable objects of the provided +model_class+. The
|
50
|
+
# +model_class+ is resolved to the canonical name for the model, which
|
51
|
+
# differs if the model is STI-enabled.
|
52
|
+
#
|
53
|
+
# \ActiveRecord:: This is a scope.
|
54
|
+
# \Sequel:: This is a dataset module method.
|
55
|
+
def self.for_type(model_class); end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Returns all votes for Voter objects of the provided +model_class+. The
|
59
|
+
# +model_class+ is resolved to the canonical name for the model, which
|
60
|
+
# differs if the model is STI-enabled.
|
61
|
+
#
|
62
|
+
# \ActiveRecord:: This is a scope.
|
63
|
+
# \Sequel:: This is a dataset module method.
|
64
|
+
def self.by_type(model_class); end
|
65
|
+
|
66
|
+
#-----
|
67
|
+
# :section:
|
68
|
+
#-----
|
69
|
+
|
70
|
+
##
|
71
|
+
# :attr_accessor: voter_id
|
72
|
+
# The id of the Voter record for this Vote.
|
73
|
+
|
74
|
+
##
|
75
|
+
# :attr_accessor: voter_type
|
76
|
+
# The canonical model name for the Voter record for this Vote.
|
77
|
+
|
78
|
+
##
|
79
|
+
# :attr_accessor: votable_id
|
80
|
+
# The id of the Votable record for this Vote.
|
81
|
+
|
82
|
+
##
|
83
|
+
# :attr_accessor: votable_type
|
84
|
+
# The canonical model name for the Votable record for this Vote.
|
85
|
+
|
86
|
+
##
|
87
|
+
# :attr_accessor: vote
|
88
|
+
# The state of the Vote; +true+ if a positive vote, +false+ if a negative
|
89
|
+
# vote.
|
90
|
+
|
91
|
+
##
|
92
|
+
# :attr_accessor: scope
|
93
|
+
# The optional scope for this Vote.
|
94
|
+
|
95
|
+
##
|
96
|
+
# :attr_accessor: weight
|
97
|
+
# The optional weight for this Vote. If missing, defaults to 1, but may be
|
98
|
+
# any integer value.
|
99
|
+
|
100
|
+
##
|
101
|
+
# :attr_reader: created_at
|
102
|
+
# When this Vote record was created.
|
103
|
+
|
104
|
+
##
|
105
|
+
# :attr_reader: updated_at
|
106
|
+
# When this Vote record was last updated.
|
107
|
+
|
108
|
+
##
|
109
|
+
# :attr_accessor: voter
|
110
|
+
# The associated Voter for this Vote. Determined from #voter_id and
|
111
|
+
# #voter_type.
|
112
|
+
|
113
|
+
##
|
114
|
+
# :attr_accessor: votable
|
115
|
+
# The associated Votable for this Vote. Determined from #votable_id and
|
116
|
+
# #votable_type.
|
117
|
+
end
|
118
|
+
remove_const :Vote
|
119
|
+
|
120
|
+
#--
|
121
|
+
def self.Vote # :nodoc:
|
122
|
+
if defined?(Ballot::Sequel::Vote) && !defined?(Ballot::ActiveRecord::Vote)
|
123
|
+
Ballot::Sequel::Vote
|
124
|
+
elsif defined?(Ballot::ActiveRecord::Vote)
|
125
|
+
Ballot::ActiveRecord::Vote
|
126
|
+
end
|
127
|
+
end
|
128
|
+
#++
|
129
|
+
end
|
data/lib/ballot/voter.rb
ADDED
@@ -0,0 +1,320 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
module Ballot
|
5
|
+
# Methods added to a model that is marked as a Voter.
|
6
|
+
module Voter
|
7
|
+
#-----
|
8
|
+
# :section: Recording Votes
|
9
|
+
#-----
|
10
|
+
|
11
|
+
##
|
12
|
+
# :method: cast_ballot_for
|
13
|
+
# :call-seq:
|
14
|
+
# cast_ballot_for(votable = nil, kwargs = {})
|
15
|
+
# cast_ballot_for(votable)
|
16
|
+
# cast_ballot_for(votable_id: id, votable_type: type)
|
17
|
+
# cast_ballot_for(votable_gid: gid)
|
18
|
+
# cast_ballot_for(votable, scope: scope, vote: false, weight: true)
|
19
|
+
#
|
20
|
+
# Record a Vote for this Voter on the provided +votable+. The +votable+ may
|
21
|
+
# be specified as its own parameter, or through the keyword arguments
|
22
|
+
# +votable_id+, +votable_type+, +votable_gid+, or +votable+ (note that the
|
23
|
+
# parameter +votable+ will override the keyword argument +votable+, if both
|
24
|
+
# are provided).
|
25
|
+
#
|
26
|
+
# Additional named arguments may be provided through +kwargs+:
|
27
|
+
#
|
28
|
+
# scope:: The scope of the vote to be recorded. Defaults to +nil+.
|
29
|
+
# vote:: The vote to be recorded. Defaults to +true+ and is parsed through
|
30
|
+
# Ballot::Words.truthy?.
|
31
|
+
# weight:: The weight of the vote to be recorded. Defaults to +1+.
|
32
|
+
# duplicate:: Allow a duplicate vote to be recorded. This is not
|
33
|
+
# recommended as it has negative performance implications at
|
34
|
+
# scale.
|
35
|
+
#
|
36
|
+
# Other arguments are ignored.
|
37
|
+
#
|
38
|
+
# \ActiveRecord:: There are no special notes for ActiveRecord.
|
39
|
+
# \Sequel:: GlobalID does not currently provide support for Sequel. The use
|
40
|
+
# of +votable_gid+ in this case will probably fail.
|
41
|
+
#
|
42
|
+
# <em>Also aliased as: #ballot_for.</em>
|
43
|
+
|
44
|
+
##
|
45
|
+
# :method: ballot_for
|
46
|
+
# :call-seq:
|
47
|
+
# ballot_for(votable = nil, kwargs = {})
|
48
|
+
# ballot_for(votable)
|
49
|
+
# ballot_for(votable_id: id, votable_type: type)
|
50
|
+
# ballot_for(votable_gid: gid)
|
51
|
+
# ballot_for(votable, scope: scope, vote: false, weight: true)
|
52
|
+
#
|
53
|
+
# <em>Alias for: #cast_ballot_for.</em>
|
54
|
+
|
55
|
+
##
|
56
|
+
# Records a positive vote by this Voter on the provided +votable+ with
|
57
|
+
# options provided in +kwargs+. Any value passed to the +vote+ keyword
|
58
|
+
# argument will be ignored. See #cast_ballot_for for more details.
|
59
|
+
def cast_up_ballot_for(votable = nil, kwargs = {})
|
60
|
+
cast_ballot_for(votable, kwargs.merge(vote: true))
|
61
|
+
end
|
62
|
+
alias up_ballot_for cast_up_ballot_for
|
63
|
+
|
64
|
+
##
|
65
|
+
# Records a negative vote by this Voter on the provided +votable+ with
|
66
|
+
# options provided in +kwargs+. Any value passed to the +vote+ keyword
|
67
|
+
# argument will be ignored. See #cast_ballot_for for more details.
|
68
|
+
def cast_down_ballot_for(votable = nil, kwargs = {})
|
69
|
+
cast_ballot_for(votable, kwargs.merge(vote: false))
|
70
|
+
end
|
71
|
+
alias down_ballot_for cast_down_ballot_for
|
72
|
+
|
73
|
+
##
|
74
|
+
# :method: remove_ballot_for
|
75
|
+
# :call-seq:
|
76
|
+
# remove_ballot_for(votable = nil, kwargs = {})
|
77
|
+
# remove_ballot_for(votable)
|
78
|
+
# remove_ballot_for(votable_id: id, votable_type: type)
|
79
|
+
# remove_ballot_for(votable_gid: gid)
|
80
|
+
# remove_ballot_for(votable, scope: scope)
|
81
|
+
#
|
82
|
+
# Remove any votes by this Voter for the provided +votable+. The +votable+
|
83
|
+
# may be specified as its own parameter, or through the keyword arguments
|
84
|
+
# +votable_id+, +votable_type+, +votable_gid+, or +votable+ (note that the
|
85
|
+
# parameter +votable+ will override the keyword argument +votable+, if both
|
86
|
+
# are provided).
|
87
|
+
#
|
88
|
+
# Only the +scope+ argument is available through +kwargs+:
|
89
|
+
#
|
90
|
+
# scope:: The scope of the vote to be recorded. Defaults to +nil+.
|
91
|
+
#
|
92
|
+
# Other arguments are ignored.
|
93
|
+
#
|
94
|
+
# \ActiveRecord:: There are no special notes for \ActiveRecord.
|
95
|
+
# \Sequel:: GlobalID does not currently provide support for \Sequel, so
|
96
|
+
# there are many cases where attempting to use +votable_gid+ will
|
97
|
+
# fail.
|
98
|
+
|
99
|
+
#-----
|
100
|
+
# :section: Finding Votes
|
101
|
+
#-----
|
102
|
+
|
103
|
+
##
|
104
|
+
# :method: ballots_by
|
105
|
+
#
|
106
|
+
# The votes attached to this Votable.
|
107
|
+
#
|
108
|
+
# \ActiveRecord:: This is generated by the polymorphic association
|
109
|
+
# <tt>has_many :ballots_by</tt>.
|
110
|
+
# \Sequel:: This is generated by the polymorphic association
|
111
|
+
# <tt>one_to_many :ballots_by</tt>
|
112
|
+
|
113
|
+
##
|
114
|
+
# :method: ballots_for_dataset
|
115
|
+
#
|
116
|
+
# The \Sequel association dataset for votes attached to this Voter.
|
117
|
+
#
|
118
|
+
# \ActiveRecord:: This does not exist for \ActiveRecord.
|
119
|
+
# \Sequel:: This is generated by the polymorphic association
|
120
|
+
# <tt>one_to_many :ballots_for</tt>
|
121
|
+
|
122
|
+
##
|
123
|
+
# Returns ballots by this Voter where the recorded vote is positive.
|
124
|
+
#
|
125
|
+
# \ActiveRecord:: There are no special notes for ActiveRecord.
|
126
|
+
# \Sequel:: This method returns the _dataset_; if vote objects are desired,
|
127
|
+
# use <tt>up_ballots_by.all</tt>.
|
128
|
+
def up_ballots_by(kwargs = {})
|
129
|
+
find_ballots_by(vote: true, scope: kwargs[:scope])
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Returns ballots by this Voter where the recorded vote is negative.
|
134
|
+
#
|
135
|
+
# \ActiveRecord:: There are no special notes for ActiveRecord.
|
136
|
+
# \Sequel:: This method returns the _dataset_; if vote objects are desired,
|
137
|
+
# use <tt>down_ballots_by.all</tt>.
|
138
|
+
def down_ballots_by(kwargs = {})
|
139
|
+
find_ballots_by(vote: false, scope: kwargs[:scope])
|
140
|
+
end
|
141
|
+
|
142
|
+
#-----
|
143
|
+
# :section: Votable Inquiries
|
144
|
+
#-----
|
145
|
+
|
146
|
+
##
|
147
|
+
# :method: cast_ballot_for?
|
148
|
+
# :call-seq:
|
149
|
+
# ballot_for?(votable = nil, kwargs = {})
|
150
|
+
# ballot_for?(votable)
|
151
|
+
# ballot_for?(votable_id: id, votable_type: type)
|
152
|
+
# ballot_for?(votable_gid: gid)
|
153
|
+
# ballot_for?(votable, scope: scope, vote: false, weight: true)
|
154
|
+
#
|
155
|
+
# Returns +true+ if this Voter has voted for the provided +votable+
|
156
|
+
# matching the provided criteria. The +votable+ may be specified as its own
|
157
|
+
# parameter, or through the keyword arguments +votable_id+, +votable_type+,
|
158
|
+
# +votable_gid+, or +votable+ (note that the parameter +votable+ will
|
159
|
+
# override the keyword argument +votable+, if both are provided).
|
160
|
+
#
|
161
|
+
# Additional named arguments may be provided through +kwargs+:
|
162
|
+
#
|
163
|
+
# scope:: The scope of the vote to be recorded. Defaults to +nil+.
|
164
|
+
# vote:: The vote to be queried. If present, is parsed through
|
165
|
+
# Ballot::Words.truthy?.
|
166
|
+
#
|
167
|
+
# Other arguments are ignored.
|
168
|
+
#
|
169
|
+
# \ActiveRecord:: There are no special notes for ActiveRecord.
|
170
|
+
# \Sequel:: GlobalID does not currently provide support for Sequel. The use
|
171
|
+
# of +votable_gid+ in this case will probably fail.
|
172
|
+
#
|
173
|
+
# <em>Also aliased as: #ballot_for?.</em>
|
174
|
+
|
175
|
+
##
|
176
|
+
# :method: ballot_for?
|
177
|
+
# :call-seq:
|
178
|
+
# ballot_for?(votable = nil, kwargs = {})
|
179
|
+
# ballot_for?(votable)
|
180
|
+
# ballot_for?(votable_id: id, votable_type: type)
|
181
|
+
# ballot_for?(votable_gid: gid)
|
182
|
+
# ballot_for?(votable, scope: scope, vote: false, weight: true)
|
183
|
+
#
|
184
|
+
# <em>Alias for: #cast_ballot_for?.</em>
|
185
|
+
|
186
|
+
##
|
187
|
+
# Returns +true+ if this Voter has made positive votes for the provided
|
188
|
+
# +votable+. Any value passed to the +vote+ keyword argument will be
|
189
|
+
# ignored. See #cast_ballot_for? for more details.
|
190
|
+
def cast_up_ballot_for?(votable = nil, kwargs = {})
|
191
|
+
cast_ballot_for?(votable, kwargs.merge(vote: true))
|
192
|
+
end
|
193
|
+
alias up_ballot_for? cast_up_ballot_for?
|
194
|
+
|
195
|
+
##
|
196
|
+
# Returns +true+ if this Voter has made negative votes for the provided
|
197
|
+
# +votable+. Any value passed to the +vote+ keyword argument will be
|
198
|
+
# ignored. See #cast_ballot_for? for more details.
|
199
|
+
def cast_down_ballot_for?(votable = nil, kwargs = {})
|
200
|
+
cast_ballot_for?(votable, kwargs.merge(vote: false))
|
201
|
+
end
|
202
|
+
alias down_ballot_for? cast_down_ballot_for?
|
203
|
+
|
204
|
+
##
|
205
|
+
# :method: ballot_as_cast_for
|
206
|
+
# :call-seq:
|
207
|
+
# ballot_as_cast_for(votable = nil, kwargs = {})
|
208
|
+
# ballot_as_cast_for(votable)
|
209
|
+
# ballot_as_cast_for(votable_id: id, votable_type: type)
|
210
|
+
# ballot_as_cast_for(votable_gid: gid)
|
211
|
+
# ballot_as_cast_for(votable, scope: scope, vote: false, weight: true)
|
212
|
+
#
|
213
|
+
# Returns the Ballot::Vote#vote value of the ballot cast by this Voter
|
214
|
+
# against the provided +votable+. The +votable+ may be specified as its own
|
215
|
+
# parameter, or through the keyword arguments +votable_id+, +votable_type+,
|
216
|
+
# +votable_gid+, or +votable+ (note that the parameter +votable+ will
|
217
|
+
# override the keyword argument +votable+, if both are provided).
|
218
|
+
#
|
219
|
+
# If this Voter has not cast a ballot against the +votable+, returns +nil+.
|
220
|
+
#
|
221
|
+
# Additional named arguments may be provided through +kwargs+:
|
222
|
+
#
|
223
|
+
# scope:: The scope of the vote to be query. Defaults to +nil+.
|
224
|
+
# vote:: The vote to be queried. If present, is parsed through
|
225
|
+
# Ballot::Words.truthy?.
|
226
|
+
#
|
227
|
+
# Other arguments are ignored.
|
228
|
+
#
|
229
|
+
# \ActiveRecord:: There are no special notes for ActiveRecord.
|
230
|
+
# \Sequel:: GlobalID does not currently provide support for Sequel. The use
|
231
|
+
# of +votable_gid+ in this case will probably fail.
|
232
|
+
|
233
|
+
##
|
234
|
+
# :method: ballots_for_class(model_class, kwargs = {})
|
235
|
+
#
|
236
|
+
# Find ballots cast by this Voter matching the canonical name of the
|
237
|
+
# +model_class+ as the type of Votable.
|
238
|
+
#
|
239
|
+
# Additional named arguments may be provided through +kwargs+:
|
240
|
+
#
|
241
|
+
# scope:: The scope of the vote to be recorded. Defaults to +nil+.
|
242
|
+
# vote:: The vote to be queried. If present, is parsed through
|
243
|
+
# Ballot::Words.truthy?.
|
244
|
+
#
|
245
|
+
# Other arguments are ignored.
|
246
|
+
|
247
|
+
##
|
248
|
+
# Find positive ballots cast by this Voter matching the canonical name of
|
249
|
+
# the +model_class+ as the type of Votable. Any value passed to the +vote+
|
250
|
+
# keyword argument will be ignored. See #ballots_for_class for more
|
251
|
+
# details.
|
252
|
+
def up_ballots_for_class(model_class, kwargs = {})
|
253
|
+
ballots_for_class(model_class, kwargs.merge(vote: true))
|
254
|
+
end
|
255
|
+
|
256
|
+
##
|
257
|
+
# Find negative ballots cast by this Voter matching the canonical name of
|
258
|
+
# the +model_class+ as the type of Votable. Any value passed to the +vote+
|
259
|
+
# keyword argument will be ignored. See #ballots_for_class for more
|
260
|
+
# details.
|
261
|
+
def down_ballots_for_class(model_class, kwargs = {})
|
262
|
+
ballots_for_class(model_class, kwargs.merge(vote: false))
|
263
|
+
end
|
264
|
+
|
265
|
+
##
|
266
|
+
# Returns the Votable objects that this Voter has voted on. Additional
|
267
|
+
# query conditions may be specified in +conds+, or in the +block+ if
|
268
|
+
# supported by the ORM. The Voter objects are eager loaded to minimize the
|
269
|
+
# number of queries required to satisfy this request.
|
270
|
+
#
|
271
|
+
# \ActiveRecord:: Polymorphic eager loading is directly supported, using
|
272
|
+
# <tt>ballots_for.includes(:votable)</tt>. Normal
|
273
|
+
# +where+-clause conditions may be provided in +conds+.
|
274
|
+
# \Sequel:: Polymorphic eager loading is not supported by \Sequel, but has
|
275
|
+
# been implemented in Ballot for this method. Normal
|
276
|
+
# +where+-clause conditions may be provided in +conds+ or in
|
277
|
+
# +block+ for \Sequel virtual row support.
|
278
|
+
def ballot_votables(*conds, &block)
|
279
|
+
__eager_ballot_votables(find_ballots_by(*conds, &block))
|
280
|
+
end
|
281
|
+
|
282
|
+
##
|
283
|
+
# Returns the Votable objects that this Voter has made positive votes on.
|
284
|
+
# See #ballot_voters for how +conds+ and +block+ apply.
|
285
|
+
def ballot_up_votables(*conds, &block)
|
286
|
+
__eager_ballot_votables(
|
287
|
+
find_ballots_by(*conds, &block).where(vote: true)
|
288
|
+
)
|
289
|
+
end
|
290
|
+
|
291
|
+
##
|
292
|
+
# Returns the Votable objects that this Voter has made negative votes on.
|
293
|
+
# See #ballot_voters for how +conds+ and +block+ apply.
|
294
|
+
def ballot_down_votables(*conds, &block)
|
295
|
+
__eager_ballot_votables(
|
296
|
+
find_ballots_by(*conds, &block).where(vote: false)
|
297
|
+
)
|
298
|
+
end
|
299
|
+
|
300
|
+
private
|
301
|
+
|
302
|
+
def __ballot_voter_kwargs(votable, kwargs = {})
|
303
|
+
if votable.kind_of?(Hash)
|
304
|
+
kwargs.merge(votable)
|
305
|
+
elsif votable.nil?
|
306
|
+
kwargs
|
307
|
+
else
|
308
|
+
kwargs.merge(votable: votable)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
# Methods added to the Voter model class.
|
313
|
+
module ClassMethods
|
314
|
+
# The class is now a voter record.
|
315
|
+
def ballot_voter?
|
316
|
+
true
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
data/lib/ballot/words.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
##
|
6
|
+
module Ballot
|
7
|
+
# Methods to determine whether the value of the vote word in question is
|
8
|
+
# positive (#truthy?) or negative (#falsy?).
|
9
|
+
module Words
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# The list of 'words' recognized as falsy values for voting purposes. This
|
13
|
+
# set can be added to for localization purposes. Any word *not* in this
|
14
|
+
# list is considered truthy.
|
15
|
+
FALSY = Set.new(
|
16
|
+
[
|
17
|
+
'down', 'downvote', 'dislike', 'disliked', 'negative', 'no', 'bad',
|
18
|
+
'false', '0', '-1'
|
19
|
+
]
|
20
|
+
)
|
21
|
+
|
22
|
+
# Returns +true+ if the word supplied is not #falsy?.
|
23
|
+
def truthy?(word)
|
24
|
+
!falsy?(word)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns +true+ if the word supplied is in the FALSY set.
|
28
|
+
def falsy?(word)
|
29
|
+
FALSY.include?(word.to_s.downcase)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|