Rails: получить следующую/предыдущую запись
В моем приложении есть фотографии, принадлежащие пользователям.
На фото # show view Я бы хотел показать "Больше от этого пользователя" и показать следующую и предыдущую фотографию этого пользователя. Мне было бы хорошо, если бы они были следующей/предыдущей фотографией в заказе id
или следующей/предыдущей фотографией в порядке created_at
.
Как бы вы пишете такой запрос для одной следующей/предыдущей фотографии или для нескольких следующих/предыдущих фотографий?
Ответы
Ответ 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() во всех ваших моделях.