Rails:获取下一个/上一个记录

Posted

技术标签:

【中文标题】Rails:获取下一个/上一个记录【英文标题】:Rails: Get next / previous record 【发布时间】:2011-09-12 21:10:34 【问题描述】:

我的应用有属于用户的照片。

在 photo#show 视图中,我想显示“来自该用户的更多信息”,并显示该用户的下一张和上一张照片。我可以将这些作为id 订单中的下一张/上一张照片或created_at 订单中的下一张/上一张照片。

您将如何为下一张/上一张照片或多张下一张/上一张照片编写这种查询?

【问题讨论】:

这颗宝石非常适合我。 ***.com/a/25712023/683157 【参考方案1】:

试试这个:

class User
  has_many :photos
end


class Photo
  belongs_to :user

  def next
    user.photos.where("id > ?", id).first
  end

  def prev
    user.photos.where("id < ?", id).last
  end

end

现在你可以:

photo.next
photo.prev

【讨论】:

prev 这种方式不能正常工作,应该是 user.photos.where("id @igrek 我已经确定了答案。一般来说,我避免使用last 调用,因为如果您有一个大数据集(***.com/questions/4481388/…),它会影响性能。我使用ORDER BY id DESC 子句到达最后一行。 使用limit(1)怎么样? @KourindouHime,first 方法将结果集限制为LIMIT 1。这里的first 方法与数组上的第一种方法不同。 @igrek,我已将解决方案更改为使用firstlast,因为我注意到在最新版本的rails 中firstlast 添加了正确的排序。【参考方案2】:

它也让我找到了解决问题的方法。我试图为一个项目制作下一个/上一个,不涉及任何关联。最终在我的模型中做了这样的事情:

  def next
    Item.where("id > ?", id).order("id ASC").first || Item.first
  end

  def previous
    Item.where("id < ?", id).order("id DESC").first || Item.last
  end

以这种方式循环,从最后一个项目到第一个项目,反之亦然。 之后我只是在我的视图中调用@item.next

【讨论】:

循环迭代很棒。 不错,也在找循环!【参考方案3】:

不确定这是否是 Rails 3.2+ 中的更改,但不是:

model.where("id < ?", id).first

为上一个。你必须这样做

.where("id > ?", id).last

看来“order by”是错误的,所以先给你DB中的第一条记录,因为如果你有3项低于当前,[1,3,4],那么“第一”是1,但最后一个是你要找的那个。您也可以在 where 之后应用排序,但这是一个额外的步骤。

【讨论】:

【参考方案4】:
class Photo < ActiveRecord::Base
  belongs_to :user
  scope :next, lambda |id| where("id > ?",id).order("id ASC")  # this is the default ordering for AR
  scope :previous, lambda |id| where("id < ?",id).order("id DESC") 

  def next
    user.photos.next(self.id).first
  end

  def previous
    user.photos.previous(self.id).first
  end
end

那么你可以:

photo.previous
photo.next

【讨论】:

【参考方案5】:

这应该可行,而且我认为它比其他解决方案更有效,因为它不会检索当前记录之上或之下的每条记录,只是为了获取下一个或上一个记录:

def next
  # remember default order is ascending, so I left it out here
  Photo.offset(self.id).limit(1).first
end

def prev
  # I set limit to 2 because if you specify descending order with an 
  # offset/limit query, the result includes the offset record as the first
  Photo.offset(self.id).limit(2).order(id: :desc).last
end

这是我在 *** 上发布的第一个答案,而且这个问题已经很老了......我希望有人看到它:)

【讨论】:

如果底层数据库 ID 不规则(这是一个常见用例),此解决方案将不起作用。例如,如果我的记录 ID 是 [3, 10, 11, 13, 14],并且如果我想找到 id =&gt; 3 的下一个元素,那么生成的结果是 offset(3) =&gt; [13,14]。这种行为在文档offset =&gt; Specifies the number of rows to skip before returning rows. 中有清楚的解释【参考方案6】:

您可以将一些选项传递给 where 方法:

下一张照片:

Photo.where(:user_id => current_user.id, :created_at > current_photo.created_at).order("created_at").first

上一张照片

Photo.where(:user_id => current_user.id, :created_at < current_photo.created_at).order("created_at").last

我可能把第一个/最后一个弄混了。

【讨论】:

【参考方案7】:

将你的 app/models/application_record.rb 修改为以下代码:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

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

  def previous
   self.class.where("id < ?", id).order("id DESC").first || self.class.last
  end
end

然后您可以在所有模型中使用 next() 和 previous()。

【讨论】:

效果很好。您可能希望在您的模型类上实现这一点,这样您就可以以与您的业务逻辑一致的方式(例如,下一篇/上一篇发表的文章)限定查询范围。【参考方案8】:

您可能想查看Nexter。 它适用于任何动态创建的范围,而不是依赖于模型中的硬编码。

【讨论】:

我创建了具有相同行为的 gem,但另一种方法:github.com/dmitry/proximal_records【参考方案9】:
class Photo < ActiveRecord::Base
  belongs_to :user

  default_scope  order('published_at DESC, id DESC') 

  def next
    current = nil
    user.photos.where('published_at >= ?', published_at).each do |p|
      if p.id == id then break else current = p end
    end
    return current
  end

  def previous
    current = nil
    user.photos.where('published_at <= ?', published_at).reverse.each do |p|
      if p.id == id then break else current = p end
    end
    return current
  end
end

我发现这里已经给出的答案不适合我的情况。想象一下,您想要基于发布日期的上一张或下一张,但有些照片是在同一日期发布的。此版本将按照片在页面上呈现的顺序循环播放照片,并获取集合中当前照片之前和之后的照片。

【讨论】:

以上是关于Rails:获取下一个/上一个记录的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3:获取随机记录

Rails N + 1查询问题时获取与where条件关联的记录

获取 STI 中的记录以获取 rails 4 中的空 has_many 记录

Rails:通过许多其他记录获取记录

Rails 最佳 API 设计,用于获取与某个用户关联的所有记录

无法在 Rails 3.2 中使用复合唯一索引将记录添加到连接表