Ruby-on-rails 销毁和删除的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22757450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between Destroy and Delete
提问by Saggex
What is the difference between
之间有什么区别
@model.destroyand @model.delete
@model.destroy和 @model.delete
For example:
例如:
Model.find_by(col: "foo").destroy_all
//and
Model.find_by(col: "foo").delete_all
Does it really matter if I use the one or the other?
我使用其中一个或另一个真的很重要吗?
回答by
Basically destroyruns any callbacks on the model while deletedoesn't.
基本上destroy在模型上运行任何回调,而delete不会。
From the Rails API:
ActiveRecord::Persistence.deleteDeletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted). Returns the frozen instance.
The row is simply removed with an SQL DELETE statement on the record's primary key, and no callbacks are executed.
To enforce the object's before_destroy and after_destroy callbacks or any :dependent association options, use #destroy.
ActiveRecord::Persistence.destroyDeletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted).
There's a series of callbacks associated with destroy. If the before_destroy callback return false the action is cancelled and destroy returns false. See ActiveRecord::Callbacks for further details.
ActiveRecord::Persistence.delete删除数据库中的记录并冻结此实例以反映不应进行任何更改(因为它们无法持久化)。返回冻结的实例。
使用记录的主键上的 SQL DELETE 语句简单地删除该行,并且不执行任何回调。
要强制执行对象的 before_destroy 和 after_destroy 回调或任何 :dependent 关联选项,请使用 #destroy。
ActiveRecord::Persistence.destroy删除数据库中的记录并冻结此实例以反映不应进行任何更改(因为它们无法持久化)。
有一系列与销毁相关的回调。如果before_destroy 回调返回false,则操作被取消并且destroy 返回false。有关详细信息,请参阅 ActiveRecord::Callbacks。
回答by Taimoor Changaiz
deletewill only delete current object record from db but not its associated children records from db.
delete只会从 db 中删除当前对象记录,但不会从 db 中删除其关联的子记录。
destroywill delete current object record from db and also its associated children record from db.
destroy将从 db 中删除当前对象记录,并从 db 中删除其关联的子记录。
Their use really matters:
它们的使用非常重要:
If your multiple parent objects share common children objects, then calling destroyon specific parent object will delete children objects which are shared among other multiple parents.
如果您的多个父对象共享共同的子对象,则调用destroy特定的父对象将删除在其他多个父对象之间共享的子对象。
回答by nickcen
When you invoke destroyor destroy_allon an ActiveRecordobject, the ActiveRecord'destruction' process is initiated, it analyzes the class you're deleting, it determines what it should do for dependencies, runs through validations, etc.
当你调用destroy或destroy_all一个上ActiveRecord对象时,ActiveRecord“毁灭”的过程开始,分析了类,你要删除的,这决定了它应该做的依赖关系,通过验证等运行
When you invoke deleteor delete_allon an object, ActiveRecordmerely tries to run the DELETE FROM tablename WHERE conditionsquery against the db, performing no other ActiveRecord-level tasks.
当您调用delete或delete_all对象时,ActiveRecord仅尝试DELETE FROM tablename WHERE conditions针对数据库运行查询,不执行其他ActiveRecord级别的任务。
回答by jamesc
Yes there is a major difference between the two methods Use delete_all if you want records to be deleted quickly without model callbacks being called
是的,这两种方法有很大的不同,如果您希望在不调用模型回调的情况下快速删除记录,请使用 delete_all
If you care about your models callbacks then use destroy_all
如果您关心模型回调,请使用 destroy_all
From the official docs
来自官方文档
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all(conditions = nil) public
Destroys the records matching conditions by instantiating each record and calling its destroy method. Each object's callbacks are executed (including :dependent association options and before_destroy/after_destroy Observer methods). Returns the collection of objects that were destroyed; each will be frozen, to reflect that no changes should be made (since they can't be persisted).
Note: Instantiation, callback execution, and deletion of each record can be time consuming when you're removing many records at once. It generates at least one SQL DELETE query per record (or possibly more, to enforce your callbacks). If you want to delete many rows quickly, without concern for their associations or callbacks, use delete_all instead.
destroy_all(conditions = nil) public
通过实例化每条记录并调用其销毁方法来销毁符合条件的记录。执行每个对象的回调(包括 :dependent 关联选项和 before_destroy/after_destroy Observer 方法)。返回被销毁对象的集合;每个都将被冻结,以反映不应进行任何更改(因为它们无法持久化)。
注意:当您一次删除许多记录时,每条记录的实例化、回调执行和删除可能会非常耗时。它为每条记录至少生成一个 SQL DELETE 查询(或可能更多,以强制执行您的回调)。如果您想快速删除许多行,而不考虑它们的关联或回调,请改用 delete_all。
回答by Severin
Basically "delete" sends a query directly to the database to delete the record. In that case Rails doesn't know what attributes are in the record it is deleting nor if there are any callbacks (such as before_destroy).
基本上“删除”直接向数据库发送查询以删除记录。在这种情况下,Rails 不知道它正在删除的记录中有哪些属性,也不知道是否有任何回调(例如before_destroy)。
The "destroy" method takes the passed id, fetches the model from the database using the "find" method, then calls destroy on that. This means the callbacks are triggered.
“destroy”方法获取传递的id,使用“find”方法从数据库中获取模型,然后调用destroy。这意味着回调被触发。
You would want to use "delete" if you don't want the callbacks to be triggered or you want better performance. Otherwise (and most of the time) you will want to use "destroy".
如果您不希望触发回调或希望获得更好的性能,则可以使用“删除”。否则(大多数时候)你会想要使用“销毁”。
回答by David Zhang
A lot of answers already; wanted to jump on with a bit more.
已经有很多答案了;想再继续一点。
docs:
文档:
For has_many, destroy and destroy_all will always call the destroy method of the record(s) being removed so that callbacks are run. However delete and delete_all will either do the deletion according to the strategy specified by the :dependent option, or if no :dependent option is given, then it will follow the default strategy. The default strategy is to do nothing (leave the foreign keys with the parent ids set), except for has_many :through, where the default strategy is delete_all (delete the join records, without running their callbacks).
对于has_many,destroy 和destroy_all 将始终调用被删除记录的destroy 方法,以便运行回调。但是 delete 和 delete_all 将根据 :dependent 选项指定的策略进行删除,或者如果没有给出 :dependent 选项,则它将遵循默认策略。默认策略是什么都不做(保留父 id 设置的外键),除了 has_many :through,默认策略是 delete_all(删除连接记录,不运行它们的回调)。
The deleteverbage works differently for ActiveRecord::Association.has_manyand ActiveRecord::Base. For the latter, delete will execute SQL DELETEand bypass all validations/callbacks. The former will be executed based on the :dependentoption passed into the association. However, during testing, I found the following side effect where callbacks were only ran for deleteand not delete_all
该deleteverbage原理不同的ActiveRecord::Association.has_many和ActiveRecord::Base。对于后者,delete 将执行SQL DELETE并绕过所有验证/回调。前者将根据:dependent传递给关联的选项执行。但是,在测试过程中,我发现了以下副作用,其中仅运行回调delete而不运行delete_all
dependent: :destroyExample:
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" = [["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" = [["id", 22]]
> parent.children.delete_all # Ran without callbacks
Child Destroy (1.0ms) DELETE FROM "children" WHERE "children"."parent_id" = [["parent_id", 1]]

