Vérifiez si l'enregistrement existe du contrôleur dans Rails


91

Dans mon application, un utilisateur peut créer une entreprise. Lorsqu'ils déclenchent l' indexaction dans mon, BusinessesControllerje veux vérifier si une entreprise est liée à current_user.id:

  • Si oui: affichez l'entreprise.
  • Si non: redirigez vers l' newaction.

J'essayais d'utiliser ceci:

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

Mais cela revient toujours vrai même lorsque l'entreprise n'existe pas ...

Comment puis-je tester si un enregistrement existe dans ma base de données?


1
L'utilisation whereretournera un tableau vide s'il n'y a pas d'enregistrements. Et []n'est pas égalnil
esprit.blank

Et juste un unless Business.find_by_user_id(current_user.id)?
Hengjie

Réponses:


231

Pourquoi votre code ne fonctionne pas?

La whereméthode renvoie un objet ActiveRecord :: Relation (agit comme un tableau qui contient les résultats de la where), il peut être vide mais il ne le sera jamaisnil .

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

Comment tester si au moins un enregistrement existe?

Option 1: Utilisation.exists?

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

Option 2: Utiliser .present?(ou .blank?, l'opposé de .present?)

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

Option 3: affectation de variable dans l'instruction if

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

Cette option peut être considérée comme une odeur de code par certains linters (Rubocop par exemple).

Option 3b: Affectation des variables

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

Vous pouvez également utiliser à la .find_by_user_id(current_user.id)place de.where(...).first


Meilleure option:

  • Si vous n'utilisez pas le ou les Businessobjets: Option 1
  • Si vous devez utiliser le ou les Businessobjets: Option 3

Cela ne semblait pas fonctionner. Il continue de passer ce test et de charger l'index html comme avec le test == nil (donc j'obtiens une erreur: méthode non définie `nom 'pour nil: NilClass).

Essayez avec d'abord avant d'appeler présent
MrYoshiji

J'ai le même problème

Oh c'est ma faute, j'étais confus, vous devez tester avecblank?
MrYoshiji

Merci qui a fonctionné! Je n'aurais pas dû remarquer cette erreur. Pouvez-vous me dire pourquoi la vérification == nil n'a pas fonctionné?

29

Dans ce cas, j'aime utiliser la exists?méthode fournie par ActiveRecord:

Business.exists? user_id: current_user.id

Existe-t-il? avec OU possible?
Imran Ahmad

5

avec 'existe?':

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

avec 'any?':

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

Si vous utilisez quelque chose avec .where, assurez-vous d'éviter les problèmes avec les étendues et mieux utiliser .unscoped

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

Mieux vaut utiliser Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? pour éviter une charge inutile de relations pour l'objet que vous vérifiez.
Juanin

1

ActiveRecord # où retournera un objet ActiveRecord :: Relation (qui ne sera jamais nul). Essayez d'utiliser .empty? sur la relation à tester si elle renverra des enregistrements.


1

Lorsque vous appelez, Business.where(:user_id => current_user.id)vous obtiendrez un tableau. Ce tableau peut ne contenir aucun objet ou un ou plusieurs objets, mais il ne sera pas nul. Ainsi, la vérification == nil ne sera jamais vraie.

Vous pouvez essayer ce qui suit:

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

Vous vérifiez donc le nombre d'éléments dans le tableau et vous les comparez à zéro.

ou vous pouvez essayer:

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

cela retournera un ou nul.


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

0

Je le ferais de cette façon si vous aviez besoin d'une variable d'instance de l'objet avec laquelle travailler:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.