ActiveRecord를 사용하면 after_update 중에 레코드의 이전 값을 가져올 수있는 방법이 있습니까?
간단한 예제를 사용하여 설정 : 두 번째 테이블 ( ) 에 각 레코드 Totals
의 amount
열 합계를 보유하는 테이블 ( ) 이 1 개 Things
있습니다.
thing.amount
가 업데이트 되면 이전 값과 새 값의 차이를에 추가하고 싶습니다 total.sum
.
지금은 뺀거야 self.amount
동안 before_update
및 추가 self.amount
시 after_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에 이전 값을 숨 깁니다.
'development' 카테고리의 다른 글
런타임시 Entity Framework 변경 연결 (0) | 2020.10.23 |
---|---|
테스트 대상 X에 오류가 발생했습니다 (예기치 않은 조기 종료, 작업이 부트 스트랩을 완료하지 않음-다시 시작하지 않음) (0) | 2020.10.23 |
Eclipse“Link with Editor”에 해당하는 IntelliJ IDEA (0) | 2020.10.23 |
드롭 다운 목록 / 선택에 optgroup 중첩 (0) | 2020.10.23 |
Vim에서 파일 찾기 (재귀 적 디렉토리 검색을 통해) (0) | 2020.10.23 |