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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e29e666977c2b4072eab98684b884cb43dba15e85367eb8221b9294ebad945c
4
- data.tar.gz: 750c5670a52675ab4dcc17bfd5389eaf87ebe4d4a3a68ccbb7ed2da1bd43e52f
3
+ metadata.gz: d64732632c8d2b579619cb3e4ec4f754a3bd82310f464aa715d79709fc0ba58d
4
+ data.tar.gz: 245ca1378370715e907ef2c7c9eaad6375a77aef0306729e98c2a046d4cb7c89
5
5
  SHA512:
6
- metadata.gz: b44b40b4683d987d67faf3fabb87d603cd6d99dad2c0c3b6b2859c5d30fd862fe3058e2fa1a1cea982a15ec45a4b8b194a55590b8d523aa8630d3b0644374b8e
7
- data.tar.gz: '0882176106dfa57ce49b0cf0c1267e2465e134a07719fc3436beec7cad5e10a23c6ff7d409b3332123cf8a5b7ce99e854351e4d60072894026027772f1cc14e8'
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 `.travis.yml`.
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.0" # not enforced in gemspec
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
- # If it is an attribute that is changing in an existing object,
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 = @record.paper_trail_options[:only].dup
211
- # Remove Hash arguments and then evaluate whether the attributes (the
212
- # keys of the hash) should also get pushed into the collection.
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
- if record_object_changes?
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
- return if @model_class.paper_trail_options[:on].include?(:create)
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
- return if @model_class.paper_trail_options[:on].include?(:update)
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.record_update(
100
- force: RAILS_LT_6_0,
101
- in_after_callback: true,
102
- is_touch: true
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] = [@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.load string
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
- if limit_option?(item.class)
380
- item.class.paper_trail_options[:limit]
381
- elsif base_class_limit_option?(item.class)
382
- item.class.base_class.paper_trail_options[:limit]
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
@@ -8,7 +8,7 @@ module PaperTrail
8
8
  # People are encouraged to use `PaperTrail.gem_version` instead.
9
9
  module VERSION
10
10
  MAJOR = 12
11
- MINOR = 1
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
@@ -26,6 +26,8 @@ module PaperTrail
26
26
  named created_at.
27
27
  EOS
28
28
 
29
+ RAILS_GTE_7_0 = ::ActiveRecord.gem_version >= ::Gem::Version.new("7.0.0")
30
+
29
31
  extend PaperTrail::Cleaner
30
32
 
31
33
  class << self
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.1.0
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: 2021-08-30 00:00:00.000000000 Z
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.0'
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.0'
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.19.0
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.19.0
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.20.0
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.20.0
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.11.3
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.11.3
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.4.0
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.4.0
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: '0.22'
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: '0.22'
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: '0.5'
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: '0.5'
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.0'
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.0'
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.5.0
363
+ version: 2.6.0
376
364
  required_rubygems_version: !ruby/object:Gem::Requirement
377
365
  requirements:
378
366
  - - ">="