activerecord :: 롤백 예외를 제기하고 값을 함께 반환하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1058738

문제

a를 사용하는 모델이 있습니다 acts_as_nested_set Fork와 모델에 모델을 저장하고 노드를 한 트랜잭션에서 세트로 이동시키는 메소드를 추가했습니다. 이 메소드는 유효성 검사 방법을 호출하여 이동이 유효한지 확인하여 True 또는 False를 반환합니다. 유효성 검사가 실패하면 저장 방법을 높이기를 원합니다. ActiveRecord::Rollback 거래를 롤백하려면 발신자에게 False를 반환합니다.

내 모델은 다음과 같습니다.

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

그러나 실패한 상황에서 저장을 호출하면 거래가 롤백되지만 함수는 반환됩니다. 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"]
도움이 되었습니까?

해결책

함수에서 반환하려는 값을 변수로 저장하고 트랜잭션 블록 외부에 반환 할 수 있습니다. 예를 들어

  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

트랜잭션 블록에서 벗어날 수있는 유일한 방법은 다른 방법 중 하나가 올라가는 것입니다. ActiveRecord::Rollback 나는 믿는다.

다른 팁

때문에 ActiveRecord::Rollback 예외는 처리되지만 다시는 다시 작성되지 않습니다 ActiveRecord::Transaction, 나는 거래 블록에서 돌아 오는 것을 옮길 수 있으므로 트랜잭션이 롤백 된 후에 값을 반환 할 수 있습니다.

약간의 리팩토링으로 :

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 false
end

나는 그것이 조금 늦었다는 것을 알고 있지만, 나는 같은 문제에 부딪쳤다. 그리고 트랜잭션 블록 내에서 당신은 단순히 예외를 제기하고 철도가 전체 거래를 암시 적으로 롤백한다는 예외를 제기 할 수 있음을 알게되었습니다. 따라서 activerecord :: 롤백이 필요하지 않습니다.

예를 들어:

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
  end
end

def check_something_afterwards(record)
  # just for demonstration purpose
  raise Exception, "name is missing" if record.name.nil?
end

나는 Rails 3.2.15와 Ruby 1.9.3으로 작업하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top