[ruby-on-rails] Rails에서 속성이 변경된 경우에만 콜백 실행

내 앱에 다음과 같은 연결이 있습니다.

# Page 
belongs_to :status

나는 콜백 언제든지 실행할 status_id의이 page변경되었습니다.

따라서 page.status_id4에서 5로 가면 그것을 잡을 수 있기를 원합니다.

어떻게하나요?



답변

Rails 5.1 이상

class Page < ActiveRecord::Base
  before_save :do_something, if: :will_save_change_to_status_id?

  private

  def do_something
    # ...
  end
end

ActiveRecord :: Dirty를 변경 한 커밋은 다음과 같습니다 : https://github.com/rails/rails/commit/16ae3db5a5c6a08383b974ae6c96faac5b4a3c81

다음은 이러한 변경 사항에 대한 블로그 게시물입니다. https://www.ombulabs.com/blog/rails/upgrades/active-record-5-1-api-changes.html

다음은 Rails 5.1+에서 ActiveRecord :: Dirty의 변경 사항에 대한 요약입니다.

ActiveRecord :: 더티

https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html

저장 전 (선택 사항 변경)

객체를 수정 한 후 데이터베이스에 저장하기 전 또는 before_save필터 내에서 :

  • changes 이제야 changes_to_save
  • changed? 이제야 has_changes_to_save?
  • changed 이제야 changed_attribute_names_to_save
  • <attribute>_change 이제야 <attribute>_change_to_be_saved
  • <attribute>_changed? 이제야 will_save_change_to_<attribute>?
  • <attribute>_was 이제야 <attribute>_in_database

저장 후 (속보)

객체를 수정 한 후 데이터베이스에 저장 한 후 또는 after_save필터 내에서 :

  • saved_changes(대체 previous_changes)
  • saved_changes?
  • saved_change_to_<attribute>
  • saved_change_to_<attribute>?
  • <attribute>_before_last_save

레일스 <= 5.0

class Page < ActiveRecord::Base
  before_save :do_something, if: :status_id_changed?

  private

  def do_something
    # ...
  end
end

이것은 before_save콜백이 메서드 호출의 반환 값에 따라 조건부로 실행될 수 있다는 사실을 활용합니다 . 이 status_id_changed?메서드는 ActiveModel :: Dirty 에서 가져 오며 _changed?, 속성 이름에 추가 하기 만하면 특정 속성이 변경되었는지 확인할 수 있습니다 .

do_something메서드를 호출해야하는 시기는 필요에 따라 다릅니다. before_save또는 정의 된 ActiveRecord :: Callbacksafter_save 중 하나 일 수 있습니다 .


답변

attribute_changed?이제 막 사용, 레일 5.1에서 더 이상 사용되지 않습니다 will_save_change_to_attribute?.

자세한 내용은 이 문제를 참조하십시오 .


답변

이 시도

after_validation :do_something, if: ->(obj){ obj.status_id.present? and obj.status_id_changed? }

def do_something
 # your code
end

참조-http: //apidock.com/rails/ActiveRecord/Dirty


답변