【问题标题】:Check if record exists from controller in Rails检查Rails中的控制器是否存在记录
【发布时间】:2013-05-16 23:16:13
【问题描述】:

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

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

我试图用这个:

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

但是即使业务不存在也总是返回true...

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

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-3 activerecord exists


【解决方案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

此选项可能被某些 linter(例如 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 的未定义方法“名称”)。
  • 先试一下再打电话给present
  • 哦,那是我的错,我弄糊涂了,你需要用blank?进行测试
  • 感谢工作!我不应该注意到这个错误。你能告诉我为什么 == nil 检查不起作用吗?
  • 是的,请稍等,我会更新我的答案,也不要在.blank? 之前使用.first ;)
【解决方案2】:

在这种情况下,我喜欢使用 ActiveRecord 提供的exists? 方法:

Business.exists? user_id: current_user.id

【讨论】:

  • 存在吗? OR 可能吗?
【解决方案3】:

带有“存在吗?”:

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?以避免对您正在检查的对象造成不必要的关系负载。
【解决方案4】:

ActiveRecord#where 将返回一个 ActiveRecord::Relation 对象(永远不会为零)。尝试使用 .empty?在关系上测试它是否会返回任何记录。

【讨论】:

    【解决方案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?
    

    这将返回 1 或 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
        

        【讨论】:

          猜你喜欢
          • 2016-08-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-07
          • 1970-01-01
          • 2023-03-22
          • 1970-01-01
          相关资源
          最近更新 更多