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?

MrYoshiji
la source
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
duplication possible de Vérifier si la recherche ActiveRecord renvoie un résultat
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

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
MrYoshiji
la source
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
Hamed
la source
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?
user2427993
la source
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.

Puhlze
la source
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.

marimaf
la source
1
business = Business.where(:user_id => current_user.id).first
if business.nil?
# no business found
else
# business.ceo = "me"
end
Nino van Hooff
la source
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
utilisateur3633260
la source