2013-05-22 9 views
58

W mojej aplikacji Użytkownik może utworzyć firmę. Kiedy wywołać akcję w moim BusinessesControllerindex Chcę sprawdzić, czy firma jest związana z current_user.id:Sprawdź, czy rekord istnieje w kontrolerze w Railsach

  • Jeśli tak: wyświetlanie biznesu.
  • Jeśli nie: przekieruj do akcji new.

starałem się to wykorzystać:

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

Ale zawsze zwraca wartość true, nawet wtedy, gdy obiekt nie istnieje ...

Jak mogę sprawdzić, czy rekord istnieje w moja baza danych?

+1

Używanie 'where' zwraca pustą tablicę, jeśli nie ma rekordów. I '[]' nie równa 'nil' –

+0

Co powiesz na' chyba Business.find_by_user_id (current_user.id) '? – Hengjie

+0

możliwy duplikat [Sprawdzanie, czy ActiveRecord find zwraca wynik] (http://stackoverflow.com/questions/2866473/checking-if-activerecord-find-returns-a-result) –

Odpowiedz

172

Dlaczego twój kod nie działa?

Sposób where zwraca ActiveRecord :: Relacja przedmiotu (działa jak tablica, która zawiera wyniki where) może być pusty, ale to nigdy nie będzie 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 

Jak sprawdzić, czy przynajmniej jeden rekord istnieje?

Opcja 1: Stosując .exists?

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

Opcja 2: za pomocą .present? (lub .blank?, przeciwny .present?)

if Business.where(:user_id => current_user.id).present? 
    # less efficiant than using .exists? (see generated SQL for .exists? vs .present?) 
else 
    # ... 
end 

Wariant 3: wybór zmiennej w if

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

Opcja ta może być uznana za zapach kod niektórych linters (Rubocop na przykład).

Wariant 3b: przypisanie zmiennej

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

Można również użyć .find_by_user_id(current_user.id) zamiast .where(...).first


najlepszym rozwiązaniem:

  • Jeśli nie użyć obiektu Business (s): Wariant 1
  • Jeśli trzeba użyć obiektu Business (s): Option 3
+0

To nie działa.Przechowuje ten test i ładuje indeks html jak przy teście == zero (otrzymuję więc błąd: niezdefiniowana metoda "name" dla nil: NilClass). –

+0

Spróbuj najpierw przed wywołaniem prezentu – MrYoshiji

+0

Mam ten sam problem –

1

ActiveRecord # gdzie zwróci obiekt ActiveRecord :: relacji (które nigdy nie będzie zero). Spróbuj użyć .empty? na relacji do testu, czy zwróci wszystkie rekordy.

1

Po wywołaniu Business.where(:user_id => current_user.id) otrzymasz tablicę. Ta tablica może nie zawierać żadnych obiektów lub jednego lub wielu obiektów, ale nie będzie miała wartości NULL. W ten sposób czek == zero nigdy nie będzie prawdą.

Można spróbować wykonać następujące czynności:

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

więc sprawdzić liczbę elementów w tablicy i porównać je do zera.

lub można spróbować:

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

ten powróci jeden lub zero.

24

W tym przypadku Lubię używać metody exists? dostarczone przez ActiveRecord:

Business.exists? user_id: current_user.id 
3

z 'istnieje?':

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

z 'każdy?':

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

Jeśli używasz coś z .gdzie pamiętaj aby uniknąć kłopotów z zakresów i lepszego wykorzystania .unscoped

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

Lepsze wykorzystanie Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? aby uniknąć niepotrzebnego obciążenia relacji dla obiektu, który sprawdzasz. – Juanin

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

chciałbym zrobić to w ten sposób, jeśli potrzebne instancję zmiennej obiektu do pracy z :

if @business = Business.where(:user_id => current_user.id).first 
    #Do stuff 
else 
    #Do stuff 
end 
Powiązane problemy