Überprüfen Sie, ob ein Datensatz vom Controller in Rails vorhanden ist

89

In meiner App kann ein Benutzer ein Unternehmen erstellen. Wenn sie die indexAktion in meinem auslösen, BusinessesControllermöchte ich überprüfen, ob ein Unternehmen mit Folgendem verbunden ist current_user.id:

  • Wenn ja: Zeigen Sie das Unternehmen an.
  • Wenn nein: Zur newAktion umleiten .

Ich habe versucht, dies zu verwenden:

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

Aber es gibt immer wahr zurück, auch wenn das Geschäft nicht existiert ...

Wie kann ich testen, ob ein Datensatz in meiner Datenbank vorhanden ist?

MrYoshiji
quelle
1
Mit using wherewird ein leeres Array zurückgegeben, wenn keine Datensätze vorhanden sind. Und []ist nicht gleichnil
mind.blank
Was ist mit nur einem unless Business.find_by_user_id(current_user.id)?
Hengjie
Mögliches Duplikat der Überprüfung, ob ActiveRecord find ein Ergebnis zurückgibt
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Antworten:

227

Warum funktioniert Ihr Code nicht?

Die whereMethode gibt ein ActiveRecord :: Relation- Objekt zurück (verhält sich wie ein Array, das die Ergebnisse von enthält where). Es kann leer sein, wird es aber niemals seinnil .

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

Wie teste ich, ob mindestens ein Datensatz vorhanden ist?

Option 1: Verwenden.exists?

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

Option 2: Verwenden .present?(oder .blank?das Gegenteil von .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: Variablenzuweisung in der if-Anweisung

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

Diese Option kann von einigen Lintern (z. B. Rubocop) als Codegeruch angesehen werden.

Option 3b: Variablenzuordnung

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

Sie können auch .find_by_user_id(current_user.id)anstelle von verwenden.where(...).first


Beste Option:

  • Wenn Sie die BusinessObjekte nicht verwenden : Option 1
  • Wenn Sie die BusinessObjekte verwenden müssen: Option 3
MrYoshiji
quelle
Das schien nicht zu funktionieren. Es besteht diesen Test weiter und lädt den Index-HTML-Code wie beim == nil-Test (daher wird der Fehler angezeigt: undefinierte Methode `name 'für nil: NilClass).
Versuchen Sie es zuerst, bevor Sie anwesend anrufen
MrYoshiji
Ich bekomme das gleiche Problem
Oh, das ist meine Schuld, ich war verwirrt, Sie müssen mitblank?
MrYoshiji
Danke das hat funktioniert! Ich hätte diesen Fehler nicht bemerken sollen. Können Sie mir sagen, warum der == nil-Check nicht funktioniert hat?
28

In diesem Fall verwende ich gerne exists?die von ActiveRecord bereitgestellte Methode:

Business.exists? user_id: current_user.id
Hamed
quelle
Gibt es? mit ODER möglich?
Imran Ahmad
5

mit 'existiert?':

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

mit jedem?':

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

Wenn Sie etwas mit .where verwenden, vermeiden Sie Probleme mit Bereichen und verwenden Sie besser .unscoped

Business.unscoped.where(:user_id => current_user.id).any?
user2427993
quelle
Verwenden Sie besser Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? um unnötige Belastungen für das zu überprüfende Objekt zu vermeiden.
Juanin
1

ActiveRecord # wobei ein ActiveRecord :: Relation-Objekt zurückgegeben wird (das niemals Null sein wird). Versuchen Sie es mit .empty? auf die Beziehung zu testen, ob es irgendwelche Datensätze zurückgibt.

Puhlze
quelle
1

Wenn Sie anrufen, erhalten Business.where(:user_id => current_user.id)Sie ein Array. Dieses Array enthält möglicherweise keine Objekte oder ein oder mehrere Objekte, ist jedoch nicht null. Somit wird die Prüfung == nil niemals wahr sein.

Sie können Folgendes versuchen:

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

Sie überprüfen also die Anzahl der Elemente im Array und vergleichen sie mit Null.

oder Sie können versuchen:

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

Dies gibt eins oder null zurück.

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

Ich würde es so machen, wenn Sie eine Instanzvariable des Objekts benötigen, um damit zu arbeiten:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
user3633260
quelle