Papertrail:日志中记录了 nil whodunnit 值和 object_changes

L45*_*457 5 ruby ruby-on-rails paper-trail-gem ruby-on-rails-6 ruby-2.6

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

has_paper_trail if: proc { |model| PaperTrail.request.whodunnit.present? }
Run Code Online (Sandbox Code Playgroud)

然而我注意到仍然有相当数量的记录存储着空的侦探小说值。从记录来看,这些似乎主要是“更新”操作,由于某种原因,所有操作都具有空对象更改。我不确定为什么该值是空的,或者考虑到上述条件它将如何保存。

我在应用程序控制器中使用以下命令从典狱长那里获取侦探小说值:

def user_for_paper_trail
  request.env['warden']&.user(:admin)&.id
end
Run Code Online (Sandbox Code Playgroud)

以前有人遇到过类似的行为吗?

Kel*_*nan 1

在 papertrail 版本表中添加source_location和字段将帮助您:command

  1. 追踪是什么命令导致了nil侦探小说的变化。
  2. 确保正确记录由rake 任务Rails 控制台启动的更改。

为此,请创建一个迁移以将source_locationcommand字段添加到您的版本表中:


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

Run Code Online (Sandbox Code Playgroud)

我在我的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
Run Code Online (Sandbox Code Playgroud)

请注意,在请求之外创建记录的任何位置,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

Run Code Online (Sandbox Code Playgroud)

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