find vs find_by vs where

Ik ben nieuw op het gebied van rails. Wat ik zie dat er veel manieren zijn om een record te vinden:

  1. find_by_<columnname>(<columnvalue>)
  2. find(:first, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>).first

En het lijkt erop dat ze allemaal precies dezelfde SQL genereren. Ik geloof ook dat hetzelfde geldt voor het vinden van meerdere records:

  1. find_all_by_<columnname>(<columnvalue>)
  2. find(:all, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>)

Is er een vuistregel of aanbeveling welke te gebruiken?


Antwoord 1, autoriteit 100%

Bewerken:
Dit antwoord is erg oud en er zijn andere, betere antwoorden naar voren gekomen sinds dit bericht is gemaakt. Ik raad aan om de onderstaande door @Hossam Khamis te bekijken voor meer details.

Gebruik degene die het beste bij je past.

De findmethode wordt meestal gebruikt om een rij op ID op te halen:

Model.find(1)

Het is vermeldenswaard dat findeen uitzondering genereert als het item niet wordt gevonden door het kenmerk dat u opgeeft. Gebruik where(zoals hieronder beschreven, wat een lege array retourneert als het kenmerk niet wordt gevonden) om te voorkomen dat er een uitzondering wordt gegenereerd.

Andere toepassingen van findworden meestal vervangen door dingen als deze:

Model.all
Model.first

find_bywordt gebruikt als hulp bij het zoeken naar informatie in een kolom, en het verwijst naar deze met naamgevingsconventies. Als u bijvoorbeeld een kolom met de naam namein uw database heeft, gebruikt u de volgende syntaxis:

Model.find_by(name: "Bob")

.whereis meer een vangst waarmee je een wat complexere logica kunt gebruiken voor wanneer de conventionele helpers het niet zullen doen, en het retourneert een reeks items die voldoen aan je voorwaarden (of anders een lege array).


Antwoord 2, autoriteit 97%

waarActiveRecord::Relation retourneert

Kijk nu eens naar de find_by-implementatie:

def find_by
  where(*args).take
end

Zoals je kunt zien is find_byhetzelfde als where, maar het retourneert slechts één record. Deze methode moet worden gebruikt om 1 record te krijgen en waarmoet worden gebruikt om alle records met bepaalde voorwaarden te krijgen.


Antwoord 3, autoriteit 41%

Model.find

1- Parameter: ID van het te vinden object.

2- Indien gevonden: het retourneert het object (slechts één object).

3- Indien niet gevonden: genereert een ActiveRecord::RecordNotFounduitzondering.

Model.find_by

1- Parameter: sleutel/waarde

Voorbeeld:

User.find_by name: 'John', email: '[email protected]'

2- Indien gevonden: het geeft het object terug.

3- Indien niet gevonden: retourneert nil.

Opmerking:Als je wilt dat het ActiveRecord::RecordNotFoundverhoogt, gebruik dan find_by!

Model.where

1- Parameter: hetzelfde als find_by

2- Indien gevonden: het retourneert ActiveRecord::Relationmet een of meer records die overeenkomen met de parameters.

3- Indien niet gevonden: het retourneert een Leeg ActiveRecord::Relation.


Antwoord 4, autoriteit 30%

Er is een verschil tussen finden find_bydoordat findeen fout retourneert als deze niet wordt gevonden, terwijl find_bygeeft null terug.

Soms is het gemakkelijker te lezen als je een methode hebt zoals find_by email: "haha", in tegenstelling tot .where(email: some_params).first.


Antwoord 5, autoriteit 16%

Sinds Rails 4 kun je het volgende doen:

User.find_by(name: 'Bob')

wat het equivalent is find_by_namein Rails 3.

Gebruik #wherewanneer #finden #find_byniet genoeg zijn.


Antwoord 6, autoriteit 7%

Het geaccepteerde antwoord dekt over het algemeen alles, maar ik wil graag iets toevoegen,
voor het geval u van plan bent om met het model te werken op een manier zoals bijwerken, en u een enkele record ophaalt (waarvan u de idniet kent), dan is find_byde te gaan, omdat het de record ophaalt en niet in een array plaatst

irb(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

maar als je wheregebruikt, kun je het niet rechtstreeks bijwerken

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)

in zo’n geval zou je het als volgt moeten specificeren

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

Antwoord 7, autoriteit 6%

Naast het geaccepteerde antwoord is het volgende ook geldig

Model.find()kan een reeks id’s accepteren en zal alle records retourneren die overeenkomen.
Model.find_by_id(123)accepteert ook array, maar verwerkt alleen de eerste id-waarde die aanwezig is in array

Model.find([1,2,3])
Model.find_by_id([1,2,3])

Antwoord 8, autoriteit 5%

De tot nu toe gegeven antwoorden zijn allemaal OK.

Een interessant verschil is echter dat Model.findzoekt op id; indien gevonden, retourneert het een Modelobject (slechts een enkele record), maar genereert anders een ActiveRecord::RecordNotFound.

Model.find_bylijkt erg op Model.finden laat je in elke kolom of groep kolommen in je database zoeken, maar het geeft nilals er geen record overeenkomt met de zoekopdracht.

Model.whereaan de andere kant retourneert een Model::ActiveRecord_Relation-object dat lijkt op een array met alle records die overeenkomen met de zoekopdracht. Als er geen record is gevonden, wordt een leeg Model::ActiveRecord_Relation-object geretourneerd.

Ik hoop dat deze u op elk moment kunnen helpen om te beslissen welke u wilt gebruiken.


Antwoord 9, autoriteit 4%

Stel dat ik een model User

. heb

  1. User.find(id)

Retourneert een rij waarbij primaire sleutel = id. Het retourtype is Userobject.

  1. User.find_by(email:"[email protected]")

Retourneert in dit geval de eerste rij met overeenkomend kenmerk of e-mailadres. Het retourtype is opnieuw User-object.

Opmerking:- User.find_by(email: "[email protected]")is vergelijkbaar met User.find_by_email("[email protected]")

  1. User.where(project_id:1)

Retourneert alle gebruikers in de gebruikerstabel waar het kenmerk overeenkomt.

Hier is het retourtype ActiveRecord::Relationobject. De klasse ActiveRecord::Relationbevat Ruby’s Enumerable-module, zodat u het object als een array kunt gebruiken en erop kunt doorkruisen.


Antwoord 10, autoriteit 4%

Beide #2’s in je lijsten worden beëindigd. Je kunt echter nog steeds find(params[:id])gebruiken.

Over het algemeen werkt where()in de meeste situaties.

Hier is een geweldige post: https://web.archive.org/web/20150206131559/http://m.onkey.org/active-record-query-interface


Antwoord 11

Het beste van werken met open source-technologie is dat je de lengte en de breedte ervan kunt inspecteren.
Bekijk deze link

find_by ~> Vindt de eerste record die aan de opgegeven voorwaarden voldoet. Er is geen impliciete bestelling, dus als de volgorde belangrijk is, moet u deze zelf specificeren. Als er geen record wordt gevonden, wordt nul geretourneerd.

vind ~> Vindt het eerste record dat aan de opgegeven voorwaarden voldoet, maar als er geen record wordt gevonden, wordt er een uitzondering gemaakt, maar dat is opzettelijk gedaan.

Kijk naar de bovenstaande link, deze heeft alle uitleg en gebruiksscenario’s voor de volgende twee functies.


Antwoord 12

Ik zal persoonlijk aanbevelen om

. te gebruiken

where(< columnname> => < columnvalue>)

Other episodes