Given this example:
class Server < ActiveRecord::Base
has_many :clients,:dependent => :destroy
after_destroy: delete_server_directory
end
class Client < ActiveRecord::Base
belongs_to :server
before_destroy :copy_some_important_stuff_from_the_server_directory_before_its_too_late
end
Will this be the order of destruction when I call server.destroy
?
Server#clients
, along with Client
's before/after_destroy
callbacksServer
will be destroyedServer
's after_destroy
callbackDependent is an option of Rails collection association declaration to cascade the delete action. The :destroy is to cause the associated object to also be destroyed when its owner is destroyed.
The standard way to delete associated data in Rails is to let ActiveRecord handle it via dependent: :destroy . In the following example, when the parent model ( author ) is deleted, all data in the dependent models will get deleted by ActiveRecord as well. There is an indexed foreign key, but no foreign key constraint.
Rails Delete operation using delete method Unlike the destroy method, with delete, you can remove a record directly from the database. Any dependencies to other records in the model are not taken into account. The method delete only deletes that one row in the database and nothing else.
If you use delete_all , it will skip all the destroy callbacks for the records that you're deleting (helpful for when you don't want these to run) and it will return the number of records that have been deleted.
You can very easily test. I took your code, and implemented the callbacks with a simple call to puts
. Then launched script/console
and had ActiveRecord log to the console:
>> ActiveRecord::Base.logger = Logger.new(STDOUT)
=> #<Logger:0x0000000308d2f0 ...>
Set up some basic environment:
>> a = Client.create :name => 'Client 1'
Client Create (0.4ms) INSERT INTO "clients" ("name", "server_id") VALUES('Client 1', NULL)
=> #<Client id: 1, name: "Client 1", server_id: nil>
>> b = Client.create :name => 'Client 2'
Client Create (0.5ms) INSERT INTO "clients" ("name", "server_id") VALUES('Client 2', NULL)
=> #<Client id: 2, name: "Client 2", server_id: nil>
>> server = Server.create :name => 'The Server'
Server Create (0.3ms) INSERT INTO "servers" ("name") VALUES('The Server')
=> #<Server id: 1, name: "The Server">
>> server.clients = [a, b]
Client Load (0.4ms) SELECT * FROM "clients" WHERE ("clients".server_id = 1)
Client Update (0.4ms) UPDATE "clients" SET "server_id" = 1 WHERE "id" = 1
Client Update (0.2ms) UPDATE "clients" SET "server_id" = 1 WHERE "id" = 2
=> [#<Client id: 1, name: "Client 1", server_id: 1>, #<Client id: 2, name: "Client 2", server_id: 1>]
And here's the gist of it:
>> server.destroy
>>> copy_some_important_stuff_from_the_server_directory_before_its_too_late called!
Client Destroy (0.5ms) DELETE FROM "clients" WHERE "id" = 1
>>> copy_some_important_stuff_from_the_server_directory_before_its_too_late called!
Client Destroy (0.2ms) DELETE FROM "clients" WHERE "id" = 2
Server Destroy (0.2ms) DELETE FROM "servers" WHERE "id" = 1
>>> delete_server_directory called!
=> #<Server id: 1, name: "The Server">
So it looks like you were dead on target. :)
P.S.
after_destroy
.before_destroy
, as seen in your example.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