Destroy和Delete的区别

两者有什么区别

@model.destroy@model.delete

例如:

Model.find_by(col: "foo").destroy_all
//and
Model.find_by(col: "foo").delete_all

我用哪个真的重要吗?

134752 次浏览

基本上,“delete”直接向数据库发送查询以删除记录。在这种情况下,Rails不知道它正在删除的记录中有什么属性,也不知道是否有任何回调(比如before_destroy)。

“destroy”方法获取传递的id,使用“find”方法从数据库中获取模型,然后对其调用destroy。这意味着回调被触发。

如果你不想触发回调或者你想要更好的性能,你会想要使用“delete”。否则(大多数时候)你会想要使用“destroy”。

是的,这两种方法之间有一个主要的区别 如果你想在不调用模型回调的情况下快速删除记录,可以使用delete_all

如果你关心你的模型回调,那么使用destroy_all

来自官方文件

http://apidock.com/rails/ActiveRecord/Base/destroy_all/class

Destroy_all(条件= nil)公共

通过实例化每条记录来销毁匹配条件的记录 并调用它的destroy方法。执行每个对象的回调 (包括:依赖关联选项和 before_destroy/after_destroy观察者方法)。返回集合 被摧毁的物品;每一个都将被冻结,以反映 不应该做任何更改(因为它们不能被持久化)

注:实例化,回调执行,删除每条记录 当您一次删除许多记录时,可能会花费时间。它 每条记录至少生成一个SQL DELETE查询(或可能更多), 执行你的回调)。如果你想快速删除很多行, 不用考虑它们的关联或回调,使用delete_all即可 相反。< / p >

当你在一个ActiveRecord对象上调用destroydestroy_all时,ActiveRecord“销毁”过程被启动,它会分析你要删除的类,它会确定它应该为依赖项做什么,运行验证等。

当你在一个对象上调用deletedelete_all时,ActiveRecord只是尝试对db运行DELETE FROM tablename WHERE conditions查询,不执行其他ActiveRecord级任务。

基本上,destroy会运行模型上的任何回调,而delete不会。

Rails API:

  • < p > ActiveRecord::Persistence.delete

    删除数据库中的记录并冻结该实例,以反映不应进行任何更改(因为它们不能持久保存)。返回冻结的实例。

    只需在记录的主键上使用SQL DELETE语句删除该行,并且不执行任何回调。

    要强制执行对象的before_destroy和after_destroy回调或任何:依赖关联选项,请使用#destroy。

    李< /引用> < / >
  • < p > ActiveRecord::Persistence.destroy

    删除数据库中的记录并冻结该实例,以反映不应进行任何更改(因为它们不能持久保存)。

    有一系列与destroy相关的回调。如果before_destroy回调函数返回false,则动作被取消,destroy返回false。更多细节请参见ActiveRecord::Callbacks。

    李< /引用> < / >

delete只会从db中删除当前对象记录,而不会从db中删除其相关的子记录。

destroy将从db中删除当前对象记录,并从db中删除其关联的子记录。

它们的使用真的很重要:

如果你的多个父对象共享公共的子对象,那么在特定的父对象上调用destroy将删除在其他多个父对象中共享的子对象。

已经有很多答案了;我还想再来点。

文档:

对于has_many, destroy和destroy_all将始终调用被删除记录的destroy方法,以便运行回调。然而,delete和delete_all将根据:dependent选项指定的策略执行删除,或者如果没有给出:dependent选项,则将遵循默认策略。默认策略是什么都不做(保留外键并设置父id),除了has_many:through,其中默认策略是delete_all(删除连接记录,不运行它们的回调)。

delete字符对于ActiveRecord::Association.has_manyActiveRecord::Base的工作方式不同。对于后者,delete将执行SQL DELETE并绕过所有验证/回调。前者将基于传递给关联的:dependent选项执行。然而,在测试期间,我发现了以下副作用,回调只为delete而不是delete_all运行

dependent: :destroy例子:

class Parent < ApplicationRecord
has_many :children,
before_remove: -> (_) { puts "before_remove callback" },
dependent: :destroy
end


class Child < ApplicationRecord
belongs_to :parent


before_destroy -> { puts "before_destroy callback" }
end


> child.delete                            # Ran without callbacks
Child Destroy (99.6ms)  DELETE FROM "children" WHERE "children"."id" = $1  [["id", 21]]


> parent.children.delete(other_child)     # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms)  DELETE FROM "children" WHERE "children"."id" = $1  [["id", 22]]


> parent.children.delete_all              # Ran without callbacks
Child Destroy (1.0ms)  DELETE FROM "children" WHERE "children"."parent_id" = $1  [["parent_id", 1]]

例子:

Class User
has_many :contents, dependent: :destroy
end


user = User.last
user.delete -> only user
user.destroy -> delete user , and contents of user

delete将从db中删除当前记录(没有回调)

destroy将删除当前记录和相关记录(有回调)

delete_alldestroy_all也是如此