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.
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.
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.
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.
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]]
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".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With