paper_trail 6.0.2 → 7.0.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/.github/CONTRIBUTING.md +20 -0
- data/.rubocop.yml +30 -2
- data/.rubocop_todo.yml +20 -0
- data/.travis.yml +3 -5
- data/Appraisals +5 -6
- data/CHANGELOG.md +33 -0
- data/README.md +43 -81
- data/Rakefile +1 -1
- data/doc/bug_report_template.rb +4 -2
- data/gemfiles/ar_4.0.gemfile +7 -0
- data/gemfiles/ar_4.2.gemfile +0 -1
- data/lib/generators/paper_trail/templates/create_version_associations.rb +1 -1
- data/lib/generators/paper_trail/templates/create_versions.rb +1 -1
- data/lib/paper_trail.rb +7 -9
- data/lib/paper_trail/config.rb +0 -15
- data/lib/paper_trail/frameworks/rspec.rb +8 -2
- data/lib/paper_trail/model_config.rb +6 -2
- data/lib/paper_trail/record_trail.rb +3 -1
- data/lib/paper_trail/reifier.rb +43 -354
- data/lib/paper_trail/reifiers/belongs_to.rb +48 -0
- data/lib/paper_trail/reifiers/has_and_belongs_to_many.rb +50 -0
- data/lib/paper_trail/reifiers/has_many.rb +110 -0
- data/lib/paper_trail/reifiers/has_many_through.rb +90 -0
- data/lib/paper_trail/reifiers/has_one.rb +76 -0
- data/lib/paper_trail/serializers/yaml.rb +2 -25
- data/lib/paper_trail/version_concern.rb +5 -5
- data/lib/paper_trail/version_number.rb +7 -3
- data/paper_trail.gemspec +7 -34
- data/spec/controllers/articles_controller_spec.rb +1 -1
- data/spec/generators/install_generator_spec.rb +40 -34
- data/spec/models/animal_spec.rb +50 -25
- data/spec/models/boolit_spec.rb +8 -7
- data/spec/models/callback_modifier_spec.rb +13 -13
- data/spec/models/document_spec.rb +21 -0
- data/spec/models/gadget_spec.rb +35 -39
- data/spec/models/joined_version_spec.rb +4 -4
- data/spec/models/json_version_spec.rb +14 -15
- data/spec/models/not_on_update_spec.rb +1 -1
- data/spec/models/post_with_status_spec.rb +2 -2
- data/spec/models/skipper_spec.rb +4 -4
- data/spec/models/thing_spec.rb +1 -1
- data/spec/models/truck_spec.rb +1 -1
- data/spec/models/vehicle_spec.rb +1 -1
- data/spec/models/version_spec.rb +152 -168
- data/spec/models/widget_spec.rb +170 -196
- data/spec/modules/paper_trail_spec.rb +3 -3
- data/spec/modules/version_concern_spec.rb +5 -8
- data/spec/modules/version_number_spec.rb +11 -36
- data/spec/paper_trail/cleaner_spec.rb +152 -0
- data/spec/paper_trail/config_spec.rb +1 -1
- data/spec/paper_trail/serializers/custom_yaml_serializer_spec.rb +45 -0
- data/spec/paper_trail/serializers/json_spec.rb +57 -0
- data/spec/paper_trail/version_limit_spec.rb +55 -0
- data/spec/paper_trail_spec.rb +45 -32
- data/spec/requests/articles_spec.rb +4 -4
- data/test/dummy/app/models/custom_primary_key_record.rb +4 -2
- data/test/dummy/app/models/document.rb +1 -1
- data/test/dummy/app/models/not_on_update.rb +1 -1
- data/test/dummy/app/models/on/create.rb +6 -0
- data/test/dummy/app/models/on/destroy.rb +6 -0
- data/test/dummy/app/models/on/empty_array.rb +6 -0
- data/test/dummy/app/models/on/update.rb +6 -0
- data/test/dummy/app/models/person.rb +1 -0
- data/test/dummy/app/models/song.rb +19 -28
- data/test/dummy/config/application.rb +10 -43
- data/test/dummy/config/routes.rb +1 -1
- data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +25 -51
- data/test/dummy/db/schema.rb +29 -19
- data/test/test_helper.rb +0 -16
- data/test/unit/associations_test.rb +81 -81
- data/test/unit/model_test.rb +48 -131
- data/test/unit/serializer_test.rb +34 -45
- data/test/unit/serializers/mixin_json_test.rb +3 -1
- data/test/unit/serializers/yaml_test.rb +1 -5
- metadata +44 -19
- data/lib/paper_trail/frameworks/sinatra.rb +0 -40
- data/test/functional/modular_sinatra_test.rb +0 -46
- data/test/functional/sinatra_test.rb +0 -51
- data/test/unit/cleaner_test.rb +0 -151
- data/test/unit/inheritance_column_test.rb +0 -41
- data/test/unit/serializers/json_test.rb +0 -95
- data/test/unit/serializers/mixin_yaml_test.rb +0 -53
@@ -0,0 +1,48 @@
|
|
1
|
+
module PaperTrail
|
2
|
+
module Reifiers
|
3
|
+
# Reify a single `belongs_to` association of `model`.
|
4
|
+
# @api private
|
5
|
+
module BelongsTo
|
6
|
+
class << self
|
7
|
+
# @api private
|
8
|
+
def reify(assoc, model, options, transaction_id)
|
9
|
+
id = model.send(assoc.foreign_key)
|
10
|
+
version = load_version(assoc, id, transaction_id, options[:version_at])
|
11
|
+
record = load_record(assoc, id, options, version)
|
12
|
+
model.send("#{assoc.name}=".to_sym, record)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Given a `belongs_to` association and a `version`, return a record that
|
18
|
+
# can be assigned in order to reify that association.
|
19
|
+
# @api private
|
20
|
+
def load_record(assoc, id, options, version)
|
21
|
+
if version.nil?
|
22
|
+
assoc.klass.where(assoc.klass.primary_key => id).first
|
23
|
+
else
|
24
|
+
version.reify(
|
25
|
+
options.merge(
|
26
|
+
has_many: false,
|
27
|
+
has_one: false,
|
28
|
+
belongs_to: false,
|
29
|
+
has_and_belongs_to_many: false
|
30
|
+
)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Given a `belongs_to` association and an `id`, return a version record
|
36
|
+
# from the point in time identified by `transaction_id` or `version_at`.
|
37
|
+
# @api private
|
38
|
+
def load_version(assoc, id, transaction_id, version_at)
|
39
|
+
assoc.klass.paper_trail.version_class.
|
40
|
+
where("item_type = ?", assoc.class_name).
|
41
|
+
where("item_id = ?", id).
|
42
|
+
where("created_at >= ? OR transaction_id = ?", version_at, transaction_id).
|
43
|
+
order("id").limit(1).first
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module PaperTrail
|
2
|
+
module Reifiers
|
3
|
+
# Reify a single HABTM association of `model`.
|
4
|
+
# @api private
|
5
|
+
module HasAndBelongsToMany
|
6
|
+
class << self
|
7
|
+
# @api private
|
8
|
+
def reify(pt_enabled, assoc, model, options, transaction_id)
|
9
|
+
version_ids = ::PaperTrail::VersionAssociation.
|
10
|
+
where("foreign_key_name = ?", assoc.name).
|
11
|
+
where("version_id = ?", transaction_id).
|
12
|
+
pluck(:foreign_key_id)
|
13
|
+
|
14
|
+
model.send(assoc.name).proxy_association.target =
|
15
|
+
version_ids.map do |id|
|
16
|
+
if pt_enabled
|
17
|
+
version = load_version(assoc, id, transaction_id, options[:version_at])
|
18
|
+
if version
|
19
|
+
next version.reify(
|
20
|
+
options.merge(
|
21
|
+
has_many: false,
|
22
|
+
has_one: false,
|
23
|
+
belongs_to: false,
|
24
|
+
has_and_belongs_to_many: false
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
assoc.klass.where(assoc.klass.primary_key => id).first
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Given a HABTM association `assoc` and an `id`, return a version record
|
36
|
+
# from the point in time identified by `transaction_id` or `version_at`.
|
37
|
+
# @api private
|
38
|
+
def load_version(assoc, id, transaction_id, version_at)
|
39
|
+
assoc.klass.paper_trail.version_class.
|
40
|
+
where("item_type = ?", assoc.klass.name).
|
41
|
+
where("item_id = ?", id).
|
42
|
+
where("created_at >= ? OR transaction_id = ?", version_at, transaction_id).
|
43
|
+
order("id").
|
44
|
+
limit(1).
|
45
|
+
first
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module PaperTrail
|
2
|
+
module Reifiers
|
3
|
+
# Reify a single, direct (not `through`) `has_many` association of `model`.
|
4
|
+
# @api private
|
5
|
+
module HasMany
|
6
|
+
class << self
|
7
|
+
# @api private
|
8
|
+
def reify(assoc, model, options, transaction_id, version_table_name)
|
9
|
+
versions = load_versions_for_hm_association(
|
10
|
+
assoc,
|
11
|
+
model,
|
12
|
+
version_table_name,
|
13
|
+
transaction_id,
|
14
|
+
options[:version_at]
|
15
|
+
)
|
16
|
+
collection = Array.new model.send(assoc.name).reload # to avoid cache
|
17
|
+
prepare_array(collection, options, versions)
|
18
|
+
model.send(assoc.name).proxy_association.target = collection
|
19
|
+
end
|
20
|
+
|
21
|
+
# Replaces each record in `array` with its reified version, if present
|
22
|
+
# in `versions`.
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
# @param array - The collection to be modified.
|
26
|
+
# @param options
|
27
|
+
# @param versions - A `Hash` mapping IDs to `Version`s
|
28
|
+
# @return nil - Always returns `nil`
|
29
|
+
#
|
30
|
+
# Once modified by this method, `array` will be assigned to the
|
31
|
+
# AR association currently being reified.
|
32
|
+
#
|
33
|
+
def prepare_array(array, options, versions)
|
34
|
+
# Iterate each child to replace it with the previous value if there is
|
35
|
+
# a version after the timestamp.
|
36
|
+
array.map! do |record|
|
37
|
+
if (version = versions.delete(record.id)).nil?
|
38
|
+
record
|
39
|
+
elsif version.event == "create"
|
40
|
+
options[:mark_for_destruction] ? record.tap(&:mark_for_destruction) : nil
|
41
|
+
else
|
42
|
+
version.reify(
|
43
|
+
options.merge(
|
44
|
+
has_many: false,
|
45
|
+
has_one: false,
|
46
|
+
belongs_to: false,
|
47
|
+
has_and_belongs_to_many: false
|
48
|
+
)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Reify the rest of the versions and add them to the collection, these
|
54
|
+
# versions are for those that have been removed from the live
|
55
|
+
# associations.
|
56
|
+
array.concat(
|
57
|
+
versions.values.map { |v|
|
58
|
+
v.reify(
|
59
|
+
options.merge(
|
60
|
+
has_many: false,
|
61
|
+
has_one: false,
|
62
|
+
belongs_to: false,
|
63
|
+
has_and_belongs_to_many: false
|
64
|
+
)
|
65
|
+
)
|
66
|
+
}
|
67
|
+
)
|
68
|
+
|
69
|
+
array.compact!
|
70
|
+
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Given a SQL fragment that identifies the IDs of version records,
|
75
|
+
# returns a `Hash` mapping those IDs to `Version`s.
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
# @param klass - An ActiveRecord class.
|
79
|
+
# @param version_id_subquery - String. A SQL subquery that selects
|
80
|
+
# the IDs of version records.
|
81
|
+
# @return A `Hash` mapping IDs to `Version`s
|
82
|
+
#
|
83
|
+
def versions_by_id(klass, version_id_subquery)
|
84
|
+
klass.
|
85
|
+
paper_trail.version_class.
|
86
|
+
where("id IN (#{version_id_subquery})").
|
87
|
+
inject({}) { |a, e| a.merge!(e.item_id => e) }
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Given a `has_many` association on `model`, return the version records
|
93
|
+
# from the point in time identified by `tx_id` or `version_at`.
|
94
|
+
# @api private
|
95
|
+
def load_versions_for_hm_association(assoc, model, version_table, tx_id, version_at)
|
96
|
+
version_id_subquery = ::PaperTrail::VersionAssociation.
|
97
|
+
joins(model.class.version_association_name).
|
98
|
+
select("MIN(version_id)").
|
99
|
+
where("foreign_key_name = ?", assoc.foreign_key).
|
100
|
+
where("foreign_key_id = ?", model.id).
|
101
|
+
where("#{version_table}.item_type = ?", assoc.class_name).
|
102
|
+
where("created_at >= ? OR transaction_id = ?", version_at, tx_id).
|
103
|
+
group("item_id").
|
104
|
+
to_sql
|
105
|
+
versions_by_id(model.class, version_id_subquery)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module PaperTrail
|
2
|
+
module Reifiers
|
3
|
+
# Reify a single HMT association of `model`.
|
4
|
+
# @api private
|
5
|
+
module HasManyThrough
|
6
|
+
class << self
|
7
|
+
# @api private
|
8
|
+
def reify(assoc, model, options, transaction_id)
|
9
|
+
# Load the collection of through-models. For example, if `model` is a
|
10
|
+
# Chapter, having many Paragraphs through Sections, then
|
11
|
+
# `through_collection` will contain Sections.
|
12
|
+
through_collection = model.send(assoc.options[:through])
|
13
|
+
|
14
|
+
# Now, given the collection of "through" models (e.g. sections), load
|
15
|
+
# the collection of "target" models (e.g. paragraphs)
|
16
|
+
collection = collection(through_collection, assoc, options, transaction_id)
|
17
|
+
|
18
|
+
# Finally, assign the `collection` of "target" models, e.g. to
|
19
|
+
# `model.paragraphs`.
|
20
|
+
model.send(assoc.name).proxy_association.target = collection
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Examine the `source_reflection`, i.e. the "source" of `assoc` the
|
26
|
+
# `ThroughReflection`. The source can be a `BelongsToReflection`
|
27
|
+
# or a `HasManyReflection`.
|
28
|
+
#
|
29
|
+
# If the association is a has_many association again, then call
|
30
|
+
# reify_has_manys for each record in `through_collection`.
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def collection(through_collection, assoc, options, transaction_id)
|
34
|
+
if !assoc.source_reflection.belongs_to? && through_collection.present?
|
35
|
+
collection_through_has_many(through_collection, assoc, options, transaction_id)
|
36
|
+
else
|
37
|
+
collection_through_belongs_to(through_collection, assoc, options, transaction_id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
def collection_through_has_many(through_collection, assoc, options, transaction_id)
|
43
|
+
through_collection.each do |through_model|
|
44
|
+
::PaperTrail::Reifier.reify_has_manys(transaction_id, through_model, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
# At this point, the "through" part of the association chain has
|
48
|
+
# been reified, but not the final, "target" part. To continue our
|
49
|
+
# example, `model.sections` (including `model.sections.paragraphs`)
|
50
|
+
# has been loaded. However, the final "target" part of the
|
51
|
+
# association, that is, `model.paragraphs`, has not been loaded. So,
|
52
|
+
# we do that now.
|
53
|
+
through_collection.flat_map { |through_model|
|
54
|
+
through_model.public_send(assoc.name.to_sym).to_a
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def collection_through_belongs_to(through_collection, assoc, options, tx_id)
|
60
|
+
ids = through_collection.map { |through_model|
|
61
|
+
through_model.send(assoc.source_reflection.foreign_key)
|
62
|
+
}
|
63
|
+
versions = load_versions_for_hmt_association(assoc, ids, tx_id, options[:version_at])
|
64
|
+
collection = Array.new assoc.klass.where(assoc.klass.primary_key => ids)
|
65
|
+
Reifiers::HasMany.prepare_array(collection, options, versions)
|
66
|
+
collection
|
67
|
+
end
|
68
|
+
|
69
|
+
# Given a `has_many(through:)` association and an array of `ids`, return
|
70
|
+
# the version records from the point in time identified by `tx_id` or
|
71
|
+
# `version_at`.
|
72
|
+
# @api private
|
73
|
+
def load_versions_for_hmt_association(assoc, ids, tx_id, version_at)
|
74
|
+
version_id_subquery = assoc.klass.paper_trail.version_class.
|
75
|
+
select("MIN(id)").
|
76
|
+
where("item_type = ?", assoc.class_name).
|
77
|
+
where("item_id IN (?)", ids).
|
78
|
+
where(
|
79
|
+
"created_at >= ? OR transaction_id = ?",
|
80
|
+
version_at,
|
81
|
+
tx_id
|
82
|
+
).
|
83
|
+
group("item_id").
|
84
|
+
to_sql
|
85
|
+
Reifiers::HasMany.versions_by_id(assoc.klass, version_id_subquery)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module PaperTrail
|
2
|
+
module Reifiers
|
3
|
+
# Reify a single `has_one` association of `model`.
|
4
|
+
# @api private
|
5
|
+
module HasOne
|
6
|
+
class << self
|
7
|
+
# @api private
|
8
|
+
def reify(assoc, model, options, transaction_id)
|
9
|
+
version = load_version_for_has_one(assoc, model, transaction_id, options[:version_at])
|
10
|
+
return unless version
|
11
|
+
if version.event == "create"
|
12
|
+
create_event(assoc, model, options)
|
13
|
+
else
|
14
|
+
noncreate_event(assoc, model, options, version)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def create_event(assoc, model, options)
|
22
|
+
if options[:mark_for_destruction]
|
23
|
+
model.send(assoc.name).mark_for_destruction if model.send(assoc.name, true)
|
24
|
+
else
|
25
|
+
model.paper_trail.appear_as_new_record do
|
26
|
+
model.send "#{assoc.name}=", nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Given a has-one association `assoc` on `model`, return the version
|
32
|
+
# record from the point in time identified by `transaction_id` or `version_at`.
|
33
|
+
# @api private
|
34
|
+
def load_version_for_has_one(assoc, model, transaction_id, version_at)
|
35
|
+
version_table_name = model.class.paper_trail.version_class.table_name
|
36
|
+
model.class.paper_trail.version_class.joins(:version_associations).
|
37
|
+
where("version_associations.foreign_key_name = ?", assoc.foreign_key).
|
38
|
+
where("version_associations.foreign_key_id = ?", model.id).
|
39
|
+
where("#{version_table_name}.item_type = ?", assoc.class_name).
|
40
|
+
where("created_at >= ? OR transaction_id = ?", version_at, transaction_id).
|
41
|
+
order("#{version_table_name}.id ASC").
|
42
|
+
first
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api private
|
46
|
+
def noncreate_event(assoc, model, options, version)
|
47
|
+
child = version.reify(
|
48
|
+
options.merge(
|
49
|
+
has_many: false,
|
50
|
+
has_one: false,
|
51
|
+
belongs_to: false,
|
52
|
+
has_and_belongs_to_many: false
|
53
|
+
)
|
54
|
+
)
|
55
|
+
model.paper_trail.appear_as_new_record do
|
56
|
+
without_persisting(child) do
|
57
|
+
model.send "#{assoc.name}=", child
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Temporarily suppress #save so we can reassociate with the reified
|
63
|
+
# master of a has_one relationship. Since ActiveRecord 5 the related
|
64
|
+
# object is saved when it is assigned to the association. ActiveRecord
|
65
|
+
# 5 also happens to be the first version that provides #suppress.
|
66
|
+
def without_persisting(record)
|
67
|
+
if record.class.respond_to? :suppress
|
68
|
+
record.class.suppress { yield }
|
69
|
+
else
|
70
|
+
yield
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -24,33 +24,10 @@ module PaperTrail
|
|
24
24
|
# value in the serialized `object_changes`.
|
25
25
|
def where_object_changes_condition(arel_field, field, value)
|
26
26
|
# Need to check first (before) and secondary (after) fields
|
27
|
-
m1 =
|
28
|
-
m2 =
|
29
|
-
case yaml_engine_id
|
30
|
-
when :psych
|
31
|
-
m1 = "%\n#{field}:\n- #{value}\n%"
|
32
|
-
m2 = "%\n#{field}:\n-%\n- #{value}\n%"
|
33
|
-
when :syck
|
34
|
-
# Syck adds extra spaces into array dumps
|
35
|
-
m1 = "%\n#{field}: \n%- #{value}\n%"
|
36
|
-
m2 = "%\n#{field}: \n-%\n- #{value}\n%"
|
37
|
-
else
|
38
|
-
raise "Unknown yaml engine"
|
39
|
-
end
|
27
|
+
m1 = "%\n#{field}:\n- #{value}\n%"
|
28
|
+
m2 = "%\n#{field}:\n-%\n- #{value}\n%"
|
40
29
|
arel_field.matches(m1).or(arel_field.matches(m2))
|
41
30
|
end
|
42
|
-
|
43
|
-
# Returns a symbol identifying the YAML engine. Syck was removed from
|
44
|
-
# the ruby stdlib in ruby 2.0, but is still available as a gem.
|
45
|
-
# @api private
|
46
|
-
def yaml_engine_id
|
47
|
-
if (defined?(::YAML::ENGINE) && ::YAML::ENGINE.yamler == "psych") ||
|
48
|
-
(defined?(::Psych) && ::YAML == ::Psych)
|
49
|
-
:psych
|
50
|
-
else
|
51
|
-
:syck
|
52
|
-
end
|
53
|
-
end
|
54
31
|
end
|
55
32
|
end
|
56
33
|
end
|
@@ -162,13 +162,13 @@ module PaperTrail
|
|
162
162
|
# Returns whether the `object` column is using the `json` type supported
|
163
163
|
# by PostgreSQL.
|
164
164
|
def object_col_is_json?
|
165
|
-
|
165
|
+
%i(json jsonb).include?(columns_hash["object"].type)
|
166
166
|
end
|
167
167
|
|
168
168
|
# Returns whether the `object_changes` column is using the `json` type
|
169
169
|
# supported by PostgreSQL.
|
170
170
|
def object_changes_col_is_json?
|
171
|
-
|
171
|
+
%i(json jsonb).include?(columns_hash["object_changes"].try(:type))
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
@@ -306,13 +306,13 @@ module PaperTrail
|
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
309
|
-
#
|
310
|
-
# option, and if so enforces it.
|
309
|
+
# Enforces the `version_limit`, if set. Default: no limit.
|
311
310
|
# @api private
|
312
311
|
def enforce_version_limit!
|
313
312
|
limit = PaperTrail.config.version_limit
|
314
313
|
return unless limit.is_a? Numeric
|
315
|
-
previous_versions = sibling_versions.not_creates
|
314
|
+
previous_versions = sibling_versions.not_creates.
|
315
|
+
order(self.class.timestamp_sort_order("asc"))
|
316
316
|
return unless previous_versions.size > limit
|
317
317
|
excess_versions = previous_versions - previous_versions.last(limit)
|
318
318
|
excess_versions.map(&:destroy)
|