I am trying to prevent a record from being destroyed if there are children.
class Submission < ActiveRecord::Base has_many :quotations, :dependent => :destroy before_destroy :check_for_payments def quoted? quotations.any? end def has_payments? true if quotations.detect {|q| q.payment} end private def check_for_payments if quoted? && has_payments? errors[:base] << "cannot delete submission that has already been paid" false end end end class Quotation < ActiveRecord::Base #associations belongs_to :submission has_one :payment_notification has_one :payment before_destroy :check_for_payments private def check_for_payments if payment_notification || payment errors[:base] << "cannot delete quotation while payment exist" return false end end end
When I test this code the before_destroy :check_for_payments prevents the Quotation record from being deleted.
However the :check_for_payments in the Submission before_destroy callback does not stop the Submission from being deleted.
How can I stop the Submission with payments from being destroyed?
Show activity on this post. Yes.
Basically destroy runs any callbacks on the model while delete doesn't. 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.
Rails delete operation using destroy method By using destroy, you can delete the record from rails as well as its other existing dependencies. So in the context of our rails application, if we delete a book record using the destroy function, the authors associated with the book will also be deleted.
Active Record Callbacks are hooks to which we can register methods in our models. These hooks are executed in various stages of an Active Record object lifecycle. The following callbacks are run when an object is created. These callbacks are executed in the order in which they are listed below.
In Rails 5 you have to throw :abort
otherwise it won't work. (even returning false
)
Also, you should add prepend: true
to the callback, to make sure it runs before the dependent: :destroy
on the parent models.
Something like this should work:
class Something < ApplicationRecord before_destroy :can_destroy?, prepend: true private def can_destroy? if model.something? self.errors.add(:base, "Can't be destroy because of something") throw :abort end end end
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