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

Dans mon application, un Utilisateur peut créer une Entreprise. Quand ils déclenchent le index action dans mon BusinessesController je veux vérifier si une Entreprise est liée à la current_user.id:

  • Si oui: afficher l'entreprise.
  • Si non: rediriger vers l'action new.

J'essayais d'utiliser ceci:

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

Mais il retourne toujours vrai même lorsque l'entreprise n'existe pas...

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

65
demandé sur MrYoshiji 2013-05-22 06:49:12

7 réponses

Pourquoi votre code ne fonctionne pas?

Le where méthode retourne un ActiveRecord::Relation objet (agit comme un tableau qui contient les résultats de l'where), il peut être vide, mais il ne sera jamais nil.

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: À L'Aide De .exists?

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

Option 2: à l'Aide de .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 de variables

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

Vous pouvez aussi utiliser .find_by_user_id(current_user.id) au lieu de .where(...).first


Meilleure option:

  • si vous n'utilisez pas le (s) objet (s) Business: Option 1
  • si vous avez besoin d'utiliser le(s) objet (s): Option 3
189
répondu MrYoshiji 2017-12-13 19:03:11

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

Business.exists? user_id: current_user.id
24
répondu Hamed 2013-06-26 17:34:08

Avec ' existe?':

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

, Avec 'tout?':

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

Si vous utilisez quelque chose avec .où, assurez-vous d'éviter les problèmes avec les étendues et une meilleure utilisation .non délimité

Business.unscoped.where(:user_id => current_user.id).any?
3
répondu user2427993 2013-08-21 09:39:19

ActiveRecord # where retournera un objet ActiveRecord::Relation (qui ne sera jamais nul). Essayez d'utiliser .est-il vide? sur la relation à tester si elle retournera des enregistrements.

1
répondu Puhlze 2013-05-22 03:01:37

Lorsque vous appelez Business.where(:user_id => current_user.id), vous obtiendrez un tableau. Ce tableau peut ne pas avoir d'objets ou un ou plusieurs objets, mais il ne sera pas null. Ainsi, le chèque = = nil ne sera jamais vrai.

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 les comparez à zéro.

, Ou vous pouvez essayer:

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

Cela renverra un ou zéro.

1
répondu marimaf 2013-05-22 03:07:09
business = Business.where(:user_id => current_user.id).first
if business.nil?
# no business found
else
# business.ceo = "me"
end
0
répondu Nino van Hooff 2015-03-19 11:06:08

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

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
0
répondu user3633260 2016-03-16 15:45:40