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

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

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

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

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

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

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

8 ответов

Решение

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

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

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

Business.exists? user_id: current_user.id

С "существует?":

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?

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

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

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

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

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

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

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

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

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

Что-то новое попробовать (:

Присвоить переменную или вернуть

      return unless @business = Business.where(user_id: current_user.id).first

Метод завершит работу в этот момент, если не будет найдено предприятий с идентификатором текущего пользователя, или присвоит переменную экземплярак первому бизнес-объекту.

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

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
Другие вопросы по тегам