0

내 응용 프로그램에 감사 추적을 구현하려고하지만 일부 요구 사항으로 인해 기존의 보석이나 플러그인을 사용할 수 없습니다.오버로드 및 액티브 레코드 업데이트 무시

모든 업데이트를 별도의 별도의 테이블 (업데이트라고 함)에 저장하는 사용자 지정 메서드로 모델을 업데이트하려는 일반적인 시도를 돌리고 싶습니다.

그런 다음 응용 프로그램은 업데이트 테이블을 사용하여 실제로 업데이트를 수행합니다.

지금 내가 오버로드 create_or_update 지금 업데이트 모델이 실제로 업데이트를 수행하려고 할 때이 무한 루프가 발생한다는 것입니다 기능

def create_or_update 
    raise ReadOnlyRecord if readonly? 
    result = new_record? ? create : create_updates 
    result != false 
end 


class Update < ActiveRecord::Base 
    belongs_to :updatable, :polymorphic => true 

    after_create :update_model 

    private 

    def update_model 
    self.updatable.update_attribute self.attribute, self.new_value #infinite loop 
    end 
end 

문제의 첫 번째 부분을 얻을 수 있습니다.

나는 레일 코어 소스를 통해 첫 번째 기능의 기능을 우회하는 최고의 장소를 찾고있었습니다. 이 업데이트가 트랜잭션 내부에서 수행되기를 바랍니다. 그러나 활성 레코드 스택에서 어디서 시작 또는 끝나는 지 정확히 알지 못합니다. 또한 적극적인 리소스를 해킹하기 시작하고 싶지 않습니다.

모든 의견을 크게 기뻐할 것입니다.

답변

1

실제로 속성을 별도의 테이블에 저장 한 다음 관리자가보고 승인 한 후에 업데이트를 수행해야합니까? 이 시나리오가있는 경우, 당신은 이런 식으로 뭔가를 업데이트 방법을 덮어 쓸 수 있습니다

def update(perform_updates = false) 
    if perform_updates 
    latest_approved_update = UpdateAuditor.first(:conditions => { :updatable_id => self.id, :updatable_type => self.class.name, :approved => true }) 
    self.attributes = latest_approved_update.attributes 
    self.save 
    else 
    UpdateAuditor.create(:updatable_id => self.id, :updatable_type => self.class.name, :attributes => self.attributes) 
    end 
end 

UPDATE : 저자는 그들이 모든에이 모델을 적용 할 수 있도록하려면 논평했다 업데이트. 이것을 달성하기 위해 모델에 attr_accessor를 추가 할 수 있습니다. "perform_updates"와 같은 것을 말하자. 물론 기본적으로 nil이 될 것입니다.

데이터베이스를 업데이트하려면 먼저 속성을 true로 설정 한 다음 update를 실행해야합니다. 그렇지 않으면 업데이트는 관리자가 승인해야하는 새 UpdateAuditor 레코드를 생성합니다. 기록을 위해

class Person < ActiveRecord::Base 
    has_many :audits, :class_name => "UpdateAudit", :as => :auditable 

    attr_accessor :perform_updates 

    private 

    def create_or_update 
    raise ReadOnlyRecord if readonly? 

    if new_record? 
     result = create 
     result != false 
    else 
     if perform_updates 
     latest_approved_update = audits.approved.last 

     if latest_approved_update 
      self.attributes = latest_approved_update.attributes 
      update 
     else 
      return false 
     end 
     else 
     audits.create(:updated_attributes => self.attributes) 
     end 
    end 
    end 
end 

, 나는 기본 업데이트 방법을 덮어 쓰기하는 것은 위험한 게임이다, 및 프로그래밍이 속한 before_update 콜백에서 더 잘라고 생각합니다. 일부 인터페이스에서 업데이트가 승인되면 관찰자는 변경 사항을 승인 할 때까지 현재 수행중인 작업을 덮어 쓰면서 업데이트를 수행 할 수 있습니다. 현재 승인 대기열에있는 객체의 업데이트가 있으면 승인이 보류 중임을 사용자에게 알릴 수 있습니다.

+0

이것은 업데이트가 사전 승인 된 것을 제외하고는 기능에 가깝습니다. 나는 이런 식으로 생각했지만이 솔루션이 모든 업데이트를 잡을 것이라고 생각지 않는다. 예를 들어 update_attributes는 UpdateAuditor도 무시합니다. – stellard

+0

요청한 변경 사항을 작성했지만 하단의 내 의견을 읽어주십시오. –

+0

답변 해 주셔서 대단히 감사드립니다. 기본 업데이트 메서드를 덮어 쓰는 것이 위험 할 수 있다는 것에 동의하지만 before_update 콜백을 사용하여 수행하려는 작업을 정확히 수행 할 수 있는지 여부를 모르겠습니다. 실패한 업데이트와 동일한 방식으로 작동하지 않고 UpdateAudit을 만든 후 업데이트를 중지하려면 어떻게합니까? – stellard

관련 문제