【问题标题】:ActiveRecord delete_all method updating instead of deletingActiveRecord delete_all 方法更新而不是删除
【发布时间】:2014-05-27 01:35:31
【问题描述】:

我正在使用 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。

【问题讨论】:

  • 在尝试理解这种行为时,请记住您将 delete_all 方法发送到 关联,而不是直接发送到模型。

标签: ruby-on-rails activerecord rails-activerecord ruby-on-rails-4.1


【解决方案1】:

来自delete_all 的 Rails API 文档:

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

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

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

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

来自has_many 的 Rails API 文档:

如果对象与dependent: :destroy 相关联,则对象将被另外销毁,如果与dependent: :delete_all 相关联,则将被删除。

【讨论】:

【解决方案2】:

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

控制当关联对象的所有者是 销毁:

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

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

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

:restrict_with_exception 会在有关联记录时引发异常。

:restrict_with_error 如果存在关联对象,则会将错误添加到所有者。

【讨论】:

  • 即使当前文档说“不尊重” delete_all(conditions = nil) public 删除匹配条件的记录而不先实例化记录,因此不调用destroy方法也不调用回调。这是一条直接进入数据库的 SQL DELETE 语句,比 destroy_all 高效得多。但是要小心关系,特别是:不遵守在关联上定义的依赖规则。返回受影响的行数。
猜你喜欢
  • 1970-01-01
  • 2012-02-04
  • 2017-08-26
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-06
  • 2012-03-19
相关资源
最近更新 更多