检查Rails中的控制器是否存在记录


91

用户可以在我的应用中创建业务。当他们触发index我的操作时,我BusinessesController要检查某个业务是否与current_user.id

  • 如果是:显示业务。
  • 如果否:重定向到new操作。

我试图用这个:

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

但是即使业务不存在,它也总是返回true。

如何测试数据库中是否存在记录?


1
where如果没有记录,使用将返回一个空数组。而且[]并不相等nil
mind.blank

那一个unless Business.find_by_user_id(current_user.id)呢?
横街

Answers:


229

为什么您的代码不起作用?

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

那似乎没有用。它一直通过该测试并像== nil测试一样加载索引html(所以我遇到一个错误:nil:NilClass的未定义方法“名称”)。

先打电话先试下礼物
MrYoshiji

我遇到了同样的问题

哦,那是我的错,我感到困惑,您需要进行测试blank?
MrYoshiji 2013年

谢谢你的工作!我不应该注意到这个错误。您能告诉我为什么== 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?

更好地使用Business.unscoped.where(:user_id => current_user.id).pluck(:id).any吗?以避免不必要的关系负载正在检查的对象。
胡安

1

ActiveRecord#where将返回ActiveRecord :: Relation对象(永远不会为零)。尝试使用.empty吗?关于要测试的关系是否将返回任何记录。


1

你打电话时 Business.where(:user_id => current_user.id)您将得到一个数组。此数组中可能没有对象,也可能没有一个或多个对象,但不会为null。因此,check == nil将永远不会为真。

您可以尝试以下操作:

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

因此,您检查数组中元素的数量,并将它们与零进行比较。

或者您可以尝试:

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

这将返回一或零。



0

如果您需要使用该对象的实例变量来执行此操作,我将采用这种方式:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.