【问题标题】:Difference between Destroy and Delete销毁和删除的区别
【发布时间】:2014-05-10 13:10:03
【问题描述】:

有什么区别

@model.destroy@model.delete

例如:

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

我使用一个或另一个真的很重要吗?

【问题讨论】:

    标签: ruby-on-rails destroy delete-row


    【解决方案1】:

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

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

    如果您不希望触发回调或希望获得更好的性能,您可能需要使用“删除”。否则(大部分时间)你会想要使用“destroy”。

    【讨论】:

      【解决方案2】:

      是的,这两种方法有很大区别 如果您希望在不调用模型回调的情况下快速删除记录,请使用 delete_all

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

      来自官方文档

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

      destroy_all(conditions = nil) public

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

      注意:每条记录的实例化、回调执行和删除 一次删除多条记录时可能会很耗时。它 每条记录至少生成一个 SQL DELETE 查询(或者可能更多, 强制执行您的回调)。如果你想快速删除很多行, 不用担心它们的关联或回调,使用 delete_all 而是。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

          来自Rails API

          • ActiveRecord::Persistence.delete

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

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

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

          • ActiveRecord::Persistence.destroy

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

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

          【讨论】:

          • 您好@user740584 - 感谢您的回答。 “在模型上运行任何回调”是什么意思?
          • @BKSpureon 他的意思是 ActiveRecord::Callbacks:api.rubyonrails.org/classes/ActiveRecord/Callbacks.html。一个这样的回调是model#before_destroy,它可用于在某些条件下停止最终的destroy() 调用。
          【解决方案5】:

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

          destroy 将从 db 中删除当前对象记录以及从 db 中关联的子记录。

          它们的使用真的很重要:

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

          【讨论】:

          • 出色的答案。谢谢。我要补充一点,据我所知,术语是孩子们被“杀死”。残忍的杀婴。
          • 在生产环境中的大多数情况下,您都希望使用 'destroy'
          • 不,这没有必要。
          • 我认为您应该为 destroy 使用的词是 descendants,而不是 children:根据文档,destroy “创建一个新的从属性中提取对象,然后对其调用destroy。” rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
          【解决方案6】:

          已经有很多答案了;想继续前进。

          docs:

          对于 has_many,destroy 和 destroy_all 将始终调用要删除的记录的 destroy 方法,以便运行回调。但是 delete 和 delete_all 将根据 :dependent 选项指定的策略进行删除,或者如果没有给出 :dependent 选项,那么它将遵循默认策略。默认策略是什么都不做(保留设置了父 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]]
          

          【讨论】:

            【解决方案7】:

            例子:

            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 也一样

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-07-05
              • 1970-01-01
              相关资源
              最近更新 更多