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」,默認情況下默認爲零。

當您想要執行數據庫更新時,首先必須將該屬性設置爲true,然後運行更新。否則,更新只會創建一個新的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 2010-02-04 21:35:34

+0

我做了你所要求的改變,但是,請閱讀我的評論底部附近。 – 2010-02-06 09:32:20

+0

非常感謝您的回覆。我同意覆蓋默認的更新方法可能很危險,但我不知道如何使用before_update回調完成我想要做的事情。如何在創建UpdateAudit後停止更新,而不會像更新失敗那樣執行相同的操作? – stellard 2010-02-09 20:47:49