Rails投票应用:检测选项投票权重占比是否达50%
嘿,看起来你已经搞定了投票基础功能和权重计算的核心部分,现在要加个检测逻辑——判断当前投票里有没有选项的权重占比达到50%对吧?我给你梳理几个实用的实现思路,直接基于你现有的模型来调整:
首先先补全你没写完的VoteOption模型(假设它关联到一个投票主体,比如叫Poll,毕竟投票肯定是对应某个具体活动的):
# vote_option.rb class VoteOption < ApplicationRecord has_many :votes belongs_to :poll # 每个选项属于一个投票活动 end # 对应的Poll模型(如果还没建的话) class Poll < ApplicationRecord has_many :vote_options end
核心实现思路:在Poll模型里加检测方法
我们可以把检测逻辑封装在Poll模型里,这样调用起来非常直观,还能避免重复代码。
1. 先实现计算投票总权重的方法
总权重是所有参与该投票的用户权重之和,我们用SQL查询来保证效率:
class Poll < ApplicationRecord has_many :vote_options # 计算当前投票的总权重 def total_vote_weight # 缓存结果避免重复查询 @total_vote_weight ||= Vote.joins(vote_option: :poll) .where(polls: { id: id }) .sum('users.weight') end
2. 实现检测权重占比的方法
接下来判断有没有选项的权重占比≥50%,同时要处理**还没人投票(总权重为0)**的边界情况,避免除以0的错误:
# 检测是否有选项达到50%权重占比 def has_option_reached_majority? return false if total_vote_weight.zero? # 没人投票直接返回false # 一次性查询所有选项的权重,再逐个判断占比 vote_options.joins(:votes) .select('vote_options.id, SUM(users.weight) as option_weight') .group('vote_options.id') .pluck(:option_weight) .any? { |weight| weight.to_f / total_vote_weight >= 0.5 } end end
调用方式
在业务代码里,你只需要拿到对应的投票实例,直接调用方法就行:
@poll = Poll.find(params[:id]) if @poll.has_option_reached_majority? # 这里可以加后续逻辑,比如标记投票结束、给管理员发通知、展示结果弹窗等 @poll.update!(status: 'completed') end
可选:投票后自动检测
如果想在用户投票完成后立刻检测是否达标,可以给Vote模型加个回调:
class Vote < ApplicationRecord belongs_to :user belongs_to :vote_option after_save :check_poll_majority private def check_poll_majority poll = vote_option.poll if poll.has_option_reached_majority? # 执行你需要的后续操作 poll.update!(status: 'completed') end end end
注意:确保users表的weight字段是数值类型(比如integer或float),不然会出现计算错误哦~
内容的提问来源于stack exchange,提问作者catmal
相关产品推荐
相关产品推荐

