Rails: получить следующую / предыдущую запись - PullRequest
47 голосов
/ 13 сентября 2011

В моем приложении есть фотографии, принадлежащие пользователям.

В режиме просмотра фотографий # я хотел бы показать "Еще от этого пользователя" и показать следующую и предыдущую фотографию этого пользователя.Мне бы хотелось, чтобы это была следующая / предыдущая фотография в порядке id или следующая / предыдущая фотография в порядке created_at.

Как бы вы написали запрос такого типа для одной следующей / предыдущей фотографии,или для нескольких следующих / предыдущих фотографий?

Ответы [ 9 ]

89 голосов
/ 13 сентября 2011

Попробуйте это:

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
16 голосов
/ 25 февраля 2014

Это привело меня и к решению моей проблемы.Я пытался сделать следующий / предыдущий для элемента, без каких-либо ассоциаций.в итоге я сделал что-то подобное в моей модели:

  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 в своих взглядах потом.

8 голосов
/ 12 августа 2012

Не уверен, что это изменение в Rails 3.2+, но вместо:

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

за предыдущий. Вы должны сделать

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

Кажется, что "порядок по" неправильный, поэтому сначала дайте вам первую запись в БД, потому что если у вас на 3 элемента меньше текущего, [1,3,4], то "первый" 1, но это последнее, что вы ищете. Вы также можете применить сортировку после, где, но это дополнительный шаг.

3 голосов
/ 06 июня 2013
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
2 голосов
/ 23 мая 2018

Это должно сработать, и я думаю, что оно более эффективно, чем другие решения, в том смысле, что оно не извлекает каждую запись выше или ниже текущей, просто чтобы перейти к следующей или предыдущей:

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, и этот вопрос довольно старый ... Надеюсь, кто-нибудь его увидит:)

2 голосов
/ 13 сентября 2011

Вы можете передать некоторые опции в метод 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

У меня может быть первый /последний перепутал.

1 голос
/ 13 ноября 2014
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

Я обнаружил, что ответы уже здесь не служили моему делу.Представьте, что вы хотите предыдущий или следующий на основе даты публикации, но некоторые фотографии публикуются в тот же день.Эта версия будет перебирать фотографии в том порядке, в котором они представлены на странице, и снимать фотографии до и после текущей в коллекции.

1 голос
/ 22 декабря 2013

Возможно, вы захотите проверить Nexter .Он работает с любой динамически создаваемой областью, а не полагается на одну жестко заданную в вашей модели.

0 голосов
/ 14 января 2019

Измените ваше 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 () во всех ваших моделях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...