来自精美手册 http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many:
has_many(名称、范围 = nil、选项 = {}、&扩展名)
[...]
-
:dependent
Controls what happens to the associated objects when their owner is destroyed. Note that these are implemented as callbacks, and Rails executes callbacks in order. Therefore, other similar callbacks may affect the :dependent
behavior, and the :dependent
behavior may affect other callbacks.
-
:destroy
导致所有关联的对象也被销毁。
-
:delete_all
导致所有关联的对象直接从数据库中删除(因此不会执行回调)。
- [...]
So :delete_all
确实处理外键,但是由于没有调用回调,因此它只深入一层。所以这在Company
:
has_many :projects, dependent: :delete_all
意味着调用#destroy
在公司上会直接删除关联的projects
从数据库中。但那不会看到这个:
has_many :tasks, dependent: :delete_all
你有的Project
并且您最终尝试删除仍在中引用的项目tasks
如错误消息所示。
您可以将所有关联切换到dependent: :destroy
,这将从数据库中取出所有内容,然后再销毁它们,并且将调用回调(这将从数据库中加载更多内容,只是为了销毁它们,这将从数据库中加载更多内容......)。最终结果将是大量数据库活动,但所有外键都将得到正确遵循。
或者,您可以通过指定将逻辑放在它通常所属的数据库中on delete cascade关于外键约束 https://www.postgresql.org/docs/current/static/ddl-constraints.html#DDL-CONSTRAINTS-FK:
CASCADE 指定当删除引用的行时,引用它的行也应自动删除
Your add_foreign_key
调用看起来像:
add_foreign_key "projects", "companies", on_delete: :cascade
add_foreign_key "tasks", "projects", on_delete: :cascade
add_foreign_key "task_times", "tasks", on_delete: :cascade
在这种情况下。你可能想离开dependent: :delete_all
在您的模型中作为有关正在发生的事情的提醒,或者您可以给自己留下评论。