rails上的下一个对象问题

时间:2011-04-20 18:41:48

标签: ruby-on-rails ruby-on-rails-3

视频表

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数。当我改变v​​otes_count&lt;到votes_count&lt; =它开始在两个视频之间循环。有任何想法吗?感谢。

3 个答案:

答案 0 :(得分:3)

解决此问题的主要关键是您需要明确包含辅助排序字段,这样才能确保解决具有相同votes_count的行问题。您还需要将>=拆分为两个单独的子句,因为您只想在主要=时评估辅助字段。

现在,对于奖励积分,我还要将您的代码重构为模型上的方法,这样您的控制器就变得...... [/ p>

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

答案 1 :(得分:0)

让我们为您的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

注意,我还没有测试过,所以它可能是错误的。所有错误都放在评论中:)

答案 2 :(得分:0)

您需要阻止它返回相同的视频

@next_video = Video.order("votes_count DESC").where("votes_count < ? AND id !=", @video.votes_count, @video.id).first

您还应该添加二级排序(可能是id或created_at),以便在投票数相等时订单是一致的。