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

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

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

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

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

Но он всегда возвращает true, даже если бизнес не существует...

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

Ответ 1

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

Метод 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: Использование .present? (или .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

Ответ 2

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

Business.exists? user_id: current_user.id

Ответ 3

с 'exists?':

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

с "any?":

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

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

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

Ответ 4

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

Ответ 5

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

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

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

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

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

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

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

Ответ 6

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

Ответ 7

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

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