2011-09-12 3 views
40

У моего приложения есть фотографии, принадлежащие Пользователям.Rails: Получить следующую/предыдущую запись

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

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

+0

Этот драгоценный камень отлично работал для меня. http://stackoverflow.com/a/25712023/683157 – kuboon

ответ

80

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

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 
+0

prev не работает должным образом таким образом, должен быть user.photos.where ("id igrek

+3

@igrek I исправили ответ. Как правило, я избегаю использования «последнего» вызова, поскольку он имеет последствия для производительности, если у вас большой набор данных (http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the- запрос вниз). Я использую предложение ORDER BY id DESC, чтобы перейти к последним строкам. –

+0

как об использовании предел (1)? –

2

Вы можете передать некоторые параметры в метод, где:

На следующем фото:

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 

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

8

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

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

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

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

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

+1

Что с минусом. Это работает отлично? – jwilcox09

+0

Я могу подтвердить это. – Hendrik

3
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 
1

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

+0

Я создал драгоценный камень с таким же поведением, но другой подход: https://github.com/dmitry/proximal_records –

12

Это привело меня к решению моей проблемы. Я пытался сделать следующий/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 в мои взгляды потом.

+0

Удивительно для циклической итерации. –

+0

Ницца, тоже искал цикл! – gregblass

1
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 

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

Смежные вопросы