Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4: How to cancel save on a "before_save" callback?

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 
like image 906
bigpotato Avatar asked May 23 '14 20:05

bigpotato


2 Answers

Rails 5

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_* callback throws :abort, all the later callbacks and the associated action are cancelled.

The following section on transactions continues:

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.

Rails 4

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.

like image 156
meagar Avatar answered Oct 01 '22 12:10

meagar


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 
like image 33
Marek Lipka Avatar answered Oct 01 '22 11:10

Marek Lipka