Проверьте, существует ли запись из контроллера в 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