Module: VoteFu::Concerns::Voteable::InstanceMethods
- Defined in:
- lib/vote_fu/concerns/voteable.rb
Instance Method Summary collapse
-
#broadcast_vote_update(vote: nil, action: :updated) ⇒ Object
Broadcast vote updates via Turbo Streams and ActionCable.
- #decrement_vote_counters(value) ⇒ Object
-
#hot_score(gravity: nil) ⇒ Float
Reddit Hot ranking score.
-
#increment_vote_counters(value) ⇒ Object
Counter cache methods.
-
#percent_against(scope: nil) ⇒ Float
Percentage of downvotes.
-
#percent_for(scope: nil) ⇒ Float
Percentage of upvotes.
-
#plusminus(scope: nil) ⇒ Integer
Net score (upvotes minus downvotes) Uses counter cache if available.
- #update_vote_counters(old_value, new_value) ⇒ Object
-
#vote_stream_name(scope: nil) ⇒ Object
Subscribe to vote updates via ActionCable.
-
#voted_by?(voter, direction: nil, scope: nil) ⇒ Boolean
Check if a voter has voted on this item.
-
#voters(scope: nil) ⇒ Array<ActiveRecord::Base>
Get all voters who voted on this item.
-
#voters_against(scope: nil) ⇒ Array<ActiveRecord::Base>
Get voters who downvoted.
-
#voters_for(scope: nil) ⇒ Array<ActiveRecord::Base>
Get voters who upvoted.
-
#votes_against(scope: nil) ⇒ Integer
Count of downvotes.
-
#votes_count(scope: nil) ⇒ Integer
Total number of votes.
-
#votes_for(scope: nil) ⇒ Integer
Count of upvotes.
-
#votes_total(scope: nil) ⇒ Integer
Sum of all vote values.
-
#wilson_score(confidence: 0.95, scope: nil) ⇒ Float
Wilson Score Lower Bound.
Instance Method Details
#broadcast_vote_update(vote: nil, action: :updated) ⇒ Object
Broadcast vote updates via Turbo Streams and ActionCable
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/vote_fu/concerns/voteable.rb', line 264 def broadcast_vote_update(vote: nil, action: :updated) return unless [:broadcasts] # Turbo Streams broadcast if respond_to?(:broadcast_replace_to) broadcast_replace_to( [self, :votes], target: "#{self.class.name.underscore}_#{id}_vote_widget", partial: "vote_fu/votes/widget", locals: { voteable: self } ) end # ActionCable broadcast (for custom JS handling) if defined?(VoteFu::VotesChannel) VoteFu::VotesChannel.broadcast_vote_update(self, vote: vote, action: action) end end |
#decrement_vote_counters(value) ⇒ Object
227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/vote_fu/concerns/voteable.rb', line 227 def decrement_vote_counters(value) return unless [:counter_cache] updates = {} updates[:votes_count] = -1 if has_attribute?(:votes_count) updates[:votes_total] = -value if has_attribute?(:votes_total) updates[:upvotes_count] = -1 if has_attribute?(:upvotes_count) && value.positive? updates[:downvotes_count] = -1 if has_attribute?(:downvotes_count) && value.negative? self.class.update_counters(id, **updates) if updates.any? end |
#hot_score(gravity: nil) ⇒ Float
Reddit Hot ranking score
209 210 211 212 |
# File 'lib/vote_fu/concerns/voteable.rb', line 209 def hot_score(gravity: nil) gravity ||= VoteFu.configuration.hot_ranking_gravity VoteFu::Algorithms::RedditHot.call(self, gravity: gravity) end |
#increment_vote_counters(value) ⇒ Object
Counter cache methods
215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/vote_fu/concerns/voteable.rb', line 215 def increment_vote_counters(value) return unless [:counter_cache] updates = {} updates[:votes_count] = 1 if has_attribute?(:votes_count) updates[:votes_total] = value if has_attribute?(:votes_total) updates[:upvotes_count] = 1 if has_attribute?(:upvotes_count) && value.positive? updates[:downvotes_count] = 1 if has_attribute?(:downvotes_count) && value.negative? self.class.update_counters(id, **updates) if updates.any? end |
#percent_against(scope: nil) ⇒ Float
Percentage of downvotes
153 154 155 156 157 158 |
# File 'lib/vote_fu/concerns/voteable.rb', line 153 def percent_against(scope: nil) total = votes_count(scope: scope) return 0.0 if total.zero? (votes_against(scope: scope).to_f / total * 100).round(1) end |
#percent_for(scope: nil) ⇒ Float
Percentage of upvotes
143 144 145 146 147 148 |
# File 'lib/vote_fu/concerns/voteable.rb', line 143 def percent_for(scope: nil) total = votes_count(scope: scope) return 0.0 if total.zero? (votes_for(scope: scope).to_f / total * 100).round(1) end |
#plusminus(scope: nil) ⇒ Integer
Net score (upvotes minus downvotes) Uses counter cache if available
132 133 134 135 136 137 138 |
# File 'lib/vote_fu/concerns/voteable.rb', line 132 def plusminus(scope: nil) if has_attribute?(:votes_total) && scope.nil? read_attribute(:votes_total) || 0 else votes_for(scope: scope) - votes_against(scope: scope) end end |
#update_vote_counters(old_value, new_value) ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/vote_fu/concerns/voteable.rb', line 239 def update_vote_counters(old_value, new_value) return unless [:counter_cache] updates = {} if has_attribute?(:votes_total) updates[:votes_total] = new_value - old_value end if has_attribute?(:upvotes_count) old_up = old_value.positive? ? 1 : 0 new_up = new_value.positive? ? 1 : 0 updates[:upvotes_count] = new_up - old_up if new_up != old_up end if has_attribute?(:downvotes_count) old_down = old_value.negative? ? 1 : 0 new_down = new_value.negative? ? 1 : 0 updates[:downvotes_count] = new_down - old_down if new_down != old_down end self.class.update_counters(id, **updates) if updates.any? end |
#vote_stream_name(scope: nil) ⇒ Object
Subscribe to vote updates via ActionCable
284 285 286 287 |
# File 'lib/vote_fu/concerns/voteable.rb', line 284 def vote_stream_name(scope: nil) base = "vote_fu:#{self.class.name}:#{id}" scope.present? ? "#{base}:#{scope}" : base end |
#voted_by?(voter, direction: nil, scope: nil) ⇒ Boolean
Check if a voter has voted on this item
165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/vote_fu/concerns/voteable.rb', line 165 def voted_by?(voter, direction: nil, scope: nil) vote = received_votes.find_by(voter: voter, scope: scope) return false unless vote case direction when nil then true when :up, :positive then vote.up? when :down, :negative then vote.down? else false end end |
#voters(scope: nil) ⇒ Array<ActiveRecord::Base>
Get all voters who voted on this item
180 181 182 |
# File 'lib/vote_fu/concerns/voteable.rb', line 180 def voters(scope: nil) received_votes.with_scope(scope).includes(:voter).map(&:voter).uniq end |
#voters_against(scope: nil) ⇒ Array<ActiveRecord::Base>
Get voters who downvoted
194 195 196 |
# File 'lib/vote_fu/concerns/voteable.rb', line 194 def voters_against(scope: nil) received_votes.with_scope(scope).down.includes(:voter).map(&:voter).uniq end |
#voters_for(scope: nil) ⇒ Array<ActiveRecord::Base>
Get voters who upvoted
187 188 189 |
# File 'lib/vote_fu/concerns/voteable.rb', line 187 def voters_for(scope: nil) received_votes.with_scope(scope).up.includes(:voter).map(&:voter).uniq end |
#votes_against(scope: nil) ⇒ Integer
Count of downvotes
110 111 112 |
# File 'lib/vote_fu/concerns/voteable.rb', line 110 def votes_against(scope: nil) received_votes.with_scope(scope).down.count end |
#votes_count(scope: nil) ⇒ Integer
Total number of votes
117 118 119 |
# File 'lib/vote_fu/concerns/voteable.rb', line 117 def votes_count(scope: nil) received_votes.with_scope(scope).count end |
#votes_for(scope: nil) ⇒ Integer
Count of upvotes
103 104 105 |
# File 'lib/vote_fu/concerns/voteable.rb', line 103 def votes_for(scope: nil) received_votes.with_scope(scope).up.count end |
#votes_total(scope: nil) ⇒ Integer
Sum of all vote values
124 125 126 |
# File 'lib/vote_fu/concerns/voteable.rb', line 124 def votes_total(scope: nil) received_votes.with_scope(scope).sum(:value) end |
#wilson_score(confidence: 0.95, scope: nil) ⇒ Float
Wilson Score Lower Bound
202 203 204 |
# File 'lib/vote_fu/concerns/voteable.rb', line 202 def wilson_score(confidence: 0.95, scope: nil) VoteFu::Algorithms::WilsonScore.call(self, confidence: confidence, scope: scope) end |