Difference between Destroy and Delete

前端 未结 6 912
慢半拍i
慢半拍i 2020-11-27 11:00

What is the difference between

@model.destroy and @model.delete

For example:

Model.find_by(col: \"foo\").destroy_         


        
相关标签:
6条回答
  • 2020-11-27 11:30

    Basically destroy runs any callbacks on the model while delete doesn't.

    From the Rails API:

    • ActiveRecord::Persistence.delete

      Deletes 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.destroy

      Deletes 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.

    0 讨论(0)
  • 2020-11-27 11:37

    When you invoke destroy or destroy_all on an ActiveRecord object, 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.

    When you invoke delete or delete_all on an object, ActiveRecord merely tries to run the DELETE FROM tablename WHERE conditions query against the db, performing no other ActiveRecord-level tasks.

    0 讨论(0)
  • 2020-11-27 11:42

    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).

    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.

    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".

    0 讨论(0)
  • 2020-11-27 11:49

    delete will only delete current object record from db but not its associated children records from db.

    destroy will delete current object record from db and also its associated children record from db.

    Their use really matters:

    If your multiple parent objects share common children objects, then calling destroy on specific parent object will delete children objects which are shared among other multiple parents.

    0 讨论(0)
  • 2020-11-27 11:52

    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

    If you care about your models callbacks then use destroy_all

    From the official docs

    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.

    0 讨论(0)
  • 2020-11-27 11:57

    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).

    The delete verbage works differently for ActiveRecord::Association.has_many and ActiveRecord::Base. For the latter, delete will execute SQL DELETE and bypass all validations/callbacks. The former will be executed based on the :dependent option passed into the association. However, during testing, I found the following side effect where callbacks were only ran for delete and not delete_all

    dependent: :destroy Example:

    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]]
    
    0 讨论(0)
提交回复
热议问题