paper_trail 10.3.1 → 14.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +20 -0
- data/lib/generators/paper_trail/install/install_generator.rb +25 -7
- data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +4 -2
- data/lib/generators/paper_trail/migration_generator.rb +5 -4
- 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 +17 -45
- data/lib/paper_trail/compatibility.rb +3 -3
- data/lib/paper_trail/config.rb +0 -33
- data/lib/paper_trail/errors.rb +33 -0
- data/lib/paper_trail/events/base.rb +92 -69
- 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 +1 -9
- data/lib/paper_trail/frameworks/rails/railtie.rb +30 -0
- data/lib/paper_trail/frameworks/rails.rb +1 -2
- data/lib/paper_trail/has_paper_trail.rb +1 -1
- data/lib/paper_trail/model_config.rb +46 -46
- 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 +80 -64
- data/lib/paper_trail/reifier.rb +41 -26
- 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 +86 -41
- data/lib/paper_trail/version_number.rb +3 -3
- data/lib/paper_trail.rb +22 -40
- metadata +106 -45
- data/lib/paper_trail/frameworks/rails/engine.rb +0 -45
@@ -7,8 +7,6 @@ require "paper_trail/events/update"
|
|
7
7
|
module PaperTrail
|
8
8
|
# Represents the "paper trail" for a single record.
|
9
9
|
class RecordTrail
|
10
|
-
RAILS_GTE_5_1 = ::ActiveRecord.gem_version >= ::Gem::Version.new("5.1.0.beta1")
|
11
|
-
|
12
10
|
def initialize(record)
|
13
11
|
@record = record
|
14
12
|
end
|
@@ -27,14 +25,6 @@ module PaperTrail
|
|
27
25
|
@record.send("#{@record.class.version_association_name}=", nil)
|
28
26
|
end
|
29
27
|
|
30
|
-
# Is PT enabled for this particular record?
|
31
|
-
# @api private
|
32
|
-
def enabled?
|
33
|
-
PaperTrail.enabled? &&
|
34
|
-
PaperTrail.request.enabled? &&
|
35
|
-
PaperTrail.request.enabled_for_model?(@record.class)
|
36
|
-
end
|
37
|
-
|
38
28
|
# Returns true if this instance is the current, live one;
|
39
29
|
# returns false if this instance came from a previous version.
|
40
30
|
def live?
|
@@ -77,13 +67,6 @@ module PaperTrail
|
|
77
67
|
end
|
78
68
|
end
|
79
69
|
|
80
|
-
# PT-AT extends this method to add its transaction id.
|
81
|
-
#
|
82
|
-
# @api private
|
83
|
-
def data_for_create
|
84
|
-
{}
|
85
|
-
end
|
86
|
-
|
87
70
|
# `recording_order` is "after" or "before". See ModelConfig#on_destroy.
|
88
71
|
#
|
89
72
|
# @api private
|
@@ -107,14 +90,12 @@ module PaperTrail
|
|
107
90
|
end
|
108
91
|
end
|
109
92
|
|
110
|
-
# PT-AT extends this method to add its transaction id.
|
111
|
-
#
|
112
|
-
# @api private
|
113
|
-
def data_for_destroy
|
114
|
-
{}
|
115
|
-
end
|
116
|
-
|
117
93
|
# @api private
|
94
|
+
# @param force [boolean] Insert a `Version` even if `@record` has not
|
95
|
+
# `changed_notably?`.
|
96
|
+
# @param in_after_callback [boolean] True when called from an `after_update`
|
97
|
+
# or `after_touch` callback.
|
98
|
+
# @param is_touch [boolean] True when called from an `after_touch` callback.
|
118
99
|
# @return - The created version object, so that plugins can use it, e.g.
|
119
100
|
# paper_trail-association_tracking
|
120
101
|
def record_update(force:, in_after_callback:, is_touch:)
|
@@ -138,40 +119,6 @@ module PaperTrail
|
|
138
119
|
end
|
139
120
|
end
|
140
121
|
|
141
|
-
# PT-AT extends this method to add its transaction id.
|
142
|
-
#
|
143
|
-
# @api private
|
144
|
-
def data_for_update
|
145
|
-
{}
|
146
|
-
end
|
147
|
-
|
148
|
-
# @api private
|
149
|
-
# @return - The created version object, so that plugins can use it, e.g.
|
150
|
-
# paper_trail-association_tracking
|
151
|
-
def record_update_columns(changes)
|
152
|
-
return unless enabled?
|
153
|
-
event = Events::Update.new(@record, false, false, changes)
|
154
|
-
|
155
|
-
# Merge data from `Event` with data from PT-AT. We no longer use
|
156
|
-
# `data_for_update_columns` but PT-AT still does.
|
157
|
-
data = event.data.merge(data_for_update_columns)
|
158
|
-
|
159
|
-
versions_assoc = @record.send(@record.class.versions_association_name)
|
160
|
-
version = versions_assoc.create(data)
|
161
|
-
if version.errors.any?
|
162
|
-
log_version_errors(version, :update)
|
163
|
-
else
|
164
|
-
version
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# PT-AT extends this method to add its transaction id.
|
169
|
-
#
|
170
|
-
# @api private
|
171
|
-
def data_for_update_columns
|
172
|
-
{}
|
173
|
-
end
|
174
|
-
|
175
122
|
# Invoked via callback when a user attempts to persist a reified
|
176
123
|
# `Version`.
|
177
124
|
def reset_timestamp_attrs_for_update_if_needed
|
@@ -196,15 +143,17 @@ module PaperTrail
|
|
196
143
|
# Save, and create a version record regardless of options such as `:on`,
|
197
144
|
# `:if`, or `:unless`.
|
198
145
|
#
|
199
|
-
#
|
146
|
+
# `in_after_callback`: Indicates if this method is being called within an
|
147
|
+
# `after` callback. Defaults to `false`.
|
148
|
+
# `options`: Optional arguments passed to `save`.
|
200
149
|
#
|
201
150
|
# This is an "update" event. That is, we record the same data we would in
|
202
151
|
# the case of a normal AR `update`.
|
203
|
-
def save_with_version(
|
152
|
+
def save_with_version(in_after_callback: false, **options)
|
204
153
|
::PaperTrail.request(enabled: false) do
|
205
|
-
@record.save(
|
154
|
+
@record.save(**options)
|
206
155
|
end
|
207
|
-
record_update(force: true, in_after_callback:
|
156
|
+
record_update(force: true, in_after_callback: in_after_callback, is_touch: false)
|
208
157
|
end
|
209
158
|
|
210
159
|
# Like the `update_column` method from `ActiveRecord::Persistence`, but also
|
@@ -269,11 +218,22 @@ module PaperTrail
|
|
269
218
|
def build_version_on_update(force:, in_after_callback:, is_touch:)
|
270
219
|
event = Events::Update.new(@record, in_after_callback, is_touch, nil)
|
271
220
|
return unless force || event.changed_notably?
|
221
|
+
data = event.data
|
222
|
+
|
223
|
+
# Copy the (recently set) `updated_at` from the record to the `created_at`
|
224
|
+
# of the `Version`. Without this feature, these two timestamps would
|
225
|
+
# differ by a few milliseconds. To some people, it seems a little
|
226
|
+
# unnatural to tamper with creation timestamps in this way. But, this
|
227
|
+
# feature has existed for a long time, almost a decade now, and some users
|
228
|
+
# may rely on it now.
|
229
|
+
if @record.respond_to?(:updated_at)
|
230
|
+
data[:created_at] = @record.updated_at
|
231
|
+
end
|
272
232
|
|
273
233
|
# Merge data from `Event` with data from PT-AT. We no longer use
|
274
234
|
# `data_for_update` but PT-AT still does. To save memory, we use `merge!`
|
275
235
|
# instead of `merge`.
|
276
|
-
data
|
236
|
+
data.merge!(data_for_update)
|
277
237
|
|
278
238
|
# Using `version_class.new` reduces memory usage compared to
|
279
239
|
# `versions_assoc.build`. It's a trade-off though. We have to clear
|
@@ -282,13 +242,69 @@ module PaperTrail
|
|
282
242
|
@record.class.paper_trail.version_class.new(data)
|
283
243
|
end
|
284
244
|
|
245
|
+
# PT-AT extends this method to add its transaction id.
|
246
|
+
#
|
247
|
+
# @api public
|
248
|
+
def data_for_create
|
249
|
+
{}
|
250
|
+
end
|
251
|
+
|
252
|
+
# PT-AT extends this method to add its transaction id.
|
253
|
+
#
|
254
|
+
# @api public
|
255
|
+
def data_for_destroy
|
256
|
+
{}
|
257
|
+
end
|
258
|
+
|
259
|
+
# PT-AT extends this method to add its transaction id.
|
260
|
+
#
|
261
|
+
# @api public
|
262
|
+
def data_for_update
|
263
|
+
{}
|
264
|
+
end
|
265
|
+
|
266
|
+
# PT-AT extends this method to add its transaction id.
|
267
|
+
#
|
268
|
+
# @api public
|
269
|
+
def data_for_update_columns
|
270
|
+
{}
|
271
|
+
end
|
272
|
+
|
273
|
+
# Is PT enabled for this particular record?
|
274
|
+
# @api private
|
275
|
+
def enabled?
|
276
|
+
PaperTrail.enabled? &&
|
277
|
+
PaperTrail.request.enabled? &&
|
278
|
+
PaperTrail.request.enabled_for_model?(@record.class)
|
279
|
+
end
|
280
|
+
|
285
281
|
def log_version_errors(version, action)
|
286
282
|
version.logger&.warn(
|
287
283
|
"Unable to create version for #{action} of #{@record.class.name}" \
|
288
|
-
|
284
|
+
"##{@record.id}: " + version.errors.full_messages.join(", ")
|
289
285
|
)
|
290
286
|
end
|
291
287
|
|
288
|
+
# @api private
|
289
|
+
# @return - The created version object, so that plugins can use it, e.g.
|
290
|
+
# paper_trail-association_tracking
|
291
|
+
def record_update_columns(changes)
|
292
|
+
return unless enabled?
|
293
|
+
data = Events::Update.new(@record, false, false, changes).data
|
294
|
+
|
295
|
+
# Merge data from `Event` with data from PT-AT. We no longer use
|
296
|
+
# `data_for_update_columns` but PT-AT still does.
|
297
|
+
data.merge!(data_for_update_columns)
|
298
|
+
|
299
|
+
versions_assoc = @record.send(@record.class.versions_association_name)
|
300
|
+
version = versions_assoc.create(data)
|
301
|
+
if version.errors.any?
|
302
|
+
log_version_errors(version, :update)
|
303
|
+
else
|
304
|
+
version
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
292
308
|
def version
|
293
309
|
@record.public_send(@record.class.version_association_name)
|
294
310
|
end
|
data/lib/paper_trail/reifier.rb
CHANGED
@@ -52,26 +52,29 @@ module PaperTrail
|
|
52
52
|
# not the actual subclass. If `type` is present but empty, the class is
|
53
53
|
# the base class.
|
54
54
|
def init_model(attrs, options, version)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
model = item_found
|
69
|
-
init_unversioned_attrs(attrs, model)
|
70
|
-
end
|
55
|
+
klass = version_reification_class(version, attrs)
|
56
|
+
|
57
|
+
# The `dup` option and destroyed version always returns a new object,
|
58
|
+
# otherwise we should attempt to load item or to look for the item
|
59
|
+
# outside of default scope(s).
|
60
|
+
model = if options[:dup] == true || version.event == "destroy"
|
61
|
+
klass.new
|
62
|
+
else
|
63
|
+
version.item || init_model_by_finding_item_id(klass, version) || klass.new
|
64
|
+
end
|
65
|
+
|
66
|
+
if options[:unversioned_attributes] == :nil && !model.new_record?
|
67
|
+
init_unversioned_attrs(attrs, model)
|
71
68
|
end
|
69
|
+
|
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
|
@@ -88,9 +91,7 @@ module PaperTrail
|
|
88
91
|
#
|
89
92
|
# @api private
|
90
93
|
def reify_attribute(k, v, model, version)
|
91
|
-
|
92
|
-
is_enum_without_type_caster = ::ActiveRecord::VERSION::MAJOR < 5 && enums.key?(k)
|
93
|
-
if model.has_attribute?(k) && !is_enum_without_type_caster
|
94
|
+
if model.has_attribute?(k)
|
94
95
|
model[k.to_sym] = v
|
95
96
|
elsif model.respond_to?("#{k}=")
|
96
97
|
model.send("#{k}=", v)
|
@@ -111,21 +112,35 @@ module PaperTrail
|
|
111
112
|
end
|
112
113
|
|
113
114
|
# Given a `version`, return the class to reify. This method supports
|
114
|
-
# Single Table Inheritance (STI) with custom inheritance columns
|
115
|
+
# Single Table Inheritance (STI) with custom inheritance columns and
|
116
|
+
# custom inheritance column values.
|
115
117
|
#
|
116
118
|
# For example, imagine a `version` whose `item_type` is "Animal". The
|
117
119
|
# `animals` table is an STI table (it has cats and dogs) and it has a
|
118
120
|
# custom inheritance column, `species`. If `attrs["species"]` is "Dog",
|
119
121
|
# this method returns the constant `Dog`. If `attrs["species"]` is blank,
|
120
|
-
# this method returns the constant `Animal`.
|
121
|
-
#
|
122
|
+
# this method returns the constant `Animal`.
|
123
|
+
#
|
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.
|
122
128
|
#
|
123
|
-
#
|
129
|
+
# You can see these particular examples in action in
|
130
|
+
# `spec/models/animal_spec.rb` and `spec/models/plant_spec.rb`
|
124
131
|
def version_reification_class(version, attrs)
|
125
|
-
|
132
|
+
clazz = version.item_type.constantize
|
133
|
+
inheritance_column_name = clazz.inheritance_column
|
126
134
|
inher_col_value = attrs[inheritance_column_name]
|
127
|
-
|
128
|
-
|
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)
|
129
144
|
end
|
130
145
|
end
|
131
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).
|