ActiveRecord delete_all 方法更新而不是删除

问题描述 投票:0回答:3

我正在使用 Rails 多态关联,这样某些模型就有许多

cash_histories
子项,如下所示:

has_many :cash_histories, as: :cashable

但是当我尝试删除父级的所有现金历史记录时

@resource
,如下所示:

@resource.cash_histories.delete_all

我收到以下查询:

UPDATE "cash_histories" SET "cashable_id" = NULL WHERE "cash_histories"."cashable_id" = $1 AND "cash_histories"."cashable_type" = $2  [["cashable_id", 1], ["cashable_type", "ServiceOrder"]]

我无法理解这种行为,将关系 id 设置为 null 而不是删除,这将导致表中出现死行。为什么会这样?

我正在使用 Rails 4.1。

ruby-on-rails activerecord rails-activerecord ruby-on-rails-4.1
3个回答
42
投票

来自

delete_all
的 Rails API 文档:

从集合中删除所有记录。对于 has_many 关联,删除是根据 :dependent 选项指定的策略完成的。返回包含已删除记录的数组。

如果没有给出 :dependent 选项,那么它将遵循默认策略。 默认策略是:nullify。这会将外键设置为 NULL。 对于 has_many :through,默认策略是 delete_all。

因此,您只需将

:dependent
上的
has_many
选项设置为
:delete_all
:destroy
,具体取决于您想要的行为。

has_many :cash_histories, as: :cashable, dependent: :delete_all

来自

has_many
的 Rails API 文档:

如果对象与 dependent: :destroy 关联,则它们还将被销毁;如果它们与 dependent: :delete_all 关联,则对象将被删除。


3
投票

它仍然很奇怪,因为在其他地方它总是描述当所有者被摧毁时会发生什么。

控制关联对象在其所有者被删除时发生的情况 被毁:

:destroy 导致关联的对象也被销毁。

:delete_all 导致关联对象直接从数据库中删除(不执行回调)。

:nullify 导致外键设置为 NULL(不执行回调)。

:如果存在关联记录,restrict_with_exception 会导致引发异常。

:restrict_with_error 会导致在存在关联对象时将错误添加到所有者。


0
投票

要添加到当前答案中,从 Rails 7 开始,访问关联时,Active Record 返回的默认基础类是

ActiveRecord::Associations::CollectionProxy
:

@resource.cash_histories.class
# => CashHistory::ActiveRecord_Associations_CollectionProxy

但是当你在收集代理上调用

#all
时,你会得到一个
ActiveRecord::Relation
:

@resource.cash_histories.all.class
# => CashHistory::ActiveRecord_AssociationRelation

OP 遇到的问题是因为这些类具有不同的

#delete_all
方法签名。

对于集合代理,

#delete_all
方法接受依赖符号:

@resource.cash_histories.delete_all(:delete_all)
@resource.cash_histories.delete_all(:destroy)
@resource.cash_histories.delete_all(:destroy_async)
@resource.cash_histories.delete_all(:nullify)
@resource.cash_histories.delete_all

正如OP发现的那样,默认值是

:nullify

另一方面,关系类的#delete_all

方法
实现了:delete_all
依赖符号,正如您所期望的:

@resource.cash_histories.all.delete_all
希望对其他人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.