Jestem nowy w railach. Co widzę, jest wiele sposobów na znalezienie rekordu:
find_by_<columnname>(<columnvalue>)
find(:first, :conditions => { <columnname> => <columnvalue> }
where(<columnname> => <columnvalue>).first
Wygląda na to, że wszystkie z nich generują dokładnie ten sam kod SQL. Uważam też, że to samo dotyczy znajdowania wielu rekordów:
find_all_by_<columnname>(<columnvalue>)
find(:all, :conditions => { <columnname> => <columnvalue> }
where(<columnname> => <columnvalue>)
Czy istnieje praktyczna zasada lub zalecenie, którego z nich należy użyć?
źródło
find_by
nie jest przestarzała, ale składnia nieco się zmienia. Odfind_by_name("Bob")
dofind_by(:name, "Bob")
.find_by(name: "Bob")
find_by_...
to, że jestem przestarzały, czy masz źródło? Wydaje się,find_by
ifind_by_...
są nadal obsługiwane zarówno w Rails 4.gdzie zwraca ActiveRecord :: Relation
Teraz spójrz na implementację find_by:
def find_by where(*args).take end
Jak widać find_by jest tym samym, co gdzie, ale zwraca tylko jeden rekord. Ta metoda powinna być używana do uzyskania 1 rekordu i gdzie powinna być używana do uzyskania wszystkich rekordów z określonymi warunkami.
źródło
find_by
uratuje::RangeError
przedwhere(*args)
i powrót zero.Model.find
1- Parametr: identyfikator obiektu do znalezienia.
2- Jeśli znaleziono: zwraca obiekt (tylko jeden obiekt).
3- Jeśli nie zostanie znaleziony: zgłasza
ActiveRecord::RecordNotFound
wyjątek.Model.find_by
1- Parametr: klucz / wartość
Przykład:
User.find_by name: 'John', email: '[email protected]'
2- Jeśli znaleziono: zwraca obiekt.
3- Jeśli nie znaleziono: zwraca
nil
.Uwaga: jeśli chcesz, aby zwiększył
ActiveRecord::RecordNotFound
użyciefind_by!
Model.where
1- Parametr: taki sam jak
find_by
2- Jeśli znaleziono: zwraca
ActiveRecord::Relation
jeden lub więcej rekordów pasujących do parametrów.3- Jeśli nie znaleziono: zwraca Empty
ActiveRecord::Relation
.źródło
Istnieje różnica między
find
ifind_by
w,find
która zwróci błąd, jeśli nie zostanie znaleziona, natomiastfind_by
zwróci wartość null.Czasami łatwiej jest przeczytać, jeśli masz metodę taką jak
find_by email: "haha"
, w przeciwieństwie do.where(email: some_params).first
.źródło
Od Rails 4 możesz:
User.find_by(name: 'Bob')
co jest odpowiednikiem
find_by_name
w Railsach 3.Użyj,
#where
kiedy#find
i#find_by
nie wystarczą.źródło
find_by
a niefind_by_<column_name>
. Potrzebuję tego, żeby komuś odpowiedzieć.find_by_name
w Rails 4? O ile wiem, nie zostało wycofane .find_by(name: "Rob*")
Odpowiedź ogólnie akceptowaną obejmuje to wszystko, ale chciałbym dodać coś, tylko okrywać planuje pracę z modelem w sposób jak aktualizacja, i jesteś pobieranie pojedynczy rekord (którego
id
nie wiem), tofind_by
jest droga do zrobienia, ponieważ pobiera rekord i nie umieszcza go w tablicyirb(main):037:0> @kit = Kit.find_by(number: "3456") Kit Load (0.9ms) SELECT "kits".* FROM "kits" WHERE "kits"."number" = '3456' LIMIT 1 => #<Kit id: 1, number: "3456", created_at: "2015-05-12 06:10:56", updated_at: "2015-05-12 06:10:56", job_id: nil> irb(main):038:0> @kit.update(job_id: 2) (0.2ms) BEGIN Kit Exists (0.4ms) SELECT 1 AS one FROM "kits" WHERE ("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.5ms) UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" = 1 [["job_id", 2], ["updated_at", Tue, 12 May 2015 07:16:58 UTC +00:00]] (0.6ms) COMMIT => true
ale jeśli używasz
where
, nie możesz go bezpośrednio zaktualizowaćirb(main):039:0> @kit = Kit.where(number: "3456") Kit Load (1.2ms) SELECT "kits".* FROM "kits" WHERE "kits"."number" = '3456' => #<ActiveRecord::Relation [#<Kit id: 1, number: "3456", created_at: "2015-05-12 06:10:56", updated_at: "2015-05-12 07:16:58", job_id: 2>]> irb(main):040:0> @kit.update(job_id: 3) ArgumentError: wrong number of arguments (1 for 2)
w takim przypadku należałoby to określić w ten sposób
irb(main):043:0> @kit[0].update(job_id: 3) (0.2ms) BEGIN Kit Exists (0.6ms) SELECT 1 AS one FROM "kits" WHERE ("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.6ms) UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" = 1 [["job_id", 3], ["updated_at", Tue, 12 May 2015 07:28:04 UTC +00:00]] (0.5ms) COMMIT => true
źródło
Oprócz zaakceptowanej odpowiedzi ważne jest również następujące
Model.find()
może akceptować tablicę identyfikatorów i zwróci wszystkie zgodne rekordy.Model.find_by_id(123)
akceptuje również tablicę, ale przetwarza tylko pierwszą wartość id obecną w tablicyModel.find([1,2,3]) Model.find_by_id([1,2,3])
źródło
Oba pozycje # 2 na Twoich listach są wycofywane. Nadal możesz używać
find(params[:id])
.Generalnie
where()
działa w większości sytuacji.Oto świetny post: http://m.onkey.org/active-record-query-interface
źródło
Wszystkie dotychczas udzielone odpowiedzi są OK.
Jednak jedną interesującą różnicą jest to, że
Model.find
wyszukiwanie według identyfikatora; jeśli zostanie znaleziony, zwracaModel
obiekt (tylko pojedynczy rekord), ale zgłaszaActiveRecord::RecordNotFound
inaczej.Model.find_by
jest bardzo podobny doModel.find
i umożliwia przeszukiwanie dowolnej kolumny lub grupy kolumn w bazie danych, ale zwraca,nil
jeśli żaden rekord nie pasuje do wyszukiwania.Model.where
z drugiej strony zwracaModel::ActiveRecord_Relation
obiekt, który przypomina tablicę zawierającą wszystkie rekordy pasujące do wyszukiwania . Jeśli nie znaleziono rekordu, zwraca pustyModel::ActiveRecord_Relation
obiekt.Mam nadzieję, że pomogą ci one zdecydować, którego użyć w dowolnym momencie.
źródło
Załóżmy, że mam model
User
User.find(id)
Zwraca wiersz, w którym klucz podstawowy = id. Zwracanym typem będzie
User
obiekt.User.find_by(email:"[email protected]")
W tym przypadku zwraca pierwszy wiersz z pasującym atrybutem lub adresem e-mail. Typ zwracany będzie
User
ponownie obiektem.Uwaga: -
User.find_by(email: "[email protected]")
jest podobny doUser.find_by_email("[email protected]")
User.where(project_id:1)
Zwraca wszystkich użytkowników w tabeli użytkowników, w której atrybut jest zgodny.
Tutaj typem zwracanym będzie
ActiveRecord::Relation
obiekt.ActiveRecord::Relation
class zawieraEnumerable
moduł Rubiego, więc możesz używać jego obiektu jako tablicy i przechodzić po niej.źródło
Najlepszą częścią pracy z dowolną technologią open source jest to, że można sprawdzić jej długość i szerokość. Sprawdź ten link
find_by ~> Znajduje pierwszy rekord spełniający określone warunki. Nie ma dorozumianych zamówień, więc jeśli zamówienie ma znaczenie, należy je określić samodzielnie. Jeśli żaden rekord nie zostanie znaleziony, zwraca nil.
find ~> Znajduje pierwszy rekord spełniający określone warunki, ale jeśli nie zostanie znaleziony żaden rekord, zgłasza wyjątek, ale jest to wykonywane celowo.
Sprawdź powyższy link, zawiera wszystkie wyjaśnienia i przypadki użycia dla następujących dwóch funkcji.
źródło
Osobiście polecam używanie
where(< columnname> => < columnvalue>)
źródło