我目前在我的应用程序中实现了一个投票系统,并且在我看来,我正在使用以下代码按票数对帖子进行排序:
<%= render @posts.sort_by { |post| post.votes.count }.reverse %>
我想按每个帖子的投票数排序,也不希望帖子超过 5 天。如何同时按票数和日期对帖子进行排序。
我目前在我的应用程序中实现了一个投票系统,并且在我看来,我正在使用以下代码按票数对帖子进行排序:
<%= render @posts.sort_by { |post| post.votes.count }.reverse %>
我想按每个帖子的投票数排序,也不希望帖子超过 5 天。如何同时按票数和日期对帖子进行排序。
这是错误的。您应该在数据库端进行所有排序操作。对于此示例,请考虑使用 Arel 创建复杂查询或考虑创建计数器缓存列。
您可以为您的帖子模型添加一个范围,例如:
scope :five_days_ago, lambda { where("created_at >= :date", :date => 5.days.ago) }
然后只需将您的渲染方法调整为以下内容:
<%= render @posts.five_days_ago.sort_by { |post| post.votes.count }.reverse %>
这假设您要保留正在使用的结构。显然,正如其他人所建议的那样,在数据库中完成所有操作是最好的做法。
卢卡索斯是对的。出于至少两个原因,最好将排序委托给数据库:
计数器缓存可能是最好的主意,但对于复杂的查询,让我试一试。在您的 Post 模型中:
class << self
def votes_descending
select('posts.*, count(votes.id) as vote_count').joins('LEFT OUTER JOIN votes on votes.post_id = posts.id').group_by('posts.id').order('votes_count desc')
end
def since(date)
where('created_at >= ?', date)
end
end
所以...
@posts = Post.votes_descending.since(5.days.ago)
事实上,让数据库进行排序会更好。我会做类似的事情
class Post < ActiveRecord::Base
default_scope :order => 'created_at DESC'
end
那么您将始终对您的帖子进行排序,如果我没记错的话,最后一个应该是您得到的第一个,这样就可以代替您的“反向”呼叫。然后,您可以使用上面发布的范围仅获取 5 天前的帖子。还要检查数据库中 created_at 列上是否有索引。你可以这样做
SHOW INDEX FROM posts
db 会比 ruby 快得多。
我想出了另一种方法,虽然我很感激你的帮助,它可能不是最干净的方法,但我做到了
def most
range = "created_at #{(7.days.ago.utc...Time.now.utc).to_s(:db)}"
@posts = Post.all(:conditions => range)
@title = "All Posts"
@vote = Vote.new(params[:vote])
respond_to do |format|
format.html
format.json { render :json => @users }
end
end
对于我的控制器
创建了 /most :to => 'posts#most' 的路线
并使用我认为的原始代码进行查看。
我知道这不是最好的方法,但我对编码还是很陌生,所以这是我能弄清楚的最好方法。