Rails获取上一个和下一个活动记录对象的最佳方式

Wil*_*ckl 14 activerecord ruby-on-rails

我需要使用Rails获取上一个和下一个活动记录对象.我做到了,但不知道这是否是正确的方法.

我得到了什么:

控制器:

@product = Product.friendly.find(params[:id])

order_list = Product.select(:id).all.map(&:id)

current_position = order_list.index(@product.id)

@previous_product = @collection.products.find(order_list[current_position - 1]) if order_list[current_position - 1]
@next_product = @collection.products.find(order_list[current_position + 1]) if order_list[current_position + 1]

@previous_product ||= Product.last
@next_product ||= Product.first
Run Code Online (Sandbox Code Playgroud)

product_model.rb

default_scope -> {order(:product_sub_group_id => :asc, :id => :asc)}
Run Code Online (Sandbox Code Playgroud)

所以,这里的问题是我需要进入我的数据库并获取所有这些ID以了解谁是前一个和下一个.

尝试使用gem order_query,但它对我不起作用,我注意到它进入数据库并按顺序获取所有记录,所以,这就是为什么我做了同样但只得到id.

我发现的所有解决方案都是简单的订单查询.按ID排序或类似优先级字段.

Rai*_*Guy 34

Product模型中写下这些方法:

class Product

  def next
    self.class.where("id > ?", id).first
  end

  def previous
    self.class.where("id < ?", id).last
  end

end
Run Code Online (Sandbox Code Playgroud)

现在你可以在你的控制器中做:

@product = Product.friendly.find(params[:id])

@previous_product = @product.next
@next_product = @product.previous
Run Code Online (Sandbox Code Playgroud)

请试一试,但未经测试.谢谢

  • 我投票支持Rails Guy的答案,但是想通过id以外的其他方式解决有关排序的问题,例如created_at.根据@Mogsdad和其他人的要求,我将答案改为评论.要通过created_at进行排序,请将建议的`next`方法的实现更改为包括:`self.class.where("created_at>?",created_at).order(created_at :: asc).first`和``previous`方法包括`self.class.where("created_at <?",created_at).order(created_at :: asc).last` (4认同)
  • 问题是我不是按ID订购的. (2认同)
  • 它仍然是放置这些方法的一个很好的例子.可以投入使用. (2认同)

D-s*_*ide 2

没有简单的开箱即用的解决方案。

有点脏,但工作方式是仔细整理查找下一个和上一个项目的条件。这id很容易,因为所有的ids 都是不同的,Rails Guy 的答案描述了这一点:在next已知的情况下id,选择一个较大的第一个条目id(如果结果按id默认值排序)。不仅如此 - 他的答案暗示了放置nextprevious进入模型类。这样做。

如果有多个订单标准,事情就会变得复杂。比如说,我们有一组行,group首先按参数排序(不同行上可能有相同的值),然后按参数排序id(保证每个地方的 id 不同)。结果按group和 然后按id(均为升序)排序,因此我们可能会遇到获取下一个元素的两种情况,它是列表中第一个包含元素的元素(这么多

  • 相同group更大的id
  • 一个更大的group

与上一个元素相同:您需要列表中的最后一个

  • 相同的group更小的id
  • 一个较小的group

它们分别获取所有下一个和上一个条目。如果您只需要一个,请使用 Rails' firstand last(按照Rails Guy 的建议)或limit(1)(并注意asc/desc顺序)。