Проверьте, существует ли запись из controllerа в Rails

В моем приложении Пользователь может создать Бизнес. Когда они запускают действие index в моем BusinessesController я хочу проверить, связан ли бизнес с current_user.id :

  • Если да: отобразите бизнес.
  • Если нет: redirect на new действие.

Я пытался использовать это:

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

Но он всегда возвращает истину, даже когда бизнес не существует …

Как проверить, существует ли запись в моей базе данных?

Почему ваш код не работает?

Метод where возвращает объект ActiveRecord :: Relation (действует как массив, который содержит результаты того, where ), он может быть пустым, но он никогда не будет равен 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 

Как проверить, существует ли хотя бы одна запись?

Вариант 1: Использование .exists?

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

Вариант 2: Использование. (или .blank? противоположность .present? )

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

Вариант 3: назначение переменной в выражении if

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

Этот вариант можно считать запахом кода некоторыми линтерами (например, Rubocop).

Вариант 3b: Переменное назначение

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

Вы также можете использовать .find_by_user_id(current_user.id) вместо .where(...).first


Лучший вариант:

  • Если вы не используете Business объект (ы): Вариант 1
  • Если вам нужно использовать Business объект (ы): Вариант 3

В этом случае мне нравится использовать exists? метод, предоставляемый ActiveRecord:

 Business.exists? user_id: current_user.id 

с ‘exists?’:

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

с любого?’:

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

Если вы используете что-то с .where, обязательно избегайте проблем с областями и лучше используйте .unscoped

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

ActiveRecord #, где будет возвращен объект ActiveRecord :: Relation (который никогда не будет равен нулю). Попробуйте использовать .путь? на отношение к тесту, если оно вернет любые записи.

Когда вы вызываете Business.where(:user_id => current_user.id) вы получите массив. В этом массиве не может быть объектов или одного или нескольких объектов, но он не будет пустым. Таким образом, проверка == nil никогда не будет правдой.

Вы можете попробовать следующее:

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

Таким образом, вы проверяете количество элементов в массиве и сравниваете их с нулем.

или вы можете попробовать:

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

это вернет один или ноль.

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

Я бы сделал это таким образом, если вам нужна переменная экземпляра объекта для работы с:

 if @business = Business.where(:user_id => current_user.id).first #Do stuff else #Do stuff end 
Давайте будем гением компьютера.