2006 年 4 月 28 日,星期五

关联不再是:依赖 => 真

由 marcel 发布

在 1.1 版本之前,自动销毁所有者自身销毁时的 has_many 关联的方法是在声明 has_many 时使用 :dependent:exclusively_dependent 选项。


class Account < ActiveRecord::Base
  has_many :members, :dependent => true
end


class Brand < ActiveRecord::Base
  has_many :products, :exclusively_dependent => true
end

:依赖选项会实例化所有关联对象并在每一个对象上调用 destroy。destroy 又会触发该关联模型上定义的回调,例如使用 before_destroyafter_destroy 声明的回调。

另一方面,:exclusively_dependent 选项不会实例化所有关联对象。而是生成一条 SQL 语句,删除关联记录而不首先为它们创建对象。当您不需要触发模型回调的灵活性时,这可以提高效率。

自 1.1 版起,收集关联记录的垃圾的 API 已合并到 :dependent 选项中。现在,您不是说 :dependent => true,而是将几个符号之一传递给 :dependent 选项,描述关联如何依赖于所有者。

声明 has many 为 :dependent => :destroy 与以前声明为 :dependent => true 相同。当所有者被销毁时,所有关联记录都会被实例化并销毁。


class Account < ActiveRecord::Base
  # Deprecated
  # has_many :members, :dependent => true
  
  # In favor of
  has_many :members, :dependent => :destroy
end

实现现在的已弃用的 :exclusively_dependent 配置的新方法是使用 :dependent => :delete_all 而不是 :dependent => :destroy


class Brand < ActiveRecord::Base
  # Deprecated
  # has_many :products, :exclusively_dependent => true

  # In favor of
  has_many :products, :dependent => :delete_all
end

命名 :destroy:delete_all 选项符号是因为它们对应于在模型对象上调用 destroy 与调用 delete 实现的行为。一个触发回调,另一个只生成 delete SQL 语句。

顺便说一下,另一个有效的选项是 :dependent => :nullify,它类似于 :dependent => :delete_all,只是它不删除关联的记录,而是仅将其外键设置为 NULL。这会有效地删除关联,而不会从数据库表中删除关联的记录。

与往常一样,:dependent => :destroy:dependent => :delete_all 的语义是相互排斥的,新的 API 让这一点更加明显。

需要注意的是,在设置 has many 关联时,声明依赖项不是必需的。当您需要这种功能时,它只是一种选择。

请记住,目前仍然支持 :dependent => true:exclusively_dependent => true,但它们已被标记为已弃用,未来可能会被取代。