基于Rails的投票应用模型关联及用户单次投票校验方法咨询
实现用户投票唯一性校验的
voted_for?方法 嘿,这事儿不难,咱们一步步来搞定这个校验方法!根据你已经定义好的模型关联,咱们可以直接利用Rails的关联查询特性,快速实现高效的voted_for?方法。
方法实现(user.rb)
直接在user.rb中添加下面这个方法就可以了:
def voted_for?(poll) # 借助已有的through关联,查询用户是否有属于该投票的选项记录 vote_options.where(poll_id: poll.id).exists? end
如果你更倾向于通过votes关联来写(逻辑完全一致,只是写法不同),也可以用这个版本:
def voted_for?(poll) votes.joins(:vote_option).where(vote_options: { poll_id: poll.id }).exists? end
为什么这么写?
- 复用现有关联:你已经在
user.rb里定义了has_many :vote_options, through: :votes,直接通过这个关联查询属于目标投票的记录就行,不用额外写复杂的原生SQL。 - 性能拉满:用
exists?而不是any?或者present?,是因为exists?会生成SELECT 1 FROM ... LIMIT 1的轻量SQL,数据库只需要判断是否存在匹配记录,不需要加载所有关联数据,在投票数据量大的时候性能差异会很明显。
用法示例
你可以在控制器或者视图里这样调用这个方法:
# 控制器中判断当前用户是否已投票 if current_user.voted_for?(@poll) flash[:notice] = "你已经投过票啦!" redirect_to poll_path(@poll) else # 渲染投票表单 end
<!-- 视图中控制投票按钮的显示状态 --> <% if current_user.voted_for?(@poll) %> <button disabled class="disabled-btn">已投票</button> <% else %> <%= form_for [@poll, @vote] do |f| %> <!-- 渲染投票选项表单内容 --> <% end %> <% end %>
额外优化:给Poll添加投票者关联(可选)
如果你需要从Poll的角度快速判断用户是否投票,可以在poll.rb里添加反向关联:
has_many :votes, through: :vote_options has_many :voters, through: :votes, source: :user
之后就能用@poll.voters.exists?(current_user.id)来判断,但这种方式和用户端的方法性能差不多,看你的业务场景选择就行。
内容的提问来源于stack exchange,提问作者catmal
相关产品推荐
相关产品推荐

