轨道上的红宝石 - 销毁和删除之间的区别



两者有什么区别

@model.destroy@model.delete

例如:

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

我使用其中一个真的重要吗?

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

从 Rails API:

  • ActiveRecord::Persistence.delete

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

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

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

  • ActiveRecord::Persistence.destroy

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

    有一系列与销毁相关的回调。如果before_destroy回调返回 false,则取消操作,销毁返回 false。有关更多详细信息,请参阅 ActiveRecord::回调。

delete只会

从数据库中删除当前对象记录,而不会从数据库中删除其关联的子记录。

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

它们的使用非常重要:

如果多个父对象共享公共子对象,则在特定父对象上调用destroy将删除在其他多个父对象之间共享的子对象。

当您在ActiveRecord对象上调用destroydestroy_all时,将启动ActiveRecord"销毁"过程,它会分析您要删除的类,确定它应该对依赖项执行的操作,运行验证等。

当您对对象调用deletedelete_all时,ActiveRecord只是尝试对数据库运行DELETE FROM tablename WHERE conditions查询,而不执行其他ActiveRecord级任务。

是的,这两种方法之间存在重大差异如果您希望在不调用模型回调的情况下快速删除记录,请使用 delete_all

如果您关心模型回调,请使用destroy_all

来自官方文档

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

destroy_all(条件 = 无)公共

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

注意:实例化、回调执行和删除每条记录 一次删除多条记录时可能会很耗时。它 每条记录至少生成一个 SQL DELETE 查询(或可能更多, 以强制执行您的回调)。如果要快速删除许多行, 无需担心其关联或回调,请使用delete_all 相反。

示例:

Class User
  has_many :contents, dependent: :destroy
end
user = User.last
user.delete -> only user
user.destroy -> delete user , and contents of user

delete将从数据库中删除当前记录(无回调)

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

delete_alldestroy_all也是如此

已经有很多答案了; 想跳上去更多。

文档:

对于has_many,销毁和destroy_all将始终调用要删除的记录的销毁方法,以便运行回调。但是,删除和delete_all将根据 :d ependent 选项指定的策略进行删除,或者如果没有给出 :d ependent 选项,则它将遵循默认策略。默认策略是不执行任何操作(保留设置父 id 的外键),除了 has_many :through,其中默认策略是delete_all(删除连接记录,而不运行其回调)。

delete动词对ActiveRecord::Association.has_manyActiveRecord::Base的工作方式不同。对于后者,删除将执行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]]

基本上"删除"将查询直接发送到数据库以删除记录。在这种情况下,Rails 不知道它正在删除的记录中有哪些属性,也不知道是否有任何回调(例如 before_destroy )。

"destroy"方法获取

传递的id,使用"find"方法从数据库中获取模型,然后调用销毁。这意味着回调被触发。

如果您不希望触发回调或想要更好的性能,则需要使用"删除"。否则(大多数时候)您将需要使用"销毁"。

最新更新