2017-08-03 243 views
0

我的應用程序是gem acts_as_votable。用戶創建的每篇文章都有upvotes和downvotes。Ruby On Rails用戶排名

我在測試和Postgresql上使用Sqlite3開發,生產。

posts_controller.rb

class PostsController < ApplicationController 

def upvote 
@post = Post.find(params[:id]) 
@post.liked_by current_user 
redirect_to posts_path 
end 

def downvote 
@post = Post.find(params[:id]) 
@post.downvote_from current_user 
redirect_to posts_path 
end 
end 

users_controller.rb

class UsersController < ApplicationController 

def ranking 
    @users = User.all 
end 

end 

的routes.rb

Rails.application.routes.draw do 

resources :posts do 

member do 

    put "like" => "posts#upvote" 
    put "unlike" => "posts#downvote" 

end 

end 

ranking.html.erb

<% @users.each_with_index do |user,index| %> 

<div class="panel panel-default col-md-offset-4 col-md-4 right"> 

<div class="center"> 

    <h4><b>#<%= index+1 %><b></h4> 

</div> 


<ul class="nav navbar-nav navbar-left margin-left"> 

    <%if user.banned? %> 
    <h5 class="red left">[BANNED]</h5> 
    <%end%> 
    <h4> <%=link_to user.name, user%></h4> 

</ul> 
<ul class="nav navbar-nav navbar-right margin-right"> 

    <h4>Points:<%= user.posts.sum(&:cached_votes_score)%></h4> 

</ul> 

有沒有一種簡單的方法來創建一個按帖子排序的用戶排名?

+0

你用什麼數據庫? –

+0

sqlite3在生產,開發測試和postgre上 – Michal

回答

0

入住此AR查詢:

Post.group(user_id).order('sum_votes DESC').sum(:votes_for) 

可能需要做一些修改

0

PostgreSQL依賴的解決方案基於window functions

# ROW_NUMBER() OVER(ORDER BY votes_sum DESC, id ASC) - 1, 2, 3, 4, 5 
# DENSE_RANK() OVER(ORDER BY votes_sum DESC)   - 1, 1, 2, 2, 3 
# RANK()  OVER(ORDER BY votes_sum DESC)   - 1, 1, 3, 3, 5 

select_clause = <<~SQL 
    users.*, 
    (
    DENSE_RANK() OVER(
     ORDER BY (
     SELECT SUM(cached_votes_score) FROM posts WHERE user_id = users.id 
    ) DESC 
    ) 
) as rank 
SQL 

@users = User.select(select_clause).to_a # .order('rank').to_a if needed 
@users.first.rank # 1 

更新

  • 您必須仔細選擇排名功能,具體取決於與具有相同點數的用戶相關的規則 。
  • 你必須緩存SUM(cached_votes_score)users表,以避免子選擇和加速查詢
0

我看了一下AR,做這樣的事情。

 @users= User.joins(:posts) 
    .order("sum(cached_votes_score) 
    DESC").group("name").distinct 

它的工作原理。

感謝Pavel和Lun4i