2017-12-10 23:05:11 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-01-31 12:25:31 -05:00
|
|
|
# AR does not require all of AS, but PT does. PT uses core_ext like
|
|
|
|
# `String#squish`, so we require `active_support/all`. Instead of eagerly
|
|
|
|
# loading all of AS here, we could put specific `require`s in only the various
|
|
|
|
# PT files that need them, but this seems easier to troubleshoot, though it may
|
|
|
|
# add a few milliseconds to rails boot time. If that becomes a pain point, we
|
|
|
|
# can revisit this decision.
|
|
|
|
require "active_support/all"
|
|
|
|
|
|
|
|
# AR is required for, eg. has_paper_trail.rb, so we could put this `require` in
|
|
|
|
# all of those files, but it seems easier to troubleshoot if we just make sure
|
|
|
|
# AR is loaded here before loading *any* of PT. See discussion of
|
|
|
|
# performance/simplicity tradeoff for activesupport above.
|
|
|
|
require "active_record"
|
|
|
|
|
2016-03-05 17:07:32 -05:00
|
|
|
require "request_store"
|
2016-04-09 01:15:51 -04:00
|
|
|
require "paper_trail/cleaner"
|
|
|
|
require "paper_trail/config"
|
|
|
|
require "paper_trail/has_paper_trail"
|
|
|
|
require "paper_trail/record_history"
|
|
|
|
require "paper_trail/reifier"
|
2018-02-01 12:04:50 -05:00
|
|
|
require "paper_trail/request"
|
2016-04-09 01:15:51 -04:00
|
|
|
require "paper_trail/version_association_concern"
|
|
|
|
require "paper_trail/version_concern"
|
|
|
|
require "paper_trail/version_number"
|
|
|
|
require "paper_trail/serializers/json"
|
|
|
|
require "paper_trail/serializers/yaml"
|
2009-05-27 11:21:20 -04:00
|
|
|
|
2016-04-09 01:08:34 -04:00
|
|
|
# An ActiveRecord extension that tracks changes to your models, for auditing or
|
|
|
|
# versioning.
|
2009-05-27 11:21:20 -04:00
|
|
|
module PaperTrail
|
2017-10-19 09:03:31 -04:00
|
|
|
E_RAILS_NOT_LOADED = <<-EOS.squish.freeze
|
|
|
|
PaperTrail has been loaded too early, before rails is loaded. This can
|
|
|
|
happen when another gem defines the ::Rails namespace, then PT is loaded,
|
|
|
|
all before rails is loaded. You may want to reorder your Gemfile, or defer
|
|
|
|
the loading of PT by using `require: false` and a manual require elsewhere.
|
|
|
|
EOS
|
2017-10-23 12:29:49 -04:00
|
|
|
E_TIMESTAMP_FIELD_CONFIG = <<-EOS.squish.freeze
|
|
|
|
PaperTrail.timestamp_field= has been removed, without replacement. It is no
|
2017-12-04 00:02:10 -05:00
|
|
|
longer configurable. The timestamp column in the versions table must now be
|
2017-10-23 12:29:49 -04:00
|
|
|
named created_at.
|
|
|
|
EOS
|
|
|
|
|
2013-03-21 16:40:15 -04:00
|
|
|
extend PaperTrail::Cleaner
|
2009-05-27 11:21:20 -04:00
|
|
|
|
2015-02-26 23:37:16 -05:00
|
|
|
class << self
|
2016-02-23 17:59:14 -05:00
|
|
|
# @api private
|
|
|
|
def clear_transaction_id
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.clear_transaction_id is deprecated, " \
|
|
|
|
"use PaperTrail.request.clear_transaction_id",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.clear_transaction_id
|
2016-02-23 17:59:14 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Switches PaperTrail on or off, for all threads.
|
2016-02-15 19:58:23 -05:00
|
|
|
# @api public
|
|
|
|
def enabled=(value)
|
|
|
|
PaperTrail.config.enabled = value
|
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Returns `true` if PaperTrail is on, `false` otherwise. This is the
|
|
|
|
# on/off switch that affects all threads. Enabled by default.
|
2016-02-15 19:58:23 -05:00
|
|
|
# @api public
|
|
|
|
def enabled?
|
|
|
|
!!PaperTrail.config.enabled
|
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def enabled_for_controller=(value)
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.enabled_for_controller= is deprecated, " \
|
2018-03-23 21:58:45 -04:00
|
|
|
"use PaperTrail.request.enabled=",
|
2018-02-01 12:04:50 -05:00
|
|
|
caller(1)
|
|
|
|
)
|
2018-03-23 21:58:45 -04:00
|
|
|
request.enabled = value
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def enabled_for_controller?
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.enabled_for_controller? is deprecated, " \
|
2018-03-23 21:58:45 -04:00
|
|
|
"use PaperTrail.request.enabled?",
|
2018-02-01 12:04:50 -05:00
|
|
|
caller(1)
|
|
|
|
)
|
2018-03-23 21:58:45 -04:00
|
|
|
request.enabled?
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def enabled_for_model(model, value)
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.enabled_for_model is deprecated, " \
|
|
|
|
"use PaperTrail.request.enabled_for_model",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.enabled_for_model(model, value)
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def enabled_for_model?(model)
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.enabled_for_model? is deprecated, " \
|
|
|
|
"use PaperTrail.request.enabled_for_model?",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.enabled_for_model?(model)
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Returns PaperTrail's `::Gem::Version`, convenient for comparisons. This is
|
2017-04-01 01:19:54 -04:00
|
|
|
# recommended over `::PaperTrail::VERSION::STRING`.
|
|
|
|
# @api public
|
|
|
|
def gem_version
|
|
|
|
::Gem::Version.new(VERSION::STRING)
|
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Set variables for the current request, eg. whodunnit.
|
|
|
|
#
|
|
|
|
# All request-level variables are now managed here, as of PT 9. Having the
|
|
|
|
# word "request" right there in your application code will remind you that
|
|
|
|
# these variables only affect the current request, not all threads.
|
|
|
|
#
|
|
|
|
# Given a block, temporarily sets the given `options` and execute the block.
|
|
|
|
#
|
|
|
|
# Without a block, this currently just returns `PaperTrail::Request`.
|
|
|
|
# However, please do not use `PaperTrail::Request` directly. Currently,
|
|
|
|
# `Request` is a `Module`, but in the future it is quite possible we may
|
|
|
|
# make it a `Class`. If we make such a choice, we will not provide any
|
|
|
|
# warning and will not treat it as a breaking change. You've been warned :)
|
|
|
|
#
|
|
|
|
# @api public
|
|
|
|
def request(options = nil, &block)
|
|
|
|
if options.nil? && !block_given?
|
|
|
|
Request
|
|
|
|
else
|
|
|
|
Request.with(options, &block)
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-15 19:58:23 -05:00
|
|
|
# Set the field which records when a version was created.
|
|
|
|
# @api public
|
2016-09-04 00:33:29 -04:00
|
|
|
def timestamp_field=(_field_name)
|
2017-10-23 12:29:49 -04:00
|
|
|
raise(E_TIMESTAMP_FIELD_CONFIG)
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def whodunnit=(value)
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.whodunnit= is deprecated, use PaperTrail.request.whodunnit=",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.whodunnit = value
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
|
|
|
def whodunnit(value = nil, &block)
|
|
|
|
if value.nil?
|
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.whodunnit is deprecated, use PaperTrail.request.whodunnit",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.whodunnit
|
|
|
|
elsif block_given?
|
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"Passing a block to PaperTrail.whodunnit is deprecated, " \
|
|
|
|
'use PaperTrail.request(whodunnit: "John") do .. end',
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request(whodunnit: value, &block)
|
2017-02-28 21:12:20 -05:00
|
|
|
else
|
2018-02-01 12:04:50 -05:00
|
|
|
raise ArgumentError, "Invalid arguments"
|
2017-02-28 21:12:20 -05:00
|
|
|
end
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def controller_info=(value)
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.controller_info= is deprecated, use PaperTrail.request.controller_info=",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.controller_info = value
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def controller_info
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.controller_info is deprecated, use PaperTrail.request.controller_info",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.controller_info
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Set the PaperTrail serializer. This setting affects all threads.
|
2016-02-15 19:58:23 -05:00
|
|
|
# @api public
|
|
|
|
def serializer=(value)
|
|
|
|
PaperTrail.config.serializer = value
|
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Get the PaperTrail serializer used by all threads.
|
2016-02-15 19:58:23 -05:00
|
|
|
# @api public
|
|
|
|
def serializer
|
|
|
|
PaperTrail.config.serializer
|
|
|
|
end
|
|
|
|
|
|
|
|
# @api public
|
|
|
|
def transaction?
|
2017-12-10 23:01:21 -05:00
|
|
|
::ActiveRecord::Base.connection.open_transactions.positive?
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def transaction_id
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.transaction_id is deprecated without replacement.",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.transaction_id
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# @deprecated
|
2016-02-15 19:58:23 -05:00
|
|
|
def transaction_id=(id)
|
2018-02-01 12:04:50 -05:00
|
|
|
::ActiveSupport::Deprecation.warn(
|
|
|
|
"PaperTrail.transaction_id= is deprecated without replacement.",
|
|
|
|
caller(1)
|
|
|
|
)
|
|
|
|
request.transaction_id = id
|
2016-02-15 19:58:23 -05:00
|
|
|
end
|
|
|
|
|
2018-02-01 12:04:50 -05:00
|
|
|
# Returns PaperTrail's global configuration object, a singleton. These
|
|
|
|
# settings affect all threads.
|
2016-02-15 19:58:23 -05:00
|
|
|
# @api private
|
|
|
|
def config
|
|
|
|
@config ||= PaperTrail::Config.instance
|
|
|
|
yield @config if block_given?
|
|
|
|
@config
|
|
|
|
end
|
2016-03-31 04:57:32 -04:00
|
|
|
alias configure config
|
2016-04-08 23:32:09 -04:00
|
|
|
|
|
|
|
def version
|
|
|
|
VERSION::STRING
|
|
|
|
end
|
2013-01-07 14:44:12 -05:00
|
|
|
end
|
2009-05-27 11:21:20 -04:00
|
|
|
end
|
2011-02-08 12:16:35 -05:00
|
|
|
|
2016-05-04 14:01:16 -04:00
|
|
|
ActiveSupport.on_load(:active_record) do
|
|
|
|
include PaperTrail::Model
|
|
|
|
end
|
|
|
|
|
2013-10-02 17:04:45 -04:00
|
|
|
# Require frameworks
|
2017-10-19 09:03:31 -04:00
|
|
|
if defined?(::Rails)
|
|
|
|
# Rails module is sometimes defined by gems like rails-html-sanitizer
|
|
|
|
# so we check for presence of Rails.application.
|
|
|
|
if defined?(::Rails.application)
|
|
|
|
require "paper_trail/frameworks/rails"
|
|
|
|
else
|
|
|
|
::Kernel.warn(::PaperTrail::E_RAILS_NOT_LOADED)
|
|
|
|
end
|
2014-06-05 11:06:51 -04:00
|
|
|
else
|
2016-03-05 17:07:32 -05:00
|
|
|
require "paper_trail/frameworks/active_record"
|
2014-06-05 11:06:51 -04:00
|
|
|
end
|