2012-03-05 11 views
69

Zauważyłem, że metoda Model.where zawsze zwraca tablicę, nawet jeśli istnieje tylko jeden wynik, gdy metoda Model.find nie. Czy jest jakikolwiek powód? Myślałem, że Model.where była preferowaną funkcją od Rails 3.X.Szyny .where vs .find

Czy powinienem używać Model.find, gdy oczekuję pojedynczego wyniku i Model.where, gdy oczekuję więcej niż jednego wyniku?

Odpowiedz

109
  • where zwraca ActiveRecord::Relation (nie tablicę, mimo że zachowuje się jak jeden), który jest kolekcja modelowych obiektów. Jeśli nic nie pasuje do warunków, po prostu zwraca pustą relację.

  • find (i związane z nią metody dynamicznych find_by_columnname) zwraca pojedynczy modelu obiektu. Jeśli nic nie zostanie znalezione, zostanie zgłoszony wyjątek ActiveRecord::RecordNotFound (ale nie w przypadku metod dynamicznych find_by_).

    Podczas find może zwrócić tablicę rekordów-not-relacja jeśli dana lista identyfikatorów, korzystając where jest korzystne, ponieważ Rails 3. Wiele podobnych zastosowań find są teraz deprecated or gone entirely.

Więc tak, jeśli tylko chcą i oczekują pojedynczy obiekt, używając find jest łatwiejsze, ponieważ w przeciwnym razie musi wywołać Model.where.first.

Należy zauważyć, że opcje mieszania w starym stylu na find i wiele metod dynamicznych find_ są przestarzałe od wersji Rails 4.0 (see relevant release notes).

+0

myślę, że 'find' może wrócić kilka obiektów w tablicy - spróbuj' User.find [1,2,3 ] '(znajduje użytkowników z identyfikatorami 1, 2 i 3) ... ale tak sądzę Andrew ma rację co do reszty – klump

+3

@klump Yup, może, ale' User.where (id: [1, 2, 3]) 'jest w tym przypadku preferowane, więc nawet o tym nie pomyślałem. Jak zwykle polecam lekturę dokumentacji API (z którą mam link w mojej odpowiedzi), ponieważ zapewnia najwięcej szczegółów. –

+0

Ale '.find (: all, ...)' zwraca tablicę. Jaka jest różnica między znalezieniem a miejscem? – highBandWidth

6

Model.find używa kolumny klucza podstawowego. Dlatego zawsze jest dokładnie jeden lub żaden wynik. Użyj go, gdy szukasz jednego konkretnego elementu zidentyfikowanego przez jego id.

+7

Nie, jeśli zrobisz '.find (: conditions => {: col_name => some_vals})'. – highBandWidth

+0

Lub jeśli używamy default_scopes, to może wziąć pod uwagę inne wartości również ... –

12

Właściwie find_by trwa model obiektowy z where uzyskane ActiveRecord::Relation

def find_by(*args) 
    where(*args).take 
end 

Source

+4

Pamiętaj, że find_by nie został dodany aż do Rails 4 (oryginalne pytanie zostało oznaczone szynami 3). – Steve

Powiązane problemy