在我的rails应用程序中,对于每个用户,这就是我计算他们得分的方式:
<% comment_vote_count = @user.comments.map{|c| c.votes.count}.sum
comment_vote_count ||=0
comment_vote_count *= 2
final_score = comment_vote_count + @user.base_score %>
这只是在某些视图中呈现,并未在任何地方保存在数据库中。
我正在尝试按照最高分数到最低分数的顺序填充所有用户的列表,并对结果进行分页。
这就是我在控制器中所拥有的:
def user_list
@users = User.order("created_at DESC").paginate(:page => params[:page], :per_page => 10)
respond_to do |format|
format.html
end
end
在我的user_list视图中
<ol>
<%= render (@users) %>
</ol>
<%= will_paginate @users, :next_label => “next” , :previous_label => '', :class => "next_pagination" %>
如何根据分数呈现有序的用户列表?我应该将分数存储在数据库中吗?
答案 0 :(得分:2)
如果您使用PostGreSQL作为数据库后端并且不怕弄脏,那么您可以替换
@users = User.order("created_at DESC").paginate(:page => params[:page], :per_page => 10)
与
@users = User.select('u.*, 2 * case when count(v.id) is null then 0 else count(v.id) end + u.score as cnt')
.from('users u').joins('left join comments c on c.user_id = u.id')
.joins('left join votes v on v.comment_id = c.id')
.group('u.id').order('cnt desc').paginate(:page => params[:page], :per_page => 10)
我在Rails控制台和psql中的本地数据库上对此进行了测试,结果相同 - 用户按总分降序排序。生成的查询是
SELECT u.id, 2 * case when count(v.id) is null then 0 else count(c.votes) end + u.score as cnt
FROM users u
LEFT JOIN comments c on c.user_id = u.id
LEFT JOIN votes v on v.comment_id = c.id
GROUP BY u.id
ORDER BY cnt desc
执行您要查找的计算。 case
语句是必要的,因为在对所有NULL
求和时,PG返回0
而不是NULL
。
答案 1 :(得分:2)
Comment
属于User
,因此每次有人投票时,您都可以添加此评论所有者积分。我向用户添加了一列名为score
的ex :integer
,然后当有人投票时,您将更新此用户score
字段:
user = @comment.user
score = @comment.votes.count
user.score = score
user.save
然后通过score
列直接订阅用户:
User.order("score DESC")
如果是act_as_voteable gem
<强> Vote.rb 强>
after_create :add_score_to_user
def add_score_to_user
user = self.voteable.user # gets comment user as voteable is a comment
score = self.voteable.votes.count # votes count of a comment
user.score = score
user.save
# or user.update_attributes(score: score) instead of last 2 lines
end
如果您想在每次投票后只为用户评分添加一个点,则可以使用increment
:
def add_score_to_user
user = self.voteable.user # gets comment user as voteable is a comment
user.increment!(:score) # this will add +1 to user score for each vote
end
P.S。
rails g migration add_score_to_users score:integer
编辑迁移,将分数默认设置为0
,然后:
User.order("score DESC").order('id DESC')
答案 2 :(得分:2)
假设user.rb包含:
has_many :votes, through: :comments
您需要一个初始化器
require 'will_paginate/array'
但是控制器就像这样简单:
@users=User.all.map {|i| [i.votes.count,i]}.sort.reverse.paginate(:page => params[:page], :per_page => 10)
在你看来:
@users.each do |user|...
用户[0]是投票数量
user [1]包含您的字段(例如:user [1] .id等)