Sammary
Add #destroy_all!
to ActiveRecord
and performs deletion processing that raises an exception if it fails.
Background
There is Already have destroy_all
, but there are scenes where I want to raise an exception if it fails, for example when I want to control transactions.
I also want destroy_by!
for the same reason, but I don’t have it now.
After the destroy_all!
method has been added, we can use it to add destroy_by!
Proposal
If the before_destroy
callback throws abort the action is cancelled and destroy_all!
raises ActiveRecord::RecordNotDestroyed
.
It is not necessary to execute rollback processing. If there is more than one target record and you want to ensure that all records are deleted, you should realize this by explicitly using transaction to cause rollback.
class User < ApplicationRecord
before_destroy do
throw :abort if id == 3
end
end
ActiveRecord::Base.transaction do
User.where(id: 1..3).destroy_all!
end
=> TRANSACTION (1.5ms) BEGIN
user Load (1.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` BETWEEN 1 AND 3
user Destroy (1.2ms) DELETE FROM `users` WHERE `users`.`id` = 1
user Destroy (1.1ms) DELETE FROM `users` WHERE `users`.`id` = 2
TRANSACTION (4.4ms) ROLLBACK
ActiveRecord::RecordNotDestroyed: Failed to destroy the record
Also, if the deletion is successful, an Array containing the target object that was successfully deleted is returned.
Correspondence
This Proposal made a PR before, but it was closed without being activated.
But I’m still looking for this feature so if community like this proposal, I’d like to work on this feature. What do you think?