I have complicated models / forms. I don't want repeated records, so I want to merge records that have similar attributes. How would I cancel "save" using a before_save callback? This is what I'm thinking:
class ProductsColor < ActiveRecord::Base before_save :check_for_similar_record def check_for_similar_record if ProductsColor.exist?(color_id: self.color_id, product_id: self.product_id) # merge values with existing ProductsColor and stop self from saving end end end
As of Rails 5, you can signal that an operation should be aborted by explicitly calling throw :abort
inside your callback. The documentation section on cancelling callbacks (now) states:
If a
before_*
callbackthrows :abort
, all the later callbacks and the associated action are cancelled.
The following section on transactions continues:
If a
before_*
callback cancels the action aROLLBACK
is issued. You can also trigger aROLLBACK
raising an exception in any of the callbacks, includingafter_*
hooks.
The story is pretty similar to with Rails 5, except that callbacks should instead return false
. The corresponding parts of the documentation helpfully states
If a
before_*
callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled.
Followed by
If a before_* callback cancels the action a
ROLLBACK
is issued. You can also trigger a ROLLBACK raising an exception in any of the callbacks, including after_* hooks.
To prevent record from being saved, you should simply return false
:
def check_for_similar_record if ProductsColor.exists?(color_id: self.color_id, product_id: self.product_id) # merge values false else true 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