我有以下 ActiveRecord 调用:
@payment = account.business.payments.find(params[:id])
它会在关联中搜索 id 为
payment
的 params[:id]
。但是,这会引发 RecordNotFound 异常。
我想调用
exists?
来查看记录是否存在以避免引发异常。这样做 Payment.exists?(account.business.payments.find(params[:id]))
不起作用。
我只想搜索
payments
那个belong_to
那个business
,而不是通过执行Payment.exists?(:id => params[:id])
进行的所有付款。这样我就可以知道这是该特定帐户的企业付款。
我该怎么做?
注意:
account
has_one business
和 business
has_many payments
。
使用
where
而不是 find
,它将返回代表 0 条或更多记录的 ActiveRecord::Relation
,您可以从中链接 .exists?
:
@payments = account.business.payments.where(id: params[:id])
if @payments.exists?
# ...
end
如果您只需要检查是否存在:
account.business.payments.where(:id => params[:id]).exists?
如果您打算使用此记录,请调用
.first
而不是 exists?
,因为预计只有 1 条记录。顺便说一句,您也可以使用动态查找器(Rails 4 中已弃用)来执行此操作:
account.business.payments.find_by_id(params[:id])
如果不存在记录,这将返回
nil
(而不是爆炸)。
您必须记住,使用
present?
会强制 ActiveRecord 从数据库加载整个集合,这显然并不总是理想的:
user.posts.present?
=> SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 ORDER BY `sales`.`id` ASC
如果您想检查数据库中是否存在集合并且不需要数据,请使用
any?
user.posts.any?
=> SELECT 1 AS one FROM `posts` WHERE `posts`.`user_id` = 1 LIMIT 1
此外,不带任何参数的
exists?
与 any?
的作用相同
user.posts.exists?
=> SELECT 1 AS one FROM `posts` WHERE `posts`.`user_id` = 1
但是你可以用这个做更多的事情:https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-exists-3F
如果我错了,有人可以否决,但我会建议
account.business.payments.where(:id => params[:id]).pluck(:id).present?
通过执行 pluck,您将跳过关联对象的实例化。 这意味着它们不必加载到内存中,如果您经常这样做,这将节省一些周期
您可以将您的关联用于存在吗?
Business.find(business_id).payments.exists?(payment_id)
如果该企业存在付款,则应返回 true。
更现代的解决方案是将
where
替换为 exists?
,如下所示:
object.association.exists?(attribute: "value")