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

我的应用程序包含属于用户的照片。

在照片显示视图中,我想显示“来自该用户的更多照片”,并显示该用户的下一张和上一张照片。 我可以将这些作为id顺序中的下一张/上一张照片,或者作为created_at顺序中的下一张/上一张照片。

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

Andrew asked 2020-02-13T16:03:40Z
9个解决方案
93 votes

尝试这个:

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
Harish Shetty answered 2020-02-13T16:04:00Z
18 votes

这也使我为自己的问题找到了解决方案。 我正在尝试为商品创建下一个/上一个商品,不涉及任何关联。 最终在我的模型中做了这样的事情:

  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

Cremz answered 2020-02-13T16:04:25Z
8 votes

不知道这是否是Rails 3.2+的更改,而不是:

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

对于以前的。 你必须做

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

似乎“ order by”是错误的,因此首先给您DB中的第一条记录,因为如果您的项比当前的[1,3,4]低3,则“ first”为1,但是 最后是您要寻找的那个。 您还可以对where之后进行排序,但这是一个额外的步骤。

jwilcox09 answered 2020-02-13T16:04:55Z
3 votes
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
Zernel answered 2020-02-13T16:05:19Z
3 votes

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

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

这是我有史以来第一个发布在StackOverflow上的答案,这个问题已经很老了...我希望有人能看到它:)

jinstrider2000 answered 2020-02-13T16:05:44Z
2 votes

您可以将一些选项传递给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

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

Jordan Schwartz answered 2020-02-13T16:06:17Z
1 votes

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

charlysisto answered 2020-02-13T16:06:37Z
1 votes
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

我发现这里已经没有答案了。 假设您要根据发布的日期创建上一个或下一个,但是有些照片是在同一日期发布的。 此版本将按照照片在页面上显示的顺序循环浏览照片,并在集合中当前照片的前后进行拍摄。

NealJMD answered 2020-02-13T16:06:57Z
0 votes

将您的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()。

Oldwolf Pang answered 2020-02-13T16:07:24Z
translate from https://stackoverflow.com:/questions/7394088/rails-get-next-previous-record