How to raise an ActiveRecord::Rollback exception and return a value together?
You could store the value you want returned from the function in a variable and return that outside the transaction block. E.g.
def save_with_place_in_set(parent_id) return_value = false Category.transaction do if !save_without_place_in_set return_value = false elsif !validate_move parent_id return_value = false raise ActiveRecord::Rollback else place_in_nested_set parent_id return_value = true end end return return_value end
I've set the return_value to false initially as the only other way you can get out of that transaction block is if one of the other methods raises ActiveRecord::Rollback
I believe.
Because the ActiveRecord::Rollback
exception is handled, but not re-raised by ActiveRecord::Transaction
, I could move my return out of the transaction block, and thus return a value after the transaction is rolled back.
With a little refactoring:
def save_with_place_in_set(parent_id = nil) Category.transaction do return false if !save_without_place_in_set raise ActiveRecord::Rollback if !validate_move parent_id place_in_nested_set parent_id return true end return falseend
I know it may be a little late, but i ran into the same problem and just found out, that within a transaction block you can simply raise an Exception and rescue that one...Rails implicitly rollbacks the whole transaction. So there is no need for ActiveRecord::Rollback.
For example:
def create begin Model.transaction do # using create! will cause Exception on validation errors record = Model.create!({name: nil}) check_something_afterwards(record) return true end rescue Exception => e puts e.message return false endenddef check_something_afterwards(record) # just for demonstration purpose raise Exception, "name is missing" if record.name.nil?end
I'm working with Rails 3.2.15 and Ruby 1.9.3.