0

我对 Rails(和开发)非常陌生,并且需要创建更改日志。假设您有一张员工表。在该表上,您有一个员工参考号、一个名字和一个姓氏。当名字或姓氏发生变化时,我需要将其记录到某处的表中以供以后报告。我只需要记录更改,因此如果员工 ref 1 从 Bill 更改为 Bob,那么我需要将参考编号和名字放入表中。更改表可以包含所有更改的列,但大多数仅填充参考号和更改的字段。我也不需要以前的值,只需要新的值。希望这是有道理的。

看着诸如纸迹之类的宝石,但对于我需要的东西来说,它们似乎很复杂。我不需要操作模型或移动版本等,我只需要跟踪哪些字段已更改、何时更改以及由谁更改。

我会很感激你的建议。

4

3 回答 3

1

我推荐 gem vestal_versions

要对ActiveRecord模型进行版本化,只需将版本化添加到您的类中,如下所示:

class User < ActiveRecord::Base
  versioned

  validates_presence_of :first_name, :last_name

  def name
    "#{first_name} #{last_name}"
  end
end

并像这样使用:

@user.update_attributes(:last_name => "Jobs", :updated_by => "Tyler")
@user.version # => 2
@user.versions.last.user # => "Tyler"
于 2013-06-03T16:51:27.877 回答
1

如果您坚持构建自己的变更日志,则可以根据您的要求使用一些回调来实现。首先创建您的日志表:

def up
  create_table :employee_change_logs do |t|
    t.references :employee
    # as per your spec - copy all column definitions from your employees table
  end
end

在您的Employee模型中:

class Employee < ActiveRecord::Base
  has_many :employee_change_logs

  before_update :capture_changed_columns
  after_update :log_changed_columns

  # capture the changes before the update occurs
  def capture_changed_columns
    @changed_columns = changed
  end

  def log_changed_columns
    return if @changed_columns.empty?
    log_entry = employee_change_logs.build
    @changed_columns.each{|c| log_entry.send(:"#{c}=", self.send(c))}
    log_entry.save!
  end
end
于 2013-06-03T16:44:22.840 回答
0

我们做的第一件事是在应用程序控制器中放置一个环绕过滤器。这就是我如何让 current_employee 进入员工模型,这是一个挑战,尤其是对于像我这样的新手!

around_filter :set_employee_for_log, :if => Proc.new { @current_account && 
@current_account.log_employee_changes? && @current_employee }

def set_employee_for_log
  Thread.current[:current_employee] = @current_employee.id
    begin
      yield
    ensure
      Thread.current[:current_employee ] = nil
    end
  end
end

接下来,在员工模型中,我定义了我有兴趣监控的字段

CHECK_FIELDS = ['first_name', 'last_name', 'middle_name']

然后我添加了一些钩子来实际捕获更改如果在帐户级别启用日志记录

before_update :capture_changed_columns
after_update :log_changed_columns, :if => Proc.new { self.account.log_employee_changes? }

def capture_changed_columns
  @changed_columns = changed
  @changes = changes
end

def log_changed_columns
  e = EmployeeChangeLog.new
  Employee::CHECK_FIELDS.each do |field|
  if self.send("#{field}_changed?")
    e.send("#{field}=", self.send(field))
  end
end

if e.changed?
  e.update_attribute(:account_id, self.account.id)
  e.update_attribute(:employee_id, self.id)
  e.update_attribute(:employee_ref, self.employee_ref)
  e.update_attribute(:user_id, Thread.current[:current_employee])
  e.save
else return
end

结尾

就是这样。如果帐户启用它,应用程序会密切关注特定字段,然后对这些字段的所有更改都会记录到一个表中,从而创建一个简单的审计跟踪。

于 2013-11-18T14:51:38.600 回答