在 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
:dependent 选项会实例化所有关联的对象,并对每个对象调用 destroy。destroy 又会触发在该关联模型上定义的 callback,例如用 before_destroy 和 after_destroy 声明的 callback。
另一方面,:exclusively_dependent 选项不会实例化所有关联的对象。它只会生成一个单独的 SQL 语句,在不先为每个记录创建对象的情况下删除关联的记录。当您不需要触发模型 callback 的灵活性时,这可以提高效率。
自 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 所达到的行为。前者触发 callback,后者仅生成 delete SQL 语句。
顺便说一下,另一个有效的选项是 :dependent => :nullify,它类似于 :dependent => :delete_all,只是它不会删除关联的记录,而是将它们的外键设置为 NULL。这有效地删除了关联,而没有从数据库表中删除关联的记录。
一如既往,:dependent => :destroy 和 :dependent => :delete_all 的语义是互斥的,而这个新的 API 使这一点更加明显。
值得注意的是,在设置 has many 关联时,声明依赖项不是必需的。它只是一个选项,用于当您需要这种功能时。
请记住,目前 :dependent => true 和 :exclusively_dependent => true 仍然受支持,但它们已被标记为已弃用,并可能在未来被移除。