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

91

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

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

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

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

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

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

MrYoshiji
источник
1
Использование whereвернет пустой массив, если нет записей. И []не равняетсяnil
mind.blank
А как насчет просто unless Business.find_by_user_id(current_user.id)?
Hengjie
возможный дубликат проверки, возвращает ли ActiveRecord find результат
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Ответы:

231

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

В whereметоде возвращает ActiveRecord :: Отношение объект (действует как массив , который содержит результаты этого 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
MrYoshiji
источник
Похоже, это не сработало. Он продолжает проходить этот тест и загружать индексный html, как с тестом == nil (поэтому я получаю сообщение об ошибке: undefined method `name 'для nil: NilClass).
Попробуй сначала, прежде чем звонить, присутствует
MrYoshiji
У меня такая же проблема
О, это моя вина, что я blank?
запуталась
Спасибо, что сработало! Я не должен был замечать эту ошибку. Не могли бы вы мне сказать, почему не сработала проверка == nil?
29

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

Business.exists? user_id: current_user.id
Хамед
источник
Существует? с ИЛИ возможно?
Imran Ahmad
5

с 'существует?':

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?
user2427993
источник
Лучше используйте Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? чтобы избежать ненужной нагрузки на отношения проверяемого объекта.
Хуанин
1

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

Пульце
источник
1

При вызове 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?

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

маримаф
источник
1
business = Business.where(:user_id => current_user.id).first
if business.nil?
# no business found
else
# business.ceo = "me"
end
Нино ван Хофф
источник
0

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

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
user3633260
источник