Reputation: 1287
I have Product
which has many product_variants
. And ProductVariant
has many document_items
. It is forbidden to destroy product_variant
if it's document_items
are not empty. And when I destroy
product, I want to delete all variants or nothing.
This setup works
class Product
has_many :product_variant, dependent: :destroy, inverse_of: :product
end
class ProductVariant
has_many :document_items, dependent: :restrict_with_error, inverse_of: :product_variant
end
If there is document_item
binded to product_variant
of product
.
pv = product.product_variants.first
pv.destroy # => false,
pv.errors.messages #=> { base: ['Cannot delete variant, because there is dependent document_item'] })
product.destroy # => false
product.errors.messages # => []
BUT. I would like to add some clarifying errors to product
.
There are two ways:
1) overwrite destroy
method:
def destroy
destroy_result = super
copy_errors_from_associations if destroy_result == false
destroy_result
end
which works as expected, but Rubocop says
Rails/ActiveRecordOverride: Use before_destroy, around_destroy, or after_destroy callbacks instead of overriding the Active Record method destroy.
2) using around_destroy
:
around_destroy :propagate_errors_from_associations_on_failed_destroy
def propagate_errors_from_associations_on_failed_destroy
destroy_result = yield
copy_errors_from_associations if destroy_result == false
end
Which copy no error. It seems that run of propagate_errors_from_associations_on_failed_destroy
return immediately on first line, if yield
returns false (actual deletion is aborted)
So I would like to know how I should setup the around_destroy
callback to check result of destroy
and if it is false, do something with errors.
Upvotes: 0
Views: 315
Reputation: 21
yield
does not returns false when deleting failed. It throws ActiveRecord::RecordNotDestroyed
exception.
Rescuing from exception should work.
def propagate_errors_from_associations_on_failed_destroy
yield
rescue ActiveRecord::RecordNotDestroyed => e
copy_errors_from_associations
raise e
end
Upvotes: 2