OP uso reale soluzione caso
La soluzione più semplice è quella di combinare il vostro check-DB e il recupero dei dati in 1 Query DB invece di avere chiamate DB separate. Il tuo codice di esempio è vicino e trasmette il tuo intento, ma è un po 'fuori nella sintassi attuale.
Se fai semplice Truck.where("id = ?", id).select('truck_no').first.truck_no
e questo record non esiste, sarà lanciare un errore nil
quando si chiama truck_no
perché first
può recuperare un record nil
se non si trovano i tuoi criteri.
Questo perché la query restituirà una matrice di oggetti che corrispondono ai criteri, quindi si esegue uno first
su tale array che (se non vengono trovati record corrispondenti) è nil
.
Una soluzione abbastanza pulito:
# Note: using Rails 4/Ruby 2 syntax
first_truck = Truck.select(:truck_no).find_by(id) # => <Truck id: nil, truck_no: "123"> OR nil if no record matches criteria
if first_truck
truck_number = first_truck.truck_no
# do some processing...
else
# record does not exist with that criteria
end
mi consiglia di utilizzare la sintassi pulita che "commenti" se stessa in modo che gli altri sanno esattamente quello che stai cercando di fare.
Se davvero si vuole andare il miglio supplementare, si potrebbe aggiungere un metodo alla classe Truck
che fa questo per voi e trasmette il vostro intento:
# truck.rb model
class Truck < ActiveRecord::Base
def self.truck_number_if_exists(record_id)
record = Truck.select(:truck_no).find_by(record_id)
if record
record.truck_no
else
nil # explicit nil so other developers know exactly what's going on
end
end
end
allora si sarebbe chiamarla in questo modo:
if truck_number = Truck.truck_number_if_exists(id)
# do processing because record exists and you have the value
else
# no matching criteria
end
Il metodo ActiveRecord.find_by
recupera il primo record che corrisponde ai criteri o restituisce nil
se non viene trovato alcun record con tali criteri. Si noti che l'ordine dei metodi find_by
e where
è importante; devi chiamare lo select
sul modello Truck
. Questo perché quando chiami il metodo where
stai effettivamente restituendo un oggetto ActiveRelation
che non è quello che stai cercando qui.
See ActiveRecord API for 'find_by' method
soluzioni generali usando 'esiste?' metodo
Come alcuni degli altri contributori hanno già menzionato, il metodo exists?
è stato progettato specificamente per verificare l'esistenza di qualcosa. Non restituisce il valore, solo conferma che il DB ha un record che corrisponde ad alcuni criteri.
È utile se è necessario verificare l'univocità o la precisione di alcuni dati. La parte interessante è che ti consente di utilizzare i criteri ActiveRelation(Record?) where(...)
.
Per esempio, se si dispone di un modello di User
con un attributo email
ed è necessario verificare se una e-mail esiste già nella dB:
User.exists?(email: "[email protected]")
Il vantaggio di utilizzare exists?
è che la query SQL corsa è
SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
che è più efficiente di dati effettivamente ritorno.
Se è necessario recuperare in modo condizionale i dati dal DB, questo non è il metodo da utilizzare. Tuttavia, funziona alla grande per un semplice controllo e la sintassi è molto chiara, così altri sviluppatori sanno esattamente cosa stai facendo. L'uso della sintassi appropriata è fondamentale nei progetti con più sviluppatori. Scrivi un codice pulito e lascia che il codice "commenta" stesso.
quale versione di rotaie stai? – Shaunak
Dai un'occhiata a esiste?metodo http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-exists-3F – cristian