development

ActiveRecord를 사용하면 after_update 중에 레코드의 이전 값을 가져올 수있는 방법이 있습니까?

big-blog 2020. 10. 23. 08:04
반응형

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에 대한 문서는 다음과 같습니다 .


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

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

건배!


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

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

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

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


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

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에서 액세스 할 수 있지만 이것은 매우 우아한 솔루션이 아닙니다.


아이디어 1 : 데이터베이스 트랜잭션에서 업데이트를 래핑하여 업데이트가 실패하더라도 Totals 테이블이 변경되지 않도록합니다. ActiveRecord Transactions docs

아이디어 2 : before_update 중에 @old_total에 이전 값을 숨 깁니다.

참고 URL : https://stackoverflow.com/questions/607069/using-activerecord-is-there-a-way-to-get-the-old-values-of-a-record-during-afte

반응형