5

我已将 papertrail 设置为仅记录包含 whodunnit 值的更改/当管理员通过在我的模型中使用以下条件进行更改时:

has_paper_trail if: proc { |model| PaperTrail.request.whodunnit.present? }

但是,我注意到仍然有相当数量的记录以空的 whodunnit 值存储。从查看记录来看,这些似乎主要是“更新”操作,出于某种原因,所有操作都具有空对象更改。我不确定为什么这个值是空的,或者考虑到上述情况,它会如何被保存。

我在我的应用程序控制器中使用以下命令从 Warden 那里获取 whodunnit 值:

def user_for_paper_trail
  request.env['warden']&.user(:admin)&.id
end

有没有人遇到过类似的行为?

4

1 回答 1

1

在您的 papertrail 版本表中添加一个source_locationcommand字段将帮助您:

  1. 跟踪导致 whodunnit 更改的命令nil
  2. 确保正确记录由rake 任务rails 控制台启动的更改。

为此,请创建迁移以将source_locationandcommand字段添加到您的 Versions 表中:


class AddSourceLocationAndCommandToVersions < ActiveRecord::Migration
  def change
    add_column :versions, :source_location, :text
    add_column :versions, :command, :text
  end
end

我在我的papertrail.rb. 我正在使用,JSON serializer但这些更改可能适用于普通序列化程序。声明后的代码serializer是您感兴趣的:

require "paper_trail/frameworks/rails"
require "paper_trail"

# the following line is required for PaperTrail >= 4.0.0 with Rails
PaperTrail::Rails::Engine.eager_load!

PaperTrail.config.enabled = true
PaperTrail.serializer = PaperTrail::Serializers::JSON

# Store some metadata about where the change came from, even for rake tasks, etc.
# See: https://github.com/paper-trail-gem/paper_trail/wiki/Setting-whodunnit-in-the-rails-console
def PaperTrail.set_global_metadata
  request.controller_info ||= {}
  request.controller_info[:command] ||= "#{File.basename($PROGRAM_NAME)} #{ARGV.join ' '} (#{$PID})"
  request.controller_info[:source_location] = caller.find { |line|
    line.starts_with? Rails.root.to_s and
   !line.starts_with? __FILE__
  }
end

# Defer evaluation in case we're using spring loader (otherwise it would be something like "spring app    | app | started 13 secs ago | development")
# There's no way to set up deferred evaluation of PaperTrail.request.controller_info from here like
# we can with whodunnit, so abuse that property of PaperTrail.request.whodunnit to set other
# metadata. Reserve the whodunnit field for storing the actual name or id of the human who made the
# change.
PaperTrail.request.whodunnit = ->() {
  PaperTrail.set_global_metadata
  if Rails.const_defined?("Console") || $rails_rake_task
    "#{`whoami`.strip}: console"
  else
    "#{`whoami`.strip}: #{File.basename($PROGRAM_NAME)} #{ARGV.join ' '}"
  end
}

Rails.application.configure do
  console do
    PaperTrail.request.controller_info = { command: "rails console" }
    PaperTrail.request.whodunnit = ->() {
      PaperTrail.set_global_metadata

      @paper_trail_whodunnit ||= (
        if Rails.const_defined?("Console") || $rails_rake_task
          "#{`whoami`.strip}: console"
        else
          "#{`whoami`.strip}: #{File.basename($PROGRAM_NAME)} #{ARGV.join ' '}"
        end
      )
    }
  end
end

请注意,在请求之外发生记录创建的任何地方,whodunnit如果您不希望它为空,您可以手动将值设置为特定的值。例如,在我的种子文件中,我执行以下操作:


class SeedCreator
  def initialize
    PaperTrail.request.whodunnit = ->() {
      PaperTrail.set_global_metadata # save source_location & command
      "seed" # set whodunnit value to "seed"
    }
    create_campaign
    create_users
    # more seeding of models....
  end
end

除了提高 Papertrail 表的质量(知道哪个命令触发了记录更新)之外,此配置还可以帮助您确定幻像whodunnits的保存位置。

于 2021-01-12T05:43:57.270 回答