paper_trail 11.1.0 → 15.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/paper_trail/install/install_generator.rb +29 -5
- data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +11 -6
- data/lib/generators/paper_trail/update_item_subtype/update_item_subtype_generator.rb +4 -2
- data/lib/paper_trail/attribute_serializers/attribute_serializer_factory.rb +24 -10
- data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +10 -10
- data/lib/paper_trail/attribute_serializers/object_attribute.rb +13 -3
- data/lib/paper_trail/attribute_serializers/object_changes_attribute.rb +13 -3
- data/lib/paper_trail/compatibility.rb +3 -3
- data/lib/paper_trail/errors.rb +33 -0
- data/lib/paper_trail/events/base.rb +84 -64
- data/lib/paper_trail/events/destroy.rb +1 -1
- data/lib/paper_trail/events/update.rb +23 -7
- data/lib/paper_trail/frameworks/active_record.rb +9 -2
- data/lib/paper_trail/frameworks/rails/controller.rb +0 -6
- data/lib/paper_trail/frameworks/rails/railtie.rb +34 -0
- data/lib/paper_trail/frameworks/rails.rb +1 -2
- data/lib/paper_trail/has_paper_trail.rb +4 -0
- data/lib/paper_trail/model_config.rb +51 -45
- data/lib/paper_trail/queries/versions/where_attribute_changes.rb +50 -0
- data/lib/paper_trail/queries/versions/where_object.rb +1 -1
- data/lib/paper_trail/queries/versions/where_object_changes.rb +9 -14
- data/lib/paper_trail/queries/versions/where_object_changes_from.rb +57 -0
- data/lib/paper_trail/queries/versions/where_object_changes_to.rb +57 -0
- data/lib/paper_trail/record_trail.rb +81 -64
- data/lib/paper_trail/reifier.rb +27 -10
- data/lib/paper_trail/request.rb +22 -25
- data/lib/paper_trail/serializers/json.rb +0 -10
- data/lib/paper_trail/serializers/yaml.rb +38 -13
- data/lib/paper_trail/type_serializers/postgres_array_serializer.rb +1 -14
- data/lib/paper_trail/version_concern.rb +74 -22
- data/lib/paper_trail/version_number.rb +2 -2
- data/lib/paper_trail.rb +30 -40
- metadata +98 -45
- data/Gemfile +0 -4
- data/lib/paper_trail/frameworks/rails/engine.rb +0 -45
- data/paper_trail.gemspec +0 -69
data/lib/paper_trail/reifier.rb
CHANGED
@@ -60,9 +60,7 @@ module PaperTrail
|
|
60
60
|
model = if options[:dup] == true || version.event == "destroy"
|
61
61
|
klass.new
|
62
62
|
else
|
63
|
-
|
64
|
-
|
65
|
-
version.item || klass.unscoped.where(find_cond).first || klass.new
|
63
|
+
version.item || init_model_by_finding_item_id(klass, version) || klass.new
|
66
64
|
end
|
67
65
|
|
68
66
|
if options[:unversioned_attributes] == :nil && !model.new_record?
|
@@ -72,6 +70,11 @@ module PaperTrail
|
|
72
70
|
model
|
73
71
|
end
|
74
72
|
|
73
|
+
# @api private
|
74
|
+
def init_model_by_finding_item_id(klass, version)
|
75
|
+
klass.unscoped.where(klass.primary_key => version.item_id).first
|
76
|
+
end
|
77
|
+
|
75
78
|
# Look for attributes that exist in `model` and not in this version.
|
76
79
|
# These attributes should be set to nil. Modifies `attrs`.
|
77
80
|
# @api private
|
@@ -109,21 +112,35 @@ module PaperTrail
|
|
109
112
|
end
|
110
113
|
|
111
114
|
# Given a `version`, return the class to reify. This method supports
|
112
|
-
# Single Table Inheritance (STI) with custom inheritance columns
|
115
|
+
# Single Table Inheritance (STI) with custom inheritance columns and
|
116
|
+
# custom inheritance column values.
|
113
117
|
#
|
114
118
|
# For example, imagine a `version` whose `item_type` is "Animal". The
|
115
119
|
# `animals` table is an STI table (it has cats and dogs) and it has a
|
116
120
|
# custom inheritance column, `species`. If `attrs["species"]` is "Dog",
|
117
121
|
# this method returns the constant `Dog`. If `attrs["species"]` is blank,
|
118
|
-
# this method returns the constant `Animal`.
|
119
|
-
# example in action in `spec/models/animal_spec.rb`.
|
122
|
+
# this method returns the constant `Animal`.
|
120
123
|
#
|
121
|
-
#
|
124
|
+
# The values contained in the inheritance columns may be non-camelized
|
125
|
+
# strings (e.g. 'dog' instead of 'Dog'). To reify classes in this case
|
126
|
+
# we need to call the parents class `sti_class_for` method to retrieve
|
127
|
+
# the correct record class.
|
128
|
+
#
|
129
|
+
# You can see these particular examples in action in
|
130
|
+
# `spec/models/animal_spec.rb` and `spec/models/plant_spec.rb`
|
122
131
|
def version_reification_class(version, attrs)
|
123
|
-
|
132
|
+
clazz = version.item_type.constantize
|
133
|
+
inheritance_column_name = clazz.inheritance_column
|
124
134
|
inher_col_value = attrs[inheritance_column_name]
|
125
|
-
|
126
|
-
|
135
|
+
return clazz if inher_col_value.blank?
|
136
|
+
|
137
|
+
# Rails 6.1 adds a public method for clients to use to customize STI classes. If that
|
138
|
+
# method is not available, fall back to using the private one
|
139
|
+
if clazz.public_methods.include?(:sti_class_for)
|
140
|
+
return clazz.sti_class_for(inher_col_value)
|
141
|
+
end
|
142
|
+
|
143
|
+
clazz.send(:find_sti_class, inher_col_value)
|
127
144
|
end
|
128
145
|
end
|
129
146
|
end
|
data/lib/paper_trail/request.rb
CHANGED
@@ -12,9 +12,6 @@ module PaperTrail
|
|
12
12
|
#
|
13
13
|
# @api private
|
14
14
|
module Request
|
15
|
-
class InvalidOption < RuntimeError
|
16
|
-
end
|
17
|
-
|
18
15
|
class << self
|
19
16
|
# Sets any data from the controller that you want PaperTrail to store.
|
20
17
|
# See also `PaperTrail::Rails::Controller#info_for_paper_trail`.
|
@@ -78,28 +75,6 @@ module PaperTrail
|
|
78
75
|
!!store.fetch(:"enabled_for_#{model}", true)
|
79
76
|
end
|
80
77
|
|
81
|
-
# @api private
|
82
|
-
def merge(options)
|
83
|
-
options.to_h.each do |k, v|
|
84
|
-
store[k] = v
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# @api private
|
89
|
-
def set(options)
|
90
|
-
store.clear
|
91
|
-
merge(options)
|
92
|
-
end
|
93
|
-
|
94
|
-
# Returns a deep copy of the internal hash from our RequestStore. Keys are
|
95
|
-
# all symbols. Values are mostly primitives, but whodunnit can be a Proc.
|
96
|
-
# We cannot use Marshal.dump here because it doesn't support Proc. It is
|
97
|
-
# unclear exactly how `deep_dup` handles a Proc, but it doesn't complain.
|
98
|
-
# @api private
|
99
|
-
def to_h
|
100
|
-
store.deep_dup
|
101
|
-
end
|
102
|
-
|
103
78
|
# Temporarily set `options` and execute a block.
|
104
79
|
# @api private
|
105
80
|
def with(options)
|
@@ -136,6 +111,19 @@ module PaperTrail
|
|
136
111
|
|
137
112
|
private
|
138
113
|
|
114
|
+
# @api private
|
115
|
+
def merge(options)
|
116
|
+
options.to_h.each do |k, v|
|
117
|
+
store[k] = v
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @api private
|
122
|
+
def set(options)
|
123
|
+
store.clear
|
124
|
+
merge(options)
|
125
|
+
end
|
126
|
+
|
139
127
|
# Returns a Hash, initializing with default values if necessary.
|
140
128
|
# @api private
|
141
129
|
def store
|
@@ -144,6 +132,15 @@ module PaperTrail
|
|
144
132
|
}
|
145
133
|
end
|
146
134
|
|
135
|
+
# Returns a deep copy of the internal hash from our RequestStore. Keys are
|
136
|
+
# all symbols. Values are mostly primitives, but whodunnit can be a Proc.
|
137
|
+
# We cannot use Marshal.dump here because it doesn't support Proc. It is
|
138
|
+
# unclear exactly how `deep_dup` handles a Proc, but it doesn't complain.
|
139
|
+
# @api private
|
140
|
+
def to_h
|
141
|
+
store.deep_dup
|
142
|
+
end
|
143
|
+
|
147
144
|
# Provide a helpful error message if someone has a typo in one of their
|
148
145
|
# option keys. We don't validate option values here. That's traditionally
|
149
146
|
# been handled with casting (`to_s`, `!!`) in the accessor method.
|
@@ -31,16 +31,6 @@ module PaperTrail
|
|
31
31
|
arel_field.matches("%\"#{field}\":#{json_value}%")
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
35
|
-
def where_object_changes_condition(*)
|
36
|
-
raise <<-STR.squish.freeze
|
37
|
-
where_object_changes no longer supports reading JSON from a text
|
38
|
-
column. The old implementation was inaccurate, returning more records
|
39
|
-
than you wanted. This feature was deprecated in 7.1.0 and removed in
|
40
|
-
8.0.0. The json and jsonb datatypes are still supported. See the
|
41
|
-
discussion at https://github.com/paper-trail-gem/paper_trail/issues/803
|
42
|
-
STR
|
43
|
-
end
|
44
34
|
end
|
45
35
|
end
|
46
36
|
end
|
@@ -9,13 +9,23 @@ module PaperTrail
|
|
9
9
|
extend self # makes all instance methods become module methods as well
|
10
10
|
|
11
11
|
def load(string)
|
12
|
-
|
12
|
+
if use_safe_load?
|
13
|
+
::YAML.safe_load(
|
14
|
+
string,
|
15
|
+
permitted_classes: yaml_column_permitted_classes,
|
16
|
+
aliases: true
|
17
|
+
)
|
18
|
+
elsif ::YAML.respond_to?(:unsafe_load)
|
19
|
+
::YAML.unsafe_load(string)
|
20
|
+
else
|
21
|
+
::YAML.load(string)
|
22
|
+
end
|
13
23
|
end
|
14
24
|
|
15
25
|
# @param object (Hash | HashWithIndifferentAccess) - Coming from
|
16
26
|
# `recordable_object` `object` will be a plain `Hash`. However, due to
|
17
|
-
# recent [memory optimizations](https://
|
18
|
-
# `recordable_object_changes`, it will be a `HashWithIndifferentAccess`.
|
27
|
+
# recent [memory optimizations](https://github.com/paper-trail-gem/paper_trail/pull/1189),
|
28
|
+
# when coming from `recordable_object_changes`, it will be a `HashWithIndifferentAccess`.
|
19
29
|
def dump(object)
|
20
30
|
object = object.to_hash if object.is_a?(HashWithIndifferentAccess)
|
21
31
|
::YAML.dump object
|
@@ -27,16 +37,31 @@ module PaperTrail
|
|
27
37
|
arel_field.matches("%\n#{field}: #{value}\n%")
|
28
38
|
end
|
29
39
|
|
30
|
-
|
31
|
-
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
private
|
41
|
+
|
42
|
+
def use_safe_load?
|
43
|
+
if ::ActiveRecord.gem_version >= Gem::Version.new("7.0.3.1")
|
44
|
+
# `use_yaml_unsafe_load` may be removed in the future, at which point
|
45
|
+
# safe loading will be the default.
|
46
|
+
!defined?(ActiveRecord.use_yaml_unsafe_load) || !ActiveRecord.use_yaml_unsafe_load
|
47
|
+
elsif defined?(ActiveRecord::Base.use_yaml_unsafe_load)
|
48
|
+
# Rails 5.2.8.1, 6.0.5.1, 6.1.6.1
|
49
|
+
!ActiveRecord::Base.use_yaml_unsafe_load
|
50
|
+
else
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def yaml_column_permitted_classes
|
56
|
+
if defined?(ActiveRecord.yaml_column_permitted_classes)
|
57
|
+
# Rails >= 7.0.3.1
|
58
|
+
ActiveRecord.yaml_column_permitted_classes
|
59
|
+
elsif defined?(ActiveRecord::Base.yaml_column_permitted_classes)
|
60
|
+
# Rails 5.2.8.1, 6.0.5.1, 6.1.6.1
|
61
|
+
ActiveRecord::Base.yaml_column_permitted_classes
|
62
|
+
else
|
63
|
+
[]
|
64
|
+
end
|
40
65
|
end
|
41
66
|
end
|
42
67
|
end
|
@@ -11,15 +11,12 @@ module PaperTrail
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def serialize(array)
|
14
|
-
return serialize_with_ar(array) if active_record_pre_502?
|
15
14
|
array
|
16
15
|
end
|
17
16
|
|
18
17
|
def deserialize(array)
|
19
|
-
return deserialize_with_ar(array) if active_record_pre_502?
|
20
|
-
|
21
18
|
case array
|
22
|
-
# Needed for legacy
|
19
|
+
# Needed for legacy data. If serialized array is a string
|
23
20
|
# then it was serialized with Rails < 5.0.2.
|
24
21
|
when ::String then deserialize_with_ar(array)
|
25
22
|
else array
|
@@ -28,16 +25,6 @@ module PaperTrail
|
|
28
25
|
|
29
26
|
private
|
30
27
|
|
31
|
-
def active_record_pre_502?
|
32
|
-
::ActiveRecord.gem_version < Gem::Version.new("5.0.2")
|
33
|
-
end
|
34
|
-
|
35
|
-
def serialize_with_ar(array)
|
36
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.
|
37
|
-
new(@subtype, @delimiter).
|
38
|
-
serialize(array)
|
39
|
-
end
|
40
|
-
|
41
28
|
def deserialize_with_ar(array)
|
42
29
|
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.
|
43
30
|
new(@subtype, @delimiter).
|
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "paper_trail/attribute_serializers/object_changes_attribute"
|
4
|
+
require "paper_trail/queries/versions/where_attribute_changes"
|
4
5
|
require "paper_trail/queries/versions/where_object"
|
5
6
|
require "paper_trail/queries/versions/where_object_changes"
|
7
|
+
require "paper_trail/queries/versions/where_object_changes_from"
|
8
|
+
require "paper_trail/queries/versions/where_object_changes_to"
|
6
9
|
|
7
10
|
module PaperTrail
|
8
11
|
# Originally, PaperTrail did not provide this module, and all of this
|
@@ -12,23 +15,20 @@ module PaperTrail
|
|
12
15
|
module VersionConcern
|
13
16
|
extend ::ActiveSupport::Concern
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
18
|
+
E_YAML_PERMITTED_CLASSES = <<-EOS.squish.freeze
|
19
|
+
PaperTrail encountered a Psych::DisallowedClass error during
|
20
|
+
deserialization of YAML column, indicating that
|
21
|
+
yaml_column_permitted_classes has not been configured correctly. %s
|
22
|
+
EOS
|
21
23
|
|
24
|
+
included do
|
25
|
+
belongs_to :item, polymorphic: true, optional: true, inverse_of: false
|
22
26
|
validates_presence_of :event
|
23
27
|
after_create :enforce_version_limit!
|
24
28
|
end
|
25
29
|
|
26
30
|
# :nodoc:
|
27
31
|
module ClassMethods
|
28
|
-
def item_subtype_column_present?
|
29
|
-
column_names.include?("item_subtype")
|
30
|
-
end
|
31
|
-
|
32
32
|
def with_item_keys(item_type, item_id)
|
33
33
|
where item_type: item_type, item_id: item_id
|
34
34
|
end
|
@@ -46,7 +46,7 @@ module PaperTrail
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def not_creates
|
49
|
-
where
|
49
|
+
where.not(event: "create")
|
50
50
|
end
|
51
51
|
|
52
52
|
def between(start_time, end_time)
|
@@ -64,6 +64,18 @@ module PaperTrail
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
+
# Given an attribute like `"name"`, query the `versions.object_changes`
|
68
|
+
# column for any changes that modified the provided attribute.
|
69
|
+
#
|
70
|
+
# @api public
|
71
|
+
def where_attribute_changes(attribute)
|
72
|
+
unless attribute.is_a?(String) || attribute.is_a?(Symbol)
|
73
|
+
raise ArgumentError, "expected to receive a String or Symbol"
|
74
|
+
end
|
75
|
+
|
76
|
+
Queries::Versions::WhereAttributeChanges.new(self, attribute).execute
|
77
|
+
end
|
78
|
+
|
67
79
|
# Given a hash of attributes like `name: 'Joan'`, query the
|
68
80
|
# `versions.objects` column.
|
69
81
|
#
|
@@ -120,6 +132,36 @@ module PaperTrail
|
|
120
132
|
Queries::Versions::WhereObjectChanges.new(self, args).execute
|
121
133
|
end
|
122
134
|
|
135
|
+
# Given a hash of attributes like `name: 'Joan'`, query the
|
136
|
+
# `versions.objects_changes` column for changes where the version changed
|
137
|
+
# from the hash of attributes to other values.
|
138
|
+
#
|
139
|
+
# This is useful for finding versions where the attribute started with a
|
140
|
+
# known value and changed to something else. This is in comparison to
|
141
|
+
# `where_object_changes` which will find both the changes before and
|
142
|
+
# after.
|
143
|
+
#
|
144
|
+
# @api public
|
145
|
+
def where_object_changes_from(args = {})
|
146
|
+
raise ArgumentError, "expected to receive a Hash" unless args.is_a?(Hash)
|
147
|
+
Queries::Versions::WhereObjectChangesFrom.new(self, args).execute
|
148
|
+
end
|
149
|
+
|
150
|
+
# Given a hash of attributes like `name: 'Joan'`, query the
|
151
|
+
# `versions.objects_changes` column for changes where the version changed
|
152
|
+
# to the hash of attributes from other values.
|
153
|
+
#
|
154
|
+
# This is useful for finding versions where the attribute started with an
|
155
|
+
# unknown value and changed to a known value. This is in comparison to
|
156
|
+
# `where_object_changes` which will find both the changes before and
|
157
|
+
# after.
|
158
|
+
#
|
159
|
+
# @api public
|
160
|
+
def where_object_changes_to(args = {})
|
161
|
+
raise ArgumentError, "expected to receive a Hash" unless args.is_a?(Hash)
|
162
|
+
Queries::Versions::WhereObjectChangesTo.new(self, args).execute
|
163
|
+
end
|
164
|
+
|
123
165
|
def primary_key_is_int?
|
124
166
|
@primary_key_is_int ||= columns_hash[primary_key].type == :integer
|
125
167
|
rescue StandardError # TODO: Rescue something more specific
|
@@ -226,7 +268,7 @@ module PaperTrail
|
|
226
268
|
#
|
227
269
|
def reify(options = {})
|
228
270
|
unless self.class.column_names.include? "object"
|
229
|
-
raise "reify
|
271
|
+
raise Error, "reify requires an object column"
|
230
272
|
end
|
231
273
|
return nil if object.nil?
|
232
274
|
::PaperTrail::Reifier.reify(self, options)
|
@@ -273,7 +315,7 @@ module PaperTrail
|
|
273
315
|
|
274
316
|
# @api private
|
275
317
|
def load_changeset
|
276
|
-
if PaperTrail.config.object_changes_adapter
|
318
|
+
if PaperTrail.config.object_changes_adapter.respond_to?(:load_changeset)
|
277
319
|
return PaperTrail.config.object_changes_adapter.load_changeset(self)
|
278
320
|
end
|
279
321
|
|
@@ -312,7 +354,10 @@ module PaperTrail
|
|
312
354
|
else
|
313
355
|
begin
|
314
356
|
PaperTrail.serializer.load(object_changes)
|
315
|
-
rescue StandardError
|
357
|
+
rescue StandardError => e
|
358
|
+
if defined?(::Psych::Exception) && e.instance_of?(::Psych::Exception)
|
359
|
+
::Kernel.warn format(E_YAML_PERMITTED_CLASSES, e)
|
360
|
+
end
|
316
361
|
{}
|
317
362
|
end
|
318
363
|
end
|
@@ -339,16 +384,23 @@ module PaperTrail
|
|
339
384
|
# The version limit can be global or per-model.
|
340
385
|
#
|
341
386
|
# @api private
|
342
|
-
#
|
343
|
-
# TODO: Duplication: similar `constantize` in Reifier#version_reification_class
|
344
387
|
def version_limit
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
388
|
+
klass = item.class
|
389
|
+
if limit_option?(klass)
|
390
|
+
klass.paper_trail_options[:limit]
|
391
|
+
elsif base_class_limit_option?(klass)
|
392
|
+
klass.base_class.paper_trail_options[:limit]
|
393
|
+
else
|
394
|
+
PaperTrail.config.version_limit
|
350
395
|
end
|
351
|
-
|
396
|
+
end
|
397
|
+
|
398
|
+
def limit_option?(klass)
|
399
|
+
klass.respond_to?(:paper_trail_options) && klass.paper_trail_options.key?(:limit)
|
400
|
+
end
|
401
|
+
|
402
|
+
def base_class_limit_option?(klass)
|
403
|
+
klass.respond_to?(:base_class) && limit_option?(klass.base_class)
|
352
404
|
end
|
353
405
|
end
|
354
406
|
end
|
@@ -7,8 +7,8 @@ module PaperTrail
|
|
7
7
|
# because of this confusion, but it's not worth the breaking change.
|
8
8
|
# People are encouraged to use `PaperTrail.gem_version` instead.
|
9
9
|
module VERSION
|
10
|
-
MAJOR =
|
11
|
-
MINOR =
|
10
|
+
MAJOR = 15
|
11
|
+
MINOR = 2
|
12
12
|
TINY = 0
|
13
13
|
|
14
14
|
# Set PRE to nil unless it's a pre-release (beta, rc, etc.)
|
data/lib/paper_trail.rb
CHANGED
@@ -8,34 +8,24 @@
|
|
8
8
|
# can revisit this decision.
|
9
9
|
require "active_support/all"
|
10
10
|
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
11
|
+
# We used to `require "active_record"` here, but that was [replaced with a
|
12
|
+
# Railtie](https://github.com/paper-trail-gem/paper_trail/pull/1281) in PT 12.
|
13
|
+
# As a result, we cannot reference `ActiveRecord` in this file (ie. until our
|
14
|
+
# Railtie has loaded). If we did, it would cause [problems with non-Rails
|
15
|
+
# projects](https://github.com/paper-trail-gem/paper_trail/pull/1401).
|
16
16
|
|
17
|
-
require "
|
17
|
+
require "paper_trail/errors"
|
18
18
|
require "paper_trail/cleaner"
|
19
19
|
require "paper_trail/compatibility"
|
20
20
|
require "paper_trail/config"
|
21
|
-
require "paper_trail/has_paper_trail"
|
22
21
|
require "paper_trail/record_history"
|
23
|
-
require "paper_trail/reifier"
|
24
22
|
require "paper_trail/request"
|
25
|
-
require "paper_trail/version_concern"
|
26
23
|
require "paper_trail/version_number"
|
27
24
|
require "paper_trail/serializers/json"
|
28
|
-
require "paper_trail/serializers/yaml"
|
29
25
|
|
30
26
|
# An ActiveRecord extension that tracks changes to your models, for auditing or
|
31
27
|
# versioning.
|
32
28
|
module PaperTrail
|
33
|
-
E_RAILS_NOT_LOADED = <<-EOS.squish.freeze
|
34
|
-
PaperTrail has been loaded too early, before rails is loaded. This can
|
35
|
-
happen when another gem defines the ::Rails namespace, then PT is loaded,
|
36
|
-
all before rails is loaded. You may want to reorder your Gemfile, or defer
|
37
|
-
the loading of PT by using `require: false` and a manual require elsewhere.
|
38
|
-
EOS
|
39
29
|
E_TIMESTAMP_FIELD_CONFIG = <<-EOS.squish.freeze
|
40
30
|
PaperTrail.timestamp_field= has been removed, without replacement. It is no
|
41
31
|
longer configurable. The timestamp column in the versions table must now be
|
@@ -85,7 +75,7 @@ module PaperTrail
|
|
85
75
|
#
|
86
76
|
# @api public
|
87
77
|
def request(options = nil, &block)
|
88
|
-
if options.nil? && !
|
78
|
+
if options.nil? && !block
|
89
79
|
Request
|
90
80
|
else
|
91
81
|
Request.with(options, &block)
|
@@ -95,7 +85,7 @@ module PaperTrail
|
|
95
85
|
# Set the field which records when a version was created.
|
96
86
|
# @api public
|
97
87
|
def timestamp_field=(_field_name)
|
98
|
-
raise
|
88
|
+
raise Error, E_TIMESTAMP_FIELD_CONFIG
|
99
89
|
end
|
100
90
|
|
101
91
|
# Set the PaperTrail serializer. This setting affects all threads.
|
@@ -112,7 +102,7 @@ module PaperTrail
|
|
112
102
|
|
113
103
|
# Returns PaperTrail's global configuration object, a singleton. These
|
114
104
|
# settings affect all threads.
|
115
|
-
# @api
|
105
|
+
# @api public
|
116
106
|
def config
|
117
107
|
@config ||= PaperTrail::Config.instance
|
118
108
|
yield @config if block_given?
|
@@ -120,33 +110,33 @@ module PaperTrail
|
|
120
110
|
end
|
121
111
|
alias configure config
|
122
112
|
|
113
|
+
# @api public
|
123
114
|
def version
|
124
115
|
VERSION::STRING
|
125
116
|
end
|
126
|
-
end
|
127
|
-
end
|
128
117
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# to learn more about `on_load`.
|
133
|
-
ActiveSupport.on_load(:active_record) do
|
134
|
-
include PaperTrail::Model
|
135
|
-
end
|
118
|
+
def active_record_gte_7_0?
|
119
|
+
@active_record_gte_7_0 ||= ::ActiveRecord.gem_version >= ::Gem::Version.new("7.0.0")
|
120
|
+
end
|
136
121
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# so we check for presence of Rails.application.
|
141
|
-
if defined?(::Rails.application)
|
142
|
-
require "paper_trail/frameworks/rails"
|
143
|
-
else
|
144
|
-
::Kernel.warn(::PaperTrail::E_RAILS_NOT_LOADED)
|
122
|
+
def deprecator
|
123
|
+
@deprecator ||= ActiveSupport::Deprecation.new("16.0", "PaperTrail")
|
124
|
+
end
|
145
125
|
end
|
146
|
-
else
|
147
|
-
require "paper_trail/frameworks/active_record"
|
148
126
|
end
|
149
127
|
|
150
|
-
|
151
|
-
|
128
|
+
# PT is built on ActiveRecord, but does not require Rails. If Rails is defined,
|
129
|
+
# our Railtie makes sure not to load the AR-dependent parts of PT until AR is
|
130
|
+
# ready. A typical Rails `application.rb` has:
|
131
|
+
#
|
132
|
+
# ```
|
133
|
+
# require 'rails/all' # Defines `Rails`
|
134
|
+
# Bundler.require(*Rails.groups) # require 'paper_trail' (this file)
|
135
|
+
# ```
|
136
|
+
#
|
137
|
+
# Non-rails applications should take similar care to load AR before PT.
|
138
|
+
if defined?(Rails)
|
139
|
+
require "paper_trail/frameworks/rails"
|
140
|
+
else
|
141
|
+
require "paper_trail/frameworks/active_record"
|
152
142
|
end
|