paper_trail 12.1.0 → 12.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +3 -1
- data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +6 -0
- data/lib/paper_trail/compatibility.rb +2 -2
- data/lib/paper_trail/events/base.rb +34 -19
- data/lib/paper_trail/events/update.rb +9 -4
- data/lib/paper_trail/model_config.rb +26 -18
- data/lib/paper_trail/serializers/yaml.rb +1 -1
- data/lib/paper_trail/version_concern.rb +6 -5
- data/lib/paper_trail/version_number.rb +1 -1
- data/lib/paper_trail.rb +2 -0
- metadata +23 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d64732632c8d2b579619cb3e4ec4f754a3bd82310f464aa715d79709fc0ba58d
|
4
|
+
data.tar.gz: 245ca1378370715e907ef2c7c9eaad6375a77aef0306729e98c2a046d4cb7c89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85ff44a62d2ca043e38805e510ac7bea9b5b2faba00e3e75b79262404b422730a2810e0e95adc0a30e867dd8d20fa21eb63d0b329908934272a591a14df0ce03
|
7
|
+
data.tar.gz: 8454773dd1a683fed0f79f6464a4d2f9944c399b81e4ce3ec205720a27db17ee4daade6793cddf5fe63e8422c3f6564893721ad02bef6abbd42d8e6e8a881b08
|
@@ -28,7 +28,9 @@ class CreateVersions < ActiveRecord::Migration<%= migration_version %>
|
|
28
28
|
# MySQL users should also upgrade to at least rails 4.2, which is the first
|
29
29
|
# version of ActiveRecord with support for fractional seconds in MySQL.
|
30
30
|
# (https://github.com/rails/rails/pull/14359)
|
31
|
-
#
|
31
|
+
#
|
32
|
+
# MySQL users should use the following line for `created_at`
|
33
|
+
# t.datetime :created_at, limit: 6
|
32
34
|
t.datetime :created_at
|
33
35
|
end
|
34
36
|
add_index :versions, %i(item_type item_id)
|
@@ -32,6 +32,12 @@ module PaperTrail
|
|
32
32
|
if defined_enums[attr] && val.is_a?(::String)
|
33
33
|
# Because PT 4 used to save the string version of enums to `object_changes`
|
34
34
|
val
|
35
|
+
elsif PaperTrail::RAILS_GTE_7_0 && val.is_a?(ActiveRecord::Type::Time::Value)
|
36
|
+
# Because Rails 7 time attribute throws a delegation error when you deserialize
|
37
|
+
# it with the factory.
|
38
|
+
# See ActiveRecord::Type::Time::Value crashes when loaded from YAML on rails 7.0
|
39
|
+
# https://github.com/rails/rails/issues/43966
|
40
|
+
val.instance_variable_get(:@time)
|
35
41
|
else
|
36
42
|
AttributeSerializerFactory.for(@klass, attr).deserialize(val)
|
37
43
|
end
|
@@ -8,7 +8,7 @@ module PaperTrail
|
|
8
8
|
#
|
9
9
|
# It is not safe to assume that a new version of rails will be compatible with
|
10
10
|
# PaperTrail. PT is only compatible with the versions of rails that it is
|
11
|
-
# tested against. See `.
|
11
|
+
# tested against. See `.github/workflows/test.yml`.
|
12
12
|
#
|
13
13
|
# However, as of
|
14
14
|
# [#1213](https://github.com/paper-trail-gem/paper_trail/pull/1213) our
|
@@ -18,7 +18,7 @@ module PaperTrail
|
|
18
18
|
# versions.
|
19
19
|
module Compatibility
|
20
20
|
ACTIVERECORD_GTE = ">= 5.2" # enforced in gemspec
|
21
|
-
ACTIVERECORD_LT = "< 7.
|
21
|
+
ACTIVERECORD_LT = "< 7.1" # not enforced in gemspec
|
22
22
|
|
23
23
|
E_INCOMPATIBLE_AR = <<-EOS
|
24
24
|
PaperTrail %s is not compatible with ActiveRecord %s. We allow PT
|
@@ -116,6 +116,20 @@ module PaperTrail
|
|
116
116
|
@changes_in_latest_version ||= load_changes_in_latest_version
|
117
117
|
end
|
118
118
|
|
119
|
+
# @api private
|
120
|
+
def evaluate_only
|
121
|
+
only = @record.paper_trail_options[:only].dup
|
122
|
+
# Remove Hash arguments and then evaluate whether the attributes (the
|
123
|
+
# keys of the hash) should also get pushed into the collection.
|
124
|
+
only.delete_if do |obj|
|
125
|
+
obj.is_a?(Hash) &&
|
126
|
+
obj.each { |attr, condition|
|
127
|
+
only << attr if condition.respond_to?(:call) && condition.call(@record)
|
128
|
+
}
|
129
|
+
end
|
130
|
+
only
|
131
|
+
end
|
132
|
+
|
119
133
|
# An attributed is "ignored" if it is listed in the `:ignore` option
|
120
134
|
# and/or the `:skip` option. Returns true if an ignored attribute has
|
121
135
|
# changed.
|
@@ -182,20 +196,28 @@ module PaperTrail
|
|
182
196
|
if value.respond_to?(:call)
|
183
197
|
value.call(@record)
|
184
198
|
elsif value.is_a?(Symbol) && @record.respond_to?(value, true)
|
185
|
-
|
186
|
-
# be sure to grab the current version.
|
187
|
-
if event != "create" &&
|
188
|
-
@record.has_attribute?(value) &&
|
189
|
-
attribute_changed_in_latest_version?(value)
|
190
|
-
attribute_in_previous_version(value, false)
|
191
|
-
else
|
192
|
-
@record.send(value)
|
193
|
-
end
|
199
|
+
metadatum_from_model_method(event, value)
|
194
200
|
else
|
195
201
|
value
|
196
202
|
end
|
197
203
|
end
|
198
204
|
|
205
|
+
# The model method can either be an attribute or a non-attribute method.
|
206
|
+
#
|
207
|
+
# If it is an attribute that is changing in an existing object,
|
208
|
+
# be sure to grab the correct version.
|
209
|
+
#
|
210
|
+
# @api private
|
211
|
+
def metadatum_from_model_method(event, method)
|
212
|
+
if event != "create" &&
|
213
|
+
@record.has_attribute?(method) &&
|
214
|
+
attribute_changed_in_latest_version?(method)
|
215
|
+
attribute_in_previous_version(method, false)
|
216
|
+
else
|
217
|
+
@record.send(method)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
199
221
|
# @api private
|
200
222
|
def notable_changes
|
201
223
|
changes_in_latest_version.delete_if { |k, _v|
|
@@ -207,16 +229,9 @@ module PaperTrail
|
|
207
229
|
def notably_changed
|
208
230
|
# Memoized to reduce memory usage
|
209
231
|
@notably_changed ||= begin
|
210
|
-
only =
|
211
|
-
|
212
|
-
|
213
|
-
only.delete_if do |obj|
|
214
|
-
obj.is_a?(Hash) &&
|
215
|
-
obj.each { |attr, condition|
|
216
|
-
only << attr if condition.respond_to?(:call) && condition.call(@record)
|
217
|
-
}
|
218
|
-
end
|
219
|
-
only.empty? ? changed_and_not_ignored : (changed_and_not_ignored & only)
|
232
|
+
only = evaluate_only
|
233
|
+
cani = changed_and_not_ignored
|
234
|
+
only.empty? ? cani : (cani & only)
|
220
235
|
end
|
221
236
|
end
|
222
237
|
|
@@ -35,16 +35,21 @@ module PaperTrail
|
|
35
35
|
if record_object?
|
36
36
|
data[:object] = recordable_object(@is_touch)
|
37
37
|
end
|
38
|
-
|
39
|
-
changes = @force_changes.nil? ? notable_changes : @force_changes
|
40
|
-
data[:object_changes] = prepare_object_changes(changes)
|
41
|
-
end
|
38
|
+
merge_object_changes_into(data)
|
42
39
|
merge_item_subtype_into(data)
|
43
40
|
merge_metadata_into(data)
|
44
41
|
end
|
45
42
|
|
46
43
|
private
|
47
44
|
|
45
|
+
# @api private
|
46
|
+
def merge_object_changes_into(data)
|
47
|
+
if record_object_changes?
|
48
|
+
changes = @force_changes.nil? ? notable_changes : @force_changes
|
49
|
+
data[:object_changes] = prepare_object_changes(changes)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
48
53
|
# `touch` cannot record `object_changes` because rails' `touch` does not
|
49
54
|
# perform dirty-tracking. Specifically, methods from `Dirty`, like
|
50
55
|
# `saved_changes`, return the same values before and after `touch`.
|
@@ -40,8 +40,7 @@ module PaperTrail
|
|
40
40
|
@model_class.after_create { |r|
|
41
41
|
r.paper_trail.record_create if r.paper_trail.save_version?
|
42
42
|
}
|
43
|
-
|
44
|
-
@model_class.paper_trail_options[:on] << :create
|
43
|
+
append_option_uniquely(:on, :create)
|
45
44
|
end
|
46
45
|
|
47
46
|
# Adds a callback that records a version before or after a "destroy" event.
|
@@ -49,7 +48,6 @@ module PaperTrail
|
|
49
48
|
# @api public
|
50
49
|
def on_destroy(recording_order = "before")
|
51
50
|
assert_valid_recording_order_for_on_destroy(recording_order)
|
52
|
-
|
53
51
|
@model_class.send(
|
54
52
|
"#{recording_order}_destroy",
|
55
53
|
lambda do |r|
|
@@ -57,9 +55,7 @@ module PaperTrail
|
|
57
55
|
r.paper_trail.record_destroy(recording_order)
|
58
56
|
end
|
59
57
|
)
|
60
|
-
|
61
|
-
return if @model_class.paper_trail_options[:on].include?(:destroy)
|
62
|
-
@model_class.paper_trail_options[:on] << :destroy
|
58
|
+
append_option_uniquely(:on, :destroy)
|
63
59
|
end
|
64
60
|
|
65
61
|
# Adds a callback that records a version after an "update" event.
|
@@ -81,8 +77,7 @@ module PaperTrail
|
|
81
77
|
@model_class.after_update { |r|
|
82
78
|
r.paper_trail.clear_version_instance
|
83
79
|
}
|
84
|
-
|
85
|
-
@model_class.paper_trail_options[:on] << :update
|
80
|
+
append_option_uniquely(:on, :update)
|
86
81
|
end
|
87
82
|
|
88
83
|
# Adds a callback that records a version after a "touch" event.
|
@@ -96,11 +91,13 @@ module PaperTrail
|
|
96
91
|
# @api public
|
97
92
|
def on_touch
|
98
93
|
@model_class.after_touch { |r|
|
99
|
-
r.paper_trail.
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
94
|
+
if r.paper_trail.save_version?
|
95
|
+
r.paper_trail.record_update(
|
96
|
+
force: RAILS_LT_6_0,
|
97
|
+
in_after_callback: true,
|
98
|
+
is_touch: true
|
99
|
+
)
|
100
|
+
end
|
104
101
|
}
|
105
102
|
end
|
106
103
|
|
@@ -127,6 +124,13 @@ module PaperTrail
|
|
127
124
|
RAILS_LT_6_0 = ::ActiveRecord.gem_version < ::Gem::Version.new("6.0.0")
|
128
125
|
private_constant :RAILS_LT_6_0
|
129
126
|
|
127
|
+
# @api private
|
128
|
+
def append_option_uniquely(option, value)
|
129
|
+
collection = @model_class.paper_trail_options.fetch(option)
|
130
|
+
return if collection.include?(value)
|
131
|
+
collection << value
|
132
|
+
end
|
133
|
+
|
130
134
|
# Raises an error if the provided class is an `abstract_class`.
|
131
135
|
# @api private
|
132
136
|
def assert_concrete_activerecord_class(class_name)
|
@@ -205,6 +209,14 @@ module PaperTrail
|
|
205
209
|
options
|
206
210
|
end
|
207
211
|
|
212
|
+
# Process an `ignore`, `skip`, or `only` option.
|
213
|
+
def event_attribute_option(option_name)
|
214
|
+
[@model_class.paper_trail_options[option_name]].
|
215
|
+
flatten.
|
216
|
+
compact.
|
217
|
+
map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
|
218
|
+
end
|
219
|
+
|
208
220
|
def get_versions_scope(options)
|
209
221
|
options[:versions][:scope] || -> { order(model.timestamp_sort_order) }
|
210
222
|
end
|
@@ -239,12 +251,8 @@ module PaperTrail
|
|
239
251
|
@model_class.paper_trail_options = options.dup
|
240
252
|
|
241
253
|
%i[ignore skip only].each do |k|
|
242
|
-
@model_class.paper_trail_options[k] =
|
243
|
-
flatten.
|
244
|
-
compact.
|
245
|
-
map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
|
254
|
+
@model_class.paper_trail_options[k] = event_attribute_option(k)
|
246
255
|
end
|
247
|
-
|
248
256
|
@model_class.paper_trail_options[:meta] ||= {}
|
249
257
|
end
|
250
258
|
end
|
@@ -9,7 +9,7 @@ module PaperTrail
|
|
9
9
|
extend self # makes all instance methods become module methods as well
|
10
10
|
|
11
11
|
def load(string)
|
12
|
-
::YAML.
|
12
|
+
::YAML.respond_to?(:unsafe_load) ? ::YAML.unsafe_load(string) : ::YAML.load(string)
|
13
13
|
end
|
14
14
|
|
15
15
|
# @param object (Hash | HashWithIndifferentAccess) - Coming from
|
@@ -16,7 +16,7 @@ module PaperTrail
|
|
16
16
|
extend ::ActiveSupport::Concern
|
17
17
|
|
18
18
|
included do
|
19
|
-
belongs_to :item, polymorphic: true, optional: true
|
19
|
+
belongs_to :item, polymorphic: true, optional: true, inverse_of: false
|
20
20
|
validates_presence_of :event
|
21
21
|
after_create :enforce_version_limit!
|
22
22
|
end
|
@@ -376,10 +376,11 @@ module PaperTrail
|
|
376
376
|
#
|
377
377
|
# @api private
|
378
378
|
def version_limit
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
379
|
+
klass = item.class
|
380
|
+
if limit_option?(klass)
|
381
|
+
klass.paper_trail_options[:limit]
|
382
|
+
elsif base_class_limit_option?(klass)
|
383
|
+
klass.base_class.paper_trail_options[:limit]
|
383
384
|
else
|
384
385
|
PaperTrail.config.version_limit
|
385
386
|
end
|
data/lib/paper_trail.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paper_trail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 12.
|
4
|
+
version: 12.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Stewart
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2022-01-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -60,28 +60,28 @@ dependencies:
|
|
60
60
|
requirements:
|
61
61
|
- - "~>"
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '11.
|
63
|
+
version: '11.1'
|
64
64
|
type: :development
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
68
|
- - "~>"
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: '11.
|
70
|
+
version: '11.1'
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: ffaker
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
75
|
- - "~>"
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 2.
|
77
|
+
version: '2.20'
|
78
78
|
type: :development
|
79
79
|
prerelease: false
|
80
80
|
version_requirements: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
82
|
- - "~>"
|
83
83
|
- !ruby/object:Gem::Version
|
84
|
-
version: 2.
|
84
|
+
version: '2.20'
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
86
|
name: generator_spec
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
@@ -158,14 +158,14 @@ dependencies:
|
|
158
158
|
requirements:
|
159
159
|
- - "~>"
|
160
160
|
- !ruby/object:Gem::Version
|
161
|
-
version: 1.
|
161
|
+
version: 1.22.2
|
162
162
|
type: :development
|
163
163
|
prerelease: false
|
164
164
|
version_requirements: !ruby/object:Gem::Requirement
|
165
165
|
requirements:
|
166
166
|
- - "~>"
|
167
167
|
- !ruby/object:Gem::Version
|
168
|
-
version: 1.
|
168
|
+
version: 1.22.2
|
169
169
|
- !ruby/object:Gem::Dependency
|
170
170
|
name: rubocop-packaging
|
171
171
|
requirement: !ruby/object:Gem::Requirement
|
@@ -200,14 +200,14 @@ dependencies:
|
|
200
200
|
requirements:
|
201
201
|
- - "~>"
|
202
202
|
- !ruby/object:Gem::Version
|
203
|
-
version: 2.
|
203
|
+
version: 2.12.4
|
204
204
|
type: :development
|
205
205
|
prerelease: false
|
206
206
|
version_requirements: !ruby/object:Gem::Requirement
|
207
207
|
requirements:
|
208
208
|
- - "~>"
|
209
209
|
- !ruby/object:Gem::Version
|
210
|
-
version: 2.
|
210
|
+
version: 2.12.4
|
211
211
|
- !ruby/object:Gem::Dependency
|
212
212
|
name: rubocop-rake
|
213
213
|
requirement: !ruby/object:Gem::Requirement
|
@@ -228,68 +228,56 @@ dependencies:
|
|
228
228
|
requirements:
|
229
229
|
- - "~>"
|
230
230
|
- !ruby/object:Gem::Version
|
231
|
-
version: 2.
|
231
|
+
version: 2.5.0
|
232
232
|
type: :development
|
233
233
|
prerelease: false
|
234
234
|
version_requirements: !ruby/object:Gem::Requirement
|
235
235
|
requirements:
|
236
236
|
- - "~>"
|
237
237
|
- !ruby/object:Gem::Version
|
238
|
-
version: 2.
|
238
|
+
version: 2.5.0
|
239
239
|
- !ruby/object:Gem::Dependency
|
240
240
|
name: simplecov
|
241
241
|
requirement: !ruby/object:Gem::Requirement
|
242
242
|
requirements:
|
243
|
-
- - "
|
244
|
-
- !ruby/object:Gem::Version
|
245
|
-
version: '0.21'
|
246
|
-
- - "<"
|
243
|
+
- - "~>"
|
247
244
|
- !ruby/object:Gem::Version
|
248
|
-
version:
|
245
|
+
version: 0.21.2
|
249
246
|
type: :development
|
250
247
|
prerelease: false
|
251
248
|
version_requirements: !ruby/object:Gem::Requirement
|
252
249
|
requirements:
|
253
|
-
- - "
|
254
|
-
- !ruby/object:Gem::Version
|
255
|
-
version: '0.21'
|
256
|
-
- - "<"
|
250
|
+
- - "~>"
|
257
251
|
- !ruby/object:Gem::Version
|
258
|
-
version:
|
252
|
+
version: 0.21.2
|
259
253
|
- !ruby/object:Gem::Dependency
|
260
254
|
name: mysql2
|
261
255
|
requirement: !ruby/object:Gem::Requirement
|
262
256
|
requirements:
|
263
257
|
- - "~>"
|
264
258
|
- !ruby/object:Gem::Version
|
265
|
-
version:
|
259
|
+
version: 0.5.3
|
266
260
|
type: :development
|
267
261
|
prerelease: false
|
268
262
|
version_requirements: !ruby/object:Gem::Requirement
|
269
263
|
requirements:
|
270
264
|
- - "~>"
|
271
265
|
- !ruby/object:Gem::Version
|
272
|
-
version:
|
266
|
+
version: 0.5.3
|
273
267
|
- !ruby/object:Gem::Dependency
|
274
268
|
name: pg
|
275
269
|
requirement: !ruby/object:Gem::Requirement
|
276
270
|
requirements:
|
277
|
-
- - "
|
278
|
-
- !ruby/object:Gem::Version
|
279
|
-
version: '0.18'
|
280
|
-
- - "<"
|
271
|
+
- - "~>"
|
281
272
|
- !ruby/object:Gem::Version
|
282
|
-
version: '2
|
273
|
+
version: '1.2'
|
283
274
|
type: :development
|
284
275
|
prerelease: false
|
285
276
|
version_requirements: !ruby/object:Gem::Requirement
|
286
277
|
requirements:
|
287
|
-
- - "
|
288
|
-
- !ruby/object:Gem::Version
|
289
|
-
version: '0.18'
|
290
|
-
- - "<"
|
278
|
+
- - "~>"
|
291
279
|
- !ruby/object:Gem::Version
|
292
|
-
version: '2
|
280
|
+
version: '1.2'
|
293
281
|
- !ruby/object:Gem::Dependency
|
294
282
|
name: sqlite3
|
295
283
|
requirement: !ruby/object:Gem::Requirement
|
@@ -372,7 +360,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
372
360
|
requirements:
|
373
361
|
- - ">="
|
374
362
|
- !ruby/object:Gem::Version
|
375
|
-
version: 2.
|
363
|
+
version: 2.6.0
|
376
364
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
377
365
|
requirements:
|
378
366
|
- - ">="
|