activerecord :: 롤백 예외를 제기하고 값을 함께 반환하는 방법은 무엇입니까?
-
21-08-2019 - |
문제
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으로 작업하고 있습니다.