视频表
id
title
votes_count
视频控制器def show
@video = Video.find(params[:id])
@next_video = Video.order("votes_count DESC").where("votes_count < ?", @video.votes_count).first
@previous_video = Video.order("votes_count ASC").where("votes_count > ?", @video.votes_count).first
end
问题是有视频具有相同的votes_count数。当我改变votes_count<到votes_count><=它开始在两个视频之间循环。什么好主意吗?谢谢。到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
注意,我还没有测试过它,所以它可能有bug。
你需要阻止它返回相同的视频
@next_video = Video.order("votes_count DESC").where("votes_count < ? AND id !=", @video.votes_count, @video.id).first
您可能还应该添加二级排序(可能是通过id或created_at),以便在投票数量相等时顺序一致。