Ü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?


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

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

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

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?

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.


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.


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

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.