rails上的下一个对象问题
video表
id title votes_count
video控制器
def show @video = Video.find(params[:id]) @next_video = Video.order("votes_count DESC").where("votes_count ?", @video.votes_count).first end
问题是有些video具有相同的votes_count数。 当我更改votes_count <to votes_count <=时,它开始在两个视频之间循环。 有任何想法吗? 谢谢。
解决此问题的主要关键是您需要显式包含辅助排序字段,这将使您确定解决具有相同votes_count
的行的问题。 您还需要将>=
拆分为两个单独的子句,因为您只想在主要=
时评估辅助字段。
现在,对于奖励积分,我还要将您的代码重构为模型上的方法,因此您的控制器就变得……
def show @video = Video.find params[:id] end
而你的模型变成……
def next self.class. order( "votes_count, id" ). where( "votes_count > :votes_count OR ( votes_count = :votes_count AND id > :id )", attributes.symbolize_keys ).first end def previous self.class. order( "votes_count DESC, id DESC" ). where( "votes_count < :votes_count OR ( votes_count = :votes_count AND id < :id )", attributes.symbolize_keys ).first end
现在在您看来,您可以参考@video.next
和@video.previous
让我们在你的Video
模型中添加一些新东西:
class Video < ActiveRecord::Base def next(column = 'votes_count', order = 'DESC') pos = self.position(column, order) on_position(pos - 1, column, order) if pos > 0 end def previous(column = 'votes_count', order = 'DESC') pos = self.position(column, order) on_position(pos + 1, column, order) end private def position(column, order) order_by = "#{column} #{order}" arrow = order.capitalize == "ASC" ? "<=" : "=>" Video.where("#{column} #{arrow} (?)", self.send(column)).order(order_by).count end def on_position(pos, column, order) order_by = "#{column} #{order}" arrow = order.capitalize == "ASC" ? "<=" : "=>" Video.order(order_by).offset(pos).first end end
和你的控制器
def show @video = Video.find(params[:id]) @next_video = @video.next @previous_video = @video.previous end
注意,我没有测试它,所以它可能是错误的。 所有错误都放在评论中:)
您需要阻止它返回相同的video
@next_video = Video.order("votes_count DESC").where("votes_count < ? AND id !=", @video.votes_count, @video.id).first
您还应该添加二级排序(可能通过id或created_at),以便在投票数相等时订单是一致的。