【问题标题】:Papertrail: records with nil whodunnit values and object_changes in logsPapertrail:日志中的 whodunnit 值和 object_changes 为零的记录
【发布时间】:2021-01-04 13:32:51
【问题描述】:

我已将 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

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

【问题讨论】:

  • 你在whodunnit中存储什么样的对象?
  • 另外,您能否确认您没有在同一型号上使用unless 选项?
  • 另外我想知道您是否在任何控制器中使用info_for_paper_trail,或者手动设置值PaperTrail.request.controller_info。如果您在其中任何一个中包含 whodunnit 键,则可能会覆盖该值。
  • 有没有可能,带有空 whodunnit 值的更新是由控制器以外的其他东西执行的,例如在后台作业中还是通过控制台?在那里你必须手动设置whodunnit 值(见这里:github.com/paper-trail-gem/paper_trail/wiki/…)。
  • 听起来您在后台作业中更新了记录,或者在控制台中手动更新了控制器请求之外的记录。如果你真的卡住了,你可以更新Papertrail.whodunnit 来保存命令的来源。

标签: ruby-on-rails ruby ruby-on-rails-6 paper-trail-gem ruby-2.6


【解决方案1】:

source_locationcommand 字段添加到您的papertrail 版本表将帮助您:

  1. track what 命令导致nil whodunnit 发生变化。
  2. 确保正确记录由 rake 任务rails 控制台 发起的更改。

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


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 的保存位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 2014-07-01
    相关资源
    最近更新 更多