2011-09-12 18 views
40

Moja aplikacja zawiera zdjęcia należące do użytkowników.Szyny: pobierz następny/poprzedni rekord

Na zdjęciu # pokaż widok Chciałbym pokazać "Więcej od tego użytkownika" i pokazać następne i poprzednie zdjęcie tego użytkownika. Byłoby dobrze, gdyby były to następne/poprzednie zdjęcia w zamówieniu id lub następne/poprzednie zdjęcie w zamówieniu created_at.

Jak napisać taką kwerendę dla jednego następnego/poprzedniego zdjęcia lub dla wielu kolejnych/poprzednich zdjęć?

+0

Ten klejnot doskonale sprawdzi się u mnie. http://stackoverflow.com/a/25712023/683157 – kuboon

Odpowiedz

80

Spróbuj tego:

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 

Teraz możesz:

photo.next 
photo.prev 
+0

prev nie działa poprawnie w ten sposób, powinno być user.photos.where ("id igrek

+3

@igrek I naprawiłem odpowiedź. Ogólnie, unikam używania połączenia 'last', ponieważ ma ono wpływ na wydajność, jeśli masz duży zestaw danych (http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the- zapytanie w dół). Używam klauzuli "ORDER BY id DESC", aby dostać się do ostatnich wierszy. –

+0

co powiesz na używanie limitu (1)? –

2

można przekazać niektóre opcje w miarę metody:

Na następnym zdjęciu:

Photo.where(:user_id => current_user.id, :created_at > current_photo.created_at).order("created_at").first 

poprzednie zdjęcie

Photo.where(:user_id => current_user.id, :created_at < current_photo.created_at).order("created_at").last 

może mam pierwszy/ostatni pomieszane.

8

Nie jestem pewien, czy jest to zmiana w Rails 3.2 lub nowszym, ale zamiast:

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

dla osób poprzedni. Trzeba zrobić

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

Wydaje się, że „zamówienie przez” jest źle, więc najpierw daje pierwszy rekord w DB, bo jeśli masz 3 pozycje niższy niż obecny, [1,3,4 ], następnie "pierwsza" to 1, ale ta ostatnia jest tą, której szukasz. Możesz również zastosować sortowanie po miejscu, ale to dodatkowy krok.

+1

Co z minusem. To działa idealnie? – jwilcox09

+0

Potwierdzam, że to działa. – 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 

Następnie można:

photo.previous 
photo.next 
1

Może chcesz sprawdzić Nexter. Działa na każdym dynamicznie tworzonym zakresie zamiast polegać na jednym zakodowanym w modelu.

+0

Stworzyłem klejnot z tym samym zachowaniem, ale inne podejście: https://github.com/dmitry/proximal_records –

12

To także doprowadziło mnie do rozwiązania mojego problemu. Próbowałem zrobić następny/poprzedni element, bez żadnych skojarzeń. skończyło się robić coś takiego w moim modelu:

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 

W ten sposób pętle dookoła, od ostatniego elementu idzie do pierwszej i na odwrót. Po prostu zadzwonię pod numer @item.next w moich widokach.

+0

Niesamowite dla iteracji cyklu. –

+0

Nice, szukał również cyklu! – 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 

Znalazłem, że odpowiedzi już tutaj nie służyły mojej sprawie. Wyobraź sobie, że chcesz mieć poprzednie lub następne w oparciu o opublikowaną datę, ale niektóre zdjęcia są publikowane tego samego dnia. Ta wersja będzie przeglądać zdjęcia w kolejności, w jakiej są renderowane na stronie, i pobrać je przed i po bieżącym w kolekcji.

Powiązane problemy