我可以在Rails中设置级联删除吗?


88

我知道这可能在Internet上的某个地方,但是我在Stackoverflow上找不到答案,所以我想我可能会在这里增加一些知识库。

我是Ruby和Rails的新手,但是我的公司已经对其进行了相当多的投资,因此我试图更详细地了解它。

我很难改变思维方式,从“模型”而不是从数据库设计应用程序,因此我试图弄清如何在数据库中经典地完成所有设计工作。 Rails模型代替。

因此,我给自己的最新任务是弄清楚如何配置Rails数据库模型以进行级联删除?有一个简单的方法吗?还是我必须进入MySql并进行设置?

Answers:


103

您也可以将:dependent选项设置为:delete_all。:delete_all将发出一条SQL语句以删除所有子记录。因此,使用:delete_all可能会为您带来更好的性能。

has_many :memberships, dependent: :delete_all

8
您的解释令人困惑。将使用单个SQL语句,但不会为每个子行调用destroy方法。您必须为此使用destroy_all。
约翰·托普利

@John-希望这些编辑能够消除混乱。感谢您指出了这一点。
Mike Breen

26
确保您了解使用:delete_all:destroy为此的区别。两者都将导致n从数据库中删除子成员身份(用于删除[需要引用]和销毁(如果其子对象具有从属销毁的级别)为1级),但是:destroy将实例化每个子对象并首先运行任何回调,而:delete_all直接运行数据库中的SQL DELETE语句。:destroy因此速度较慢,但​​是当记录被销毁时,它允许您进行回调。一端绕过Rails,另一端可能有n ^ x实例化。
jstim 2014年

2
我建议还设置数据库外键。这样一来,记录将被删除。请参阅我发布的以下答案。
亨德里克

66

是的,如果您正在使用has_many之类的关系,则可以这样做

has_many :memberships, dependent: :destroy

丹,所以我想我的下一个问题是,如果我运行db migration命令,是否可以在数据库中进行实际设置?还是级联完全由铁轨处理?
matt_dev

是的,它是由导轨处理的。(不过,请确保确实确实需要删除所有相关行。)
Stein G. Strindhaug's

@Matt-has_many行应该在您的模型类中,迁移不会为您添加。
Gareth

我更喜欢这种解决方案,因为如果从属模型具有另一个has_many关系,它也可以工作
tpei

25

与提供的答案相反,我强烈建议您也在数据库级别执行此操作。如果您有不同的进程或多线程环境,则可能会发生记录未正确删除的情况。此外,数据库外键使删除大量数据时的处理速度更快。

像在建议的答案中一样,执行以下操作:

has_many :memberships, dependent: :delete_all

但是,还要确保foreign_key在迁移中设置一个。这样数据库就可以自动为您删除记录。

假设您有用户模型,则在删除成员资格时要使这些值无效:

add_foreign_key :users, :memberships, on_delete: :nullify

您也可以在删除成员资格后删除所有模型

add_foreign_key :users, :memberships, on_delete: :cascade

因此,我可以同时使用“ has_many:memberships,dependent::delete_all”和“ add_foreign_key:users,:memberships,on_delete::cascade”吗?会运作良好吗?
Rubycon '18年

2
您甚至不需要delete_all在模型中进行设置。外键将帮助您在数据库级别正确删除所有内容。
亨德里克

3
我很好奇你们俩都发生时会发生什么。似乎它不应该产生负面影响,但是有人在进行AR和DB级别的实践方面有不好的经验吗?
詹姆斯·克莱因

1
数据库级别是我想要的。我认为这应该是公认的答案。其他似乎只在我的查询坚持标准ActiveRecord操作时才起作用。
Brett Beatty


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.