繁体   English   中英

重载和绕过活动记录更新

[英]Overload and Bypass Active Record Update

我正在尝试在我的应用程序中实施审核跟踪,但是由于某些要求,我无法使用任何现有的gem或插件。

我想将任何将模型更新的常规尝试转移到将所有更新保存在另一个单独的表(称为“更新”)中的自定义方法。

然后,应用程序使用更新表来实际执行更新。

现在,我已经重载了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  

现在的问题是,当更新模型尝试实际执行更新时,这将导致无限循环。

我一直在寻找Rails核心资源,以找到绕过第一个功能的最佳位置。 我希望在事务内部执行这些更新,但是我不确定活动记录堆栈中的确切开始或结束位置。 我也不想开始破坏活跃的资源。

任何建议将不胜感激。

您实际上是否需要将属性保存在单独的表中,然后在管理员查看并批准它们之后执行更新? 如果是这种情况,您可能只想覆盖update方法来执行以下操作:

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

更新:作者评论说,他们希望能够将此模型应用于所有更新。 为了做到这一点,您可以向模型添加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回调中进行。 一旦在某个界面中批准了更新,然后观察者就可以执行更新,覆盖当前存在的内容,直到可以批准进行的另一个更改。 如果队列中当前有待批准对象的更新,则可以提醒用户更改正在等待批准等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM