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.