How to raise an ActiveRecord::Rollback exception and return a value together?

rollback, ruby, ruby-on-rails, transactions

Solution

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.

Problem

I have a model that uses a `acts_as_nested_set` fork, and I've added a method to the model to save the model and move the node into the set in one transaction. This method calls a validation method to make sure the move is valid, which returns true or false. If the validation fails, I want my save method to raise `ActiveRecord::Rollback` to rollback the transaction, but also return false to the caller. My model looks like this: ``` class Category < ActiveRecord::Base acts_as_nested_set :dependent => :destroy, :scope => :journal def save_with_place_in_set(parent_id) Category.transaction do return false if !save_without_place_in_set if !validate_move parent_id raise ActiveRecord::Rollback and return false else place_in_nested_set parent_id return true end end end alias_method_chain :save, :place_in_set def validate_move(parent_id) # return true or false if the move is valid # ... end def place_in_nested_set(parent_id) # place the node in the correct place in the set # ... end end ``` However, when I call save in a situation that would fail, the transaction is rolled back but the function returns `nil`: ``` >> c = Category.new(:name => "test") => #<Category id: nil, name: "test" parent_id: nil, lft: nil, rgt: nil> >> c.save_with_place_in_set 47 => nil >> c.errors.full_messages => ["The specified parent is invalid"] ```

Original source

Related problems