Подтвердить что ты не робот

Rails: получить следующую/предыдущую запись

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

На фото # show view Я бы хотел показать "Больше от этого пользователя" и показать следующую и предыдущую фотографию этого пользователя. Мне было бы хорошо, если бы они были следующей/предыдущей фотографией в заказе id или следующей/предыдущей фотографией в порядке created_at.

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

4b9b3361

Ответ 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

Ответ 2

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

  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

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

Ответ 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

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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