2013-05-22 22 views
58

In meiner App kann ein Benutzer ein Geschäft erstellen. Als sie die index Aktion in meinem BusinessesController auslösen möchte ich überprüfen, ob ein Geschäft auf die current_user.id verwandt ist:Überprüfen, ob der Datensatz vom Controller in Rails existiert

  • Wenn ja: das Geschäft anzuzeigen.
  • Wenn nein: Umleiten an die new Aktion.

Ich habe versucht, dies zu nutzen:

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

Aber es gibt immer gilt auch, wenn das Geschäft nicht existiert ...

Wie kann ich testen, ob ein Datensatz existiert in meine Datenbank?

+1

Mit 'where' wird ein leeres Array zurückgegeben, wenn keine Datensätze vorhanden sind. Und '[]' ist nicht gleich "null" –

+0

Was ist mit nur einem 'außer Business.find_by_user_id (current_user.id)'? – Hengjie

+0

mögliches Duplikat von [Überprüfung, ob ActiveRecord find ein Ergebnis liefert] (http://stackoverflow.com/questions/2866473/checking-if-activerecord-find-returns-a-result) –

Antwort

172

Warum funktioniert Ihr Code nicht?

where Die Methode gibt einen Active :: Relation Objekt (wirkt wie eine Anordnung, die die Ergebnisse der where enthält), es kann leer sein, aber es wird nie nil sein.

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, wenn mindestens ein Datensatz existiert testen?

Option 1: Mit.exists?

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

Option 2: Mit.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 einen Code Geruch von einigen Linter (Rubocop zum Beispiel) in Betracht gezogen werden.

Option 3b: Variable Zuordnung

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

Sie auch .find_by_user_id(current_user.id) statt .where(...).first


Die beste Option verwenden können:

  • Wenn Sie nicht tun Verwenden Sie die Business Objekt (e): Option 1
  • Wenn Sie das Business Objekt verwenden müssen (s): Option 3
+0

Das schien nicht zu funktionieren.Er übergibt diesen Test und lädt den Index html wie beim == nil Test (damit bekomme ich einen Fehler: undefinierte Methode 'name 'für nil: NilClass). –

+0

Versuchen Sie zuerst, bevor Sie anzurufen – MrYoshiji

+0

Ich bekomme das gleiche Problem –

1

Active # wo ein Activerecord :: Relation Objekt zurück (die wird nie nil sein). Versuchen Sie es mit .lepty? auf der Beziehung zu testen, ob es irgendwelche Datensätze zurückgibt.

1

Wenn Sie Business.where(:user_id => current_user.id) anrufen, erhalten Sie ein Array. Dieses Array enthält möglicherweise keine Objekte oder ein oder mehrere Objekte, aber es wird nicht null sein. Daher wird der Check == nil niemals wahr sein.

können Sie versuchen, die folgenden:

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

Sie die Anzahl der Elemente im Array So überprüfen und sie auf Null vergleichen.

oder Sie können versuchen:

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

das eine oder null zurück.

24

In diesem Fall Ich mag die exists? Methode von Active nutzen:

Business.exists? user_id: current_user.id 
3

mit 'existiert?':

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

mit 'any?':

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

Wenn Sie etwas mit .wo verwenden, müssen Sie Probleme mit Bereichen und eine bessere Nutzung zu vermeiden .unscoped

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

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

0
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 auf diese Weise tun, wenn Sie eine Instanzvariable des Objekts benötigt, um mit zu arbeiten, :

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