Rails使用acts_as_votable如何查询指定vote_scope的投票权重分值
Rails使用acts_as_votable实现多维度评分后查询用户打分值的方法
问题背景
我在Rails应用中使用acts_as_votable gem,为用户提供在不同维度下对资源进行1-5分评分的功能,比如用户可以对场馆的位置、价格等维度分别独立打出1-5分的评分。目前我已经实现了检查用户是否对指定维度完成投票的功能,但不知道如何同时查询用户此次投票对应的vote_weight,也就是用户实际给出的是1/2/3/4/5中的哪个分值。
现有代码参考
检查用户是否在指定维度投票的视图代码
<% if (user_signed_in?) && (current_user.voted_for? @stadium, :vote_scope => 'location') %> <p>Current user has rated the location for this Stadium</p> <% else %> <p>Current user has NOT rated the location for this Stadium</p> <% end %>
投票提交视图代码
<%= link_to like_stadium_path(@stadium, :score => 1, :vote_scope => 'location'), method: :put do %> <button class="mt-4 w-full border-primary-500 border border-transparent rounded-md py-3 px-8 flex items-center justify-center text-base font-medium text-primary-500 hover:bg-primary-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"> Vote 1 </button> <% end %> <%= link_to like_stadium_path(@stadium, :score => 2, :vote_scope => 'location'), method: :put do %> <button class="mt-4 w-full border-primary-500 border border-transparent rounded-md py-3 px-8 flex items-center justify-center text-base font-medium text-primary-500 hover:bg-primary-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"> Vote 2 </button> <% end %> <%= link_to like_stadium_path(@stadium, :score => 3, :vote_scope => 'location'), method: :put do %> <button class="mt-4 w-full border-primary-500 border border-transparent rounded-md py-3 px-8 flex items-center justify-center text-base font-medium text-primary-500 hover:bg-primary-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"> Vote 3 </button> <% end %> <%= link_to like_stadium_path(@stadium, :score => 4, :vote_scope => 'location'), method: :put do %> <button class="mt-4 w-full border-primary-500 border border-transparent rounded-md py-3 px-8 flex items-center justify-center text-base font-medium text-primary-500 hover:bg-primary-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"> Vote 4 </button> <% end %> <%= link_to like_stadium_path(@stadium, :score => 5, :vote_scope => 'location'), method: :put do %> <button class="mt-4 w-full border-primary-500 border border-transparent rounded-md py-3 px-8 flex items-center justify-center text-base font-medium text-primary-500 hover:bg-primary-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"> Vote 5 </button> <% end %>
stadiums_controller.rb 代码
def upvote @stadium.upvote_by current_user, :vote_scope => params[:vote_scope], :vote_weight => params[:score] redirect_back(fallback_location: root_path) end def downvote # 删除数据库中的投票记录 @stadium.unliked_by current_user, :vote_scope => params[:vote_scope] redirect_back(fallback_location: root_path) end
routes.rb 代码
resources :stadiums do member do put "like", to: "stadiums#upvote" put "unvote", to: "stadiums#downvote" end end
解决方案
你可以直接通过votes_for关联查询指定条件的投票记录,直接取出vote_weight值,有两种常用写法:
- 从用户侧查询
# 直接获取当前用户在指定维度下对场馆的打分值,未投票返回nil user_score = current_user.find_votes_for(votable: @stadium, vote_scope: 'location').first&.vote_weight
- 从资源侧查询
# 写法更简洁,直接返回对应分值,未投票返回nil user_score = @stadium.votes_for.where(voter: current_user, vote_scope: 'location').pick(:vote_weight)
你可以把逻辑整合到原有的视图代码中,直接展示用户的打分:
<% if user_signed_in? %> <% user_score = @stadium.votes_for.where(voter: current_user, vote_scope: 'location').pick(:vote_weight) %> <% if user_score %> <p>你已为该场馆的位置打分:<%= user_score %> 分</p> <% else %> <p>你还没有为该场馆的位置打分</p> <% end %> <% end %>
内容的提问来源于stack exchange,提问作者tommers
相关产品推荐
相关产品推荐

