[ruby-on-rails] ActiveRecord를 사용하면 after_update 중에 레코드의 이전 값을 가져올 수 있습니까?

간단한 예제를 사용하여 설정 : 두 번째 테이블 ( ) 에 각 레코드 Totalsamount열 합계를 보유하는 테이블 ( ) 이 1 개 Things있습니다.

thing.amount가 업데이트 되면 이전 값과 새 값의 차이를에 추가하고 싶습니다 total.sum.

지금은 뺀거야 self.amount동안 before_update및 추가 self.amountafter_update. 이로 인해 업데이트 성공에 대해 너무 많은 신뢰가 있습니다.

제약 : 모든 거래의 합계를 단순히 재 계산하고 싶지 않습니다.

질문 : 간단히 말해서 after_update콜백 중에 원래 값에 액세스하고 싶습니다 . 이 작업을 수행하는 방법은 무엇입니까?

업데이트 : 나는 Luke Francl의 아이디어로 갈 것입니다. after_update콜백 중에 self.attr_was내가 원하는 값에 여전히 액세스 할 수 있습니다 . 나는 또한 after_update이런 종류의 논리를 모델에 유지하고 싶기 때문에 구현을하기 로 결정했습니다 . 이렇게하면 나중에 트랜잭션을 어떻게 업데이트할지 결정하더라도 트랜잭션 합계를 올바르게 업데이트하고 있음을 알 수 있습니다. 구현 제안을 해주신 모든 분들께 감사드립니다.



답변

모든 사람들이 거래에 대해 말하는 것과 동일합니다.

그건 …

Rails 2.1부터 ActiveRecord는 객체의 속성 값을 추적합니다. 따라서 속성 total이 있으면 이전 값을 반환 하는 total_changed?메서드와 total_was메서드가 있습니다.

더 이상이를 추적하기 위해 모델에 아무것도 추가 할 필요가 없습니다.

업데이트 : 요청 된 ActiveModel :: Dirty에 대한 문서는 다음과 같습니다 .


답변

다른 사람들은이 모든 것을 트랜잭션으로 감싸는 것에 대해 언급하고 있습니다.하지만 저는 그것이 당신을 위해 끝났다고 생각합니다. after_ * 콜백에서 오류에 대한 예외를 발생시켜 롤백을 트리거하기 만하면됩니다.

참조 http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html를

save, save! 또는 destroy 호출의 전체 콜백 체인은 트랜잭션 내에서 실행됩니다. 여기에는 after_ * 후크가 포함됩니다. 모든 것이 잘되면 체인이 완료되면 COMMIT가 실행됩니다.

before_ * 콜백이 작업을 취소하면 ROLLBACK이 실행됩니다. after_ * 후크를 포함한 모든 콜백에서 예외를 발생시키는 ROLLBACK을 트리거 할 수도 있습니다. 그러나이 경우 클라이언트는 일반 저장이 조용히 거짓을 반환하는 대신 이러한 예외를 발생시키기 때문에이를 인식해야합니다.


답변

속성에 “_was”를 추가하면 데이터를 저장하기 전에 이전 값이 제공됩니다.

이러한 메서드를 더티 메서드 메서드 라고 합니다.

건배!


답변

이전 값과 새 값을 각각 사용하여 변경된 모든 필드를 가져 오려면 다음을 수행하십시오.

person = Person.create!(:name => 'Bill')
person.name = 'Bob'
person.save
person.changes        # => {"name" => ["Bill", "Bob"]}


답변

ActiveRecord :: Dirty 는 속성 변경을 추적하기 위해 ActiveRecord에 내장 된 모듈입니다. 따라서 thing.amount_was이전 값을 얻는 데 사용할 수 있습니다 .


답변

이것을 모델에 추가하십시오.

def amount=(new_value)
    @old_amount = read_attribute(:amount)
    write_attribute(:amount,new_value)
end

그런 다음 after_update 코드에서 @old_amount를 사용합니다.


답변

첫째, 데이터가 함께 작성되도록 트랜잭션에서이 작업을 수행해야합니다.

질문에 답하기 위해 before_update의 이전 값으로 멤버 변수를 설정 한 다음 after_update에서 액세스 할 수 있지만 이것은 매우 우아한 솔루션이 아닙니다.