Sprawdź, czy istnieje rekord z kontrolera w Railsach


91

W mojej aplikacji Użytkownik może założyć Firmę. Kiedy wyzwalają indexakcję w moim BusinessesControllerChcę sprawdzić, czy Firma jest związana z current_user.id:

  • Jeśli tak: wyświetl firmę.
  • Jeśli nie: przekieruj do newakcji.

Próbowałem tego użyć:

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

Ale zawsze zwraca prawdę, nawet jeśli firma nie istnieje ...

Jak mogę sprawdzić, czy rekord istnieje w mojej bazie danych?


1
Użycie wherezwróci pustą tablicę, jeśli nie ma żadnych rekordów. I []nie równa sięnil
— mind.blank

A co z tylko unless Business.find_by_user_id(current_user.id)?
— Hengjie

Odpowiedzi:


231

Dlaczego twój kod nie działa?

Że wheremetoda zwraca ActiveRecord :: Relacja obiektu (działa jak tablica, która zawiera wyniki Spośród where), to może być pusty, ale to nigdy nie będzienil .

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 istnieje co najmniej jeden rekord?

Opcja 1: używanie.exists?

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

Opcja 2: używanie .present?(lub .blank?przeciwieństwo .present?)

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

Opcja 3: przypisanie zmiennej w instrukcji if

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

Tę opcję można uznać za zapach kodu przez niektóre lintery (na przykład Rubocop).

Opcja 3b: przypisanie zmiennych

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

Możesz także użyć .find_by_user_id(current_user.id)zamiast.where(...).first


Najlepsza opcja:

  • Jeśli nie korzystasz z Businessobiektów: opcja 1
  • Jeśli potrzebujesz skorzystać z Businessobiektów: opcja 3

To nie wydawało się działać. Wciąż przechodzi ten test i ładuje indeks html, tak jak w przypadku testu == nil (więc pojawia się błąd: undefined method `name 'for nil: NilClass).

Wypróbuj jako pierwszy przed wywołaniem prezentu
— MrYoshiji

Mam ten sam problem

Och, to moja wina, byłem zdezorientowany, musisz przetestowaćblank?
— MrYoshiji

Dzięki, że zadziałało! Nie powinienem był zauważyć tego błędu. Czy możesz mi powiedzieć, dlaczego sprawdzenie == nil nie zadziałało?

29

W tym przypadku lubię skorzystać z exists?metody udostępnionej przez ActiveRecord:

Business.exists? user_id: current_user.id

Istnieje? z lub możliwe?
— Imran Ahmad

5

z „istnieje?”:

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

z jakimkolwiek?':

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

Jeśli używasz czegoś z .where, unikaj problemów z celownikami i lepiej używaj .unscoped

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

Lepiej użyj Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? aby uniknąć niepotrzebnego obciążenia relacji dla sprawdzanego obiektu.
— Juanin

1

ActiveRecord # gdzie zwróci obiekt ActiveRecord :: Relation (który nigdy nie będzie zerowy). Spróbuj użyć .empty? w związku z testem, czy zwróci jakiekolwiek rekordy.


1

Kiedy zadzwonisz 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. Tak więc check == nil nigdy nie będzie prawdziwe.

Możesz spróbować następujących rzeczy:

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

Więc sprawdzasz liczbę elementów w tablicy i porównujesz je do zera.

lub możesz spróbować:

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

to zwróci jeden lub zero.


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

0

Zrobiłbym to w ten sposób, gdybyś potrzebował zmiennej instancji obiektu do pracy:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.