Controlla se esiste un record dal controller in Rails


91

Nella mia app un utente può creare un'impresa. Quando attivano l' indexazione nel mio BusinessesControllerVoglio verificare se un'azienda è correlata a current_user.id:

  • Se sì: mostra l'attività.
  • In caso negativo: reindirizza newall'azione.

Stavo cercando di usare questo:

if Business.where(:user_id => current_user.id) == nil
  # no business found
end

Ma ritorna sempre vero anche quando l'attività non esiste ...

Come posso verificare se esiste un record nel mio database?


1
L'utilizzo whererestituirà un array vuoto se non ci sono record. E []non è ugualenil
mind.blank

Che ne dici di solo un unless Business.find_by_user_id(current_user.id)?
Hengjie

Risposte:


231

Perché il tuo codice non funziona?

Il wheremetodo restituisce un oggetto ActiveRecord :: Relation (agisce come un array che contiene i risultati di where), può essere vuoto ma non lo sarà mainil .

Business.where(id: -1) 
 #=> returns an empty ActiveRecord::Relation ( similar to an array )
Business.where(id: -1).nil? # ( similar to == nil? )
 #=> returns false
Business.where(id: -1).empty? # test if the array is empty ( similar to .blank? )
 #=> returns true

Come verificare se esiste almeno un record?

Opzione 1: utilizzo di.exists?

if Business.exists?(user_id: current_user.id)
  # same as Business.where(user_id: current_user.id).exists?
  # ...
else
  # ...
end

Opzione 2: utilizzo .present?(o .blank?, l'opposto di .present?)

if Business.where(:user_id => current_user.id).present?
  # less efficiant than using .exists? (see generated SQL for .exists? vs .present?)
else
  # ...
end

Opzione 3: assegnazione di variabili nell'istruzione if

if business = Business.where(:user_id => current_user.id).first
  business.do_some_stuff
else
  # do something else
end

Questa opzione può essere considerata un odore di codice da alcuni linter (Rubocop per esempio).

Opzione 3b: assegnazione di variabili

business = Business.where(user_id: current_user.id).first
if business
  # ...
else
  # ...
end

Puoi anche usare al .find_by_user_id(current_user.id)posto di.where(...).first


Opzione migliore:

  • Se non utilizzi gli Businessoggetti: opzione 1
  • Se è necessario utilizzare gli Businessoggetti: Opzione 3

Non sembra funzionare. Continua a superare quel test ea caricare l'indice html come con il == nil test (quindi ricevo un errore: undefined method `name 'per nil: NilClass).

Prova con il primo prima di chiamare il presente
MrYoshiji

Ho lo stesso problema

Oh è colpa mia, ero confuso, devi testare conblank?
MrYoshiji

Grazie che ha funzionato! Non avrei dovuto accorgermi di quell'errore. Puoi dirmi perché il controllo == nil non ha funzionato?

29

In questo caso mi piace utilizzare il exists?metodo fornito da ActiveRecord:

Business.exists? user_id: current_user.id

Esiste? con OR possibile?
Imran Ahmad

5

con "esiste?":

Business.exists? user_id: current_user.id #=> 1 or nil

con qualsiasi?':

Business.where(:user_id => current_user.id).any? #=> true or false

Se usi qualcosa con .where, assicurati di evitare problemi con gli scope e usa meglio .unscoped

Business.unscoped.where(:user_id => current_user.id).any?

Meglio usare Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? per evitare inutili carichi di relazioni per l'oggetto che stai controllando.
Juanin

1

ActiveRecord # dove restituirà un oggetto ActiveRecord :: Relation (che non sarà mai nullo). Prova a usare .empty? sulla relazione da verificare se restituirà dei record.


1

Quando chiami Business.where(:user_id => current_user.id)otterrai un array. Questo array potrebbe non contenere oggetti oppure uno o più oggetti, ma non sarà nullo. Quindi il segno di spunta == nil non sarà mai vero.

Puoi provare quanto segue:

if Business.where(:user_id => current_user.id).count == 0

Quindi controlli il numero di elementi nell'array e li confronti con zero.

oppure puoi provare:

if Business.find_by_user_id(current_user.id).nil?

questo restituirà uno o zero.


1
business = Business.where(:user_id => current_user.id).first
if business.nil?
# no business found
else
# business.ceo = "me"
end

0

Lo farei in questo modo se avessi bisogno di una variabile di istanza dell'oggetto con cui lavorare:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.