paper_trail 12.0.0 → 12.3.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 +15 -3
- data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +4 -2
- data/lib/generators/paper_trail/update_item_subtype/update_item_subtype_generator.rb +4 -2
- data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +6 -0
- data/lib/paper_trail/compatibility.rb +2 -2
- data/lib/paper_trail/errors.rb +33 -0
- data/lib/paper_trail/events/base.rb +47 -28
- data/lib/paper_trail/events/update.rb +23 -4
- data/lib/paper_trail/model_config.rb +49 -42
- 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 +7 -12
- data/lib/paper_trail/queries/versions/where_object_changes_from.rb +7 -15
- data/lib/paper_trail/queries/versions/where_object_changes_to.rb +57 -0
- data/lib/paper_trail/record_trail.rb +6 -4
- data/lib/paper_trail/reifier.rb +27 -10
- data/lib/paper_trail/request.rb +0 -3
- data/lib/paper_trail/serializers/json.rb +0 -18
- data/lib/paper_trail/serializers/yaml.rb +1 -21
- data/lib/paper_trail/version_concern.rb +47 -15
- data/lib/paper_trail/version_number.rb +1 -1
- data/lib/paper_trail.rb +5 -2
- metadata +64 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0f6ef6591b15081a76d93a70d959527f8cdc53cc3a6343ab6f1b7c40ef6695e
|
4
|
+
data.tar.gz: 202ee3126567ab99b39f8c76039fb7e20a4eb5e10e0e0880e867f19f228ace63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c144126a2d8cec5537ef218b6637ee2ff6e6863de2e935facf6ad020dba6c2fb46bc5c13ed2ab674e9230c264d6e87905415ebc3c1e4bee5fbe50b1e73285663
|
7
|
+
data.tar.gz: 96530aebe8af35a95d47b6a5deadd3797b2d9255b28156f24a9f1be67fe629b254747d39ccad4d8f5d348d9fd74300b4b865ff9b32125c0951b14cf5d13ed60f
|
@@ -20,6 +20,12 @@ module PaperTrail
|
|
20
20
|
default: false,
|
21
21
|
desc: "Store changeset (diff) with each version"
|
22
22
|
)
|
23
|
+
class_option(
|
24
|
+
:uuid,
|
25
|
+
type: :boolean,
|
26
|
+
default: false,
|
27
|
+
desc: "Use uuid instead of bigint for item_id type (use only if tables use UUIDs)"
|
28
|
+
)
|
23
29
|
|
24
30
|
desc "Generates (but does not run) a migration to add a versions table." \
|
25
31
|
" See section 5.c. Generators in README.md for more information."
|
@@ -28,7 +34,8 @@ module PaperTrail
|
|
28
34
|
add_paper_trail_migration(
|
29
35
|
"create_versions",
|
30
36
|
item_type_options: item_type_options,
|
31
|
-
versions_table_options: versions_table_options
|
37
|
+
versions_table_options: versions_table_options,
|
38
|
+
item_id_type_options: item_id_type_options
|
32
39
|
)
|
33
40
|
if options.with_changes?
|
34
41
|
add_paper_trail_migration("add_object_changes_to_versions")
|
@@ -37,13 +44,18 @@ module PaperTrail
|
|
37
44
|
|
38
45
|
private
|
39
46
|
|
47
|
+
# To use uuid instead of integer for primary key
|
48
|
+
def item_id_type_options
|
49
|
+
options.uuid? ? "string" : "bigint"
|
50
|
+
end
|
51
|
+
|
40
52
|
# MySQL 5.6 utf8mb4 limit is 191 chars for keys used in indexes.
|
41
53
|
# See https://github.com/paper-trail-gem/paper_trail/issues/651
|
42
54
|
def item_type_options
|
43
55
|
if mysql?
|
44
|
-
",
|
56
|
+
", null: false, limit: 191"
|
45
57
|
else
|
46
|
-
",
|
58
|
+
", null: false"
|
47
59
|
end
|
48
60
|
end
|
49
61
|
|
@@ -11,7 +11,7 @@ class CreateVersions < ActiveRecord::Migration<%= migration_version %>
|
|
11
11
|
def change
|
12
12
|
create_table :versions<%= versions_table_options %> do |t|
|
13
13
|
t.string :item_type<%= item_type_options %>
|
14
|
-
t
|
14
|
+
t.<%= item_id_type_options %> :item_id, null: false
|
15
15
|
t.string :event, null: false
|
16
16
|
t.string :whodunnit
|
17
17
|
t.text :object, limit: TEXT_BYTES
|
@@ -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)
|
@@ -7,8 +7,10 @@ module PaperTrail
|
|
7
7
|
class UpdateItemSubtypeGenerator < MigrationGenerator
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
9
9
|
|
10
|
-
desc
|
11
|
-
"
|
10
|
+
desc(
|
11
|
+
"Generates (but does not run) a migration to update item_subtype for "\
|
12
|
+
"STI entries in an existing versions table."
|
13
|
+
)
|
12
14
|
|
13
15
|
def create_migration_file
|
14
16
|
add_paper_trail_migration("update_versions_for_item_subtype", sti_type_options: options)
|
@@ -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 = "<
|
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
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PaperTrail
|
4
|
+
# Generic PaperTrail exception.
|
5
|
+
# @api public
|
6
|
+
class Error < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
# An unexpected option, perhaps a typo, was passed to a public API method.
|
10
|
+
# @api public
|
11
|
+
class InvalidOption < Error
|
12
|
+
end
|
13
|
+
|
14
|
+
# The application's database schema is not supported.
|
15
|
+
# @api public
|
16
|
+
class UnsupportedSchema < Error
|
17
|
+
end
|
18
|
+
|
19
|
+
# The application's database column type is not supported.
|
20
|
+
# @api public
|
21
|
+
class UnsupportedColumnType < UnsupportedSchema
|
22
|
+
def initialize(method:, expected:, actual:)
|
23
|
+
super(
|
24
|
+
format(
|
25
|
+
"%s expected %s column, got %s",
|
26
|
+
method,
|
27
|
+
expected,
|
28
|
+
actual
|
29
|
+
)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -109,19 +109,25 @@ module PaperTrail
|
|
109
109
|
@changed_in_latest_version ||= changes_in_latest_version.keys
|
110
110
|
end
|
111
111
|
|
112
|
-
#
|
113
|
-
# https://github.com/paper-trail-gem/paper_trail/pull/899
|
112
|
+
# Memoized to reduce memory usage
|
114
113
|
#
|
115
114
|
# @api private
|
116
115
|
def changes_in_latest_version
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
116
|
+
@changes_in_latest_version ||= load_changes_in_latest_version
|
117
|
+
end
|
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
|
+
}
|
124
129
|
end
|
130
|
+
only
|
125
131
|
end
|
126
132
|
|
127
133
|
# An attributed is "ignored" if it is listed in the `:ignore` option
|
@@ -134,6 +140,18 @@ module PaperTrail
|
|
134
140
|
ignored.any? && (changed_in_latest_version & ignored).any?
|
135
141
|
end
|
136
142
|
|
143
|
+
# Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
|
144
|
+
# https://github.com/paper-trail-gem/paper_trail/pull/899
|
145
|
+
#
|
146
|
+
# @api private
|
147
|
+
def load_changes_in_latest_version
|
148
|
+
if @in_after_callback
|
149
|
+
@record.saved_changes
|
150
|
+
else
|
151
|
+
@record.changes
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
137
155
|
# PT 10 has a new optional column, `item_subtype`
|
138
156
|
#
|
139
157
|
# @api private
|
@@ -178,20 +196,28 @@ module PaperTrail
|
|
178
196
|
if value.respond_to?(:call)
|
179
197
|
value.call(@record)
|
180
198
|
elsif value.is_a?(Symbol) && @record.respond_to?(value, true)
|
181
|
-
|
182
|
-
# be sure to grab the current version.
|
183
|
-
if event != "create" &&
|
184
|
-
@record.has_attribute?(value) &&
|
185
|
-
attribute_changed_in_latest_version?(value)
|
186
|
-
attribute_in_previous_version(value, false)
|
187
|
-
else
|
188
|
-
@record.send(value)
|
189
|
-
end
|
199
|
+
metadatum_from_model_method(event, value)
|
190
200
|
else
|
191
201
|
value
|
192
202
|
end
|
193
203
|
end
|
194
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
|
+
|
195
221
|
# @api private
|
196
222
|
def notable_changes
|
197
223
|
changes_in_latest_version.delete_if { |k, _v|
|
@@ -203,16 +229,9 @@ module PaperTrail
|
|
203
229
|
def notably_changed
|
204
230
|
# Memoized to reduce memory usage
|
205
231
|
@notably_changed ||= begin
|
206
|
-
only =
|
207
|
-
|
208
|
-
|
209
|
-
only.delete_if do |obj|
|
210
|
-
obj.is_a?(Hash) &&
|
211
|
-
obj.each { |attr, condition|
|
212
|
-
only << attr if condition.respond_to?(:call) && condition.call(@record)
|
213
|
-
}
|
214
|
-
end
|
215
|
-
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)
|
216
235
|
end
|
217
236
|
end
|
218
237
|
|
@@ -35,16 +35,35 @@ 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
|
|
43
|
+
# If it is a touch event, and changed are empty, it is assumed to be
|
44
|
+
# implicit `touch` mutation, and will a version is created.
|
45
|
+
#
|
46
|
+
# See https://github.com/rails/rails/commit/dcb825902d79d0f6baba956f7c6ec5767611353e
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
def changed_notably?
|
50
|
+
if @is_touch && changes_in_latest_version.empty?
|
51
|
+
true
|
52
|
+
else
|
53
|
+
super
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
46
57
|
private
|
47
58
|
|
59
|
+
# @api private
|
60
|
+
def merge_object_changes_into(data)
|
61
|
+
if record_object_changes?
|
62
|
+
changes = @force_changes.nil? ? notable_changes : @force_changes
|
63
|
+
data[:object_changes] = prepare_object_changes(changes)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
48
67
|
# `touch` cannot record `object_changes` because rails' `touch` does not
|
49
68
|
# perform dirty-tracking. Specifically, methods from `Dirty`, like
|
50
69
|
# `saved_changes`, return the same values before and after `touch`.
|
@@ -18,11 +18,6 @@ module PaperTrail
|
|
18
18
|
`abstract_class`. This is fine, but all application models must be
|
19
19
|
configured to use concrete (not abstract) version models.
|
20
20
|
STR
|
21
|
-
E_MODEL_LIMIT_REQUIRES_ITEM_SUBTYPE = <<~STR.squish.freeze
|
22
|
-
To use PaperTrail's per-model limit in your %s model, you must have an
|
23
|
-
item_subtype column in your versions table. See documentation sections
|
24
|
-
2.e.1 Per-model limit, and 4.b.1 The optional item_subtype column.
|
25
|
-
STR
|
26
21
|
DPR_PASSING_ASSOC_NAME_DIRECTLY_TO_VERSIONS_OPTION = <<~STR.squish
|
27
22
|
Passing versions association name as `has_paper_trail versions: %{versions_name}`
|
28
23
|
is deprecated. Use `has_paper_trail versions: {name: %{versions_name}}` instead.
|
@@ -45,22 +40,14 @@ module PaperTrail
|
|
45
40
|
@model_class.after_create { |r|
|
46
41
|
r.paper_trail.record_create if r.paper_trail.save_version?
|
47
42
|
}
|
48
|
-
|
49
|
-
@model_class.paper_trail_options[:on] << :create
|
43
|
+
append_option_uniquely(:on, :create)
|
50
44
|
end
|
51
45
|
|
52
46
|
# Adds a callback that records a version before or after a "destroy" event.
|
53
47
|
#
|
54
48
|
# @api public
|
55
49
|
def on_destroy(recording_order = "before")
|
56
|
-
|
57
|
-
raise ArgumentError, 'recording order can only be "after" or "before"'
|
58
|
-
end
|
59
|
-
|
60
|
-
if recording_order.to_s == "after" && cannot_record_after_destroy?
|
61
|
-
raise E_CANNOT_RECORD_AFTER_DESTROY
|
62
|
-
end
|
63
|
-
|
50
|
+
assert_valid_recording_order_for_on_destroy(recording_order)
|
64
51
|
@model_class.send(
|
65
52
|
"#{recording_order}_destroy",
|
66
53
|
lambda do |r|
|
@@ -68,9 +55,7 @@ module PaperTrail
|
|
68
55
|
r.paper_trail.record_destroy(recording_order)
|
69
56
|
end
|
70
57
|
)
|
71
|
-
|
72
|
-
return if @model_class.paper_trail_options[:on].include?(:destroy)
|
73
|
-
@model_class.paper_trail_options[:on] << :destroy
|
58
|
+
append_option_uniquely(:on, :destroy)
|
74
59
|
end
|
75
60
|
|
76
61
|
# Adds a callback that records a version after an "update" event.
|
@@ -92,19 +77,27 @@ module PaperTrail
|
|
92
77
|
@model_class.after_update { |r|
|
93
78
|
r.paper_trail.clear_version_instance
|
94
79
|
}
|
95
|
-
|
96
|
-
@model_class.paper_trail_options[:on] << :update
|
80
|
+
append_option_uniquely(:on, :update)
|
97
81
|
end
|
98
82
|
|
99
83
|
# Adds a callback that records a version after a "touch" event.
|
84
|
+
#
|
85
|
+
# Rails < 6.0 has a bug where dirty-tracking does not occur during
|
86
|
+
# a `touch`. (https://github.com/rails/rails/issues/33429) See also:
|
87
|
+
# https://github.com/paper-trail-gem/paper_trail/issues/1121
|
88
|
+
# https://github.com/paper-trail-gem/paper_trail/issues/1161
|
89
|
+
# https://github.com/paper-trail-gem/paper_trail/pull/1285
|
90
|
+
#
|
100
91
|
# @api public
|
101
92
|
def on_touch
|
102
93
|
@model_class.after_touch { |r|
|
103
|
-
r.paper_trail.
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
108
101
|
}
|
109
102
|
end
|
110
103
|
|
@@ -117,7 +110,6 @@ module PaperTrail
|
|
117
110
|
@model_class.send :include, ::PaperTrail::Model::InstanceMethods
|
118
111
|
setup_options(options)
|
119
112
|
setup_associations(options)
|
120
|
-
check_presence_of_item_subtype_column(options)
|
121
113
|
@model_class.after_rollback { paper_trail.clear_rolled_back_versions }
|
122
114
|
setup_callbacks_from_options options[:on]
|
123
115
|
end
|
@@ -129,26 +121,37 @@ module PaperTrail
|
|
129
121
|
|
130
122
|
private
|
131
123
|
|
124
|
+
RAILS_LT_6_0 = ::ActiveRecord.gem_version < ::Gem::Version.new("6.0.0")
|
125
|
+
private_constant :RAILS_LT_6_0
|
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
|
+
|
132
134
|
# Raises an error if the provided class is an `abstract_class`.
|
133
135
|
# @api private
|
134
136
|
def assert_concrete_activerecord_class(class_name)
|
135
137
|
if class_name.constantize.abstract_class?
|
136
|
-
raise format(E_HPT_ABSTRACT_CLASS, @model_class, class_name)
|
138
|
+
raise Error, format(E_HPT_ABSTRACT_CLASS, @model_class, class_name)
|
137
139
|
end
|
138
140
|
end
|
139
141
|
|
140
|
-
|
141
|
-
|
142
|
+
# @api private
|
143
|
+
def assert_valid_recording_order_for_on_destroy(recording_order)
|
144
|
+
unless %w[after before].include?(recording_order.to_s)
|
145
|
+
raise ArgumentError, 'recording order can only be "after" or "before"'
|
146
|
+
end
|
147
|
+
|
148
|
+
if recording_order.to_s == "after" && cannot_record_after_destroy?
|
149
|
+
raise Error, E_CANNOT_RECORD_AFTER_DESTROY
|
150
|
+
end
|
142
151
|
end
|
143
152
|
|
144
|
-
|
145
|
-
|
146
|
-
#
|
147
|
-
# @api private
|
148
|
-
def check_presence_of_item_subtype_column(options)
|
149
|
-
return unless options.key?(:limit)
|
150
|
-
return if version_class.item_subtype_column_present?
|
151
|
-
raise format(E_MODEL_LIMIT_REQUIRES_ITEM_SUBTYPE, @model_class.name)
|
153
|
+
def cannot_record_after_destroy?
|
154
|
+
::ActiveRecord::Base.belongs_to_required_by_default
|
152
155
|
end
|
153
156
|
|
154
157
|
def check_version_class_name(options)
|
@@ -206,6 +209,14 @@ module PaperTrail
|
|
206
209
|
options
|
207
210
|
end
|
208
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
|
+
|
209
220
|
def get_versions_scope(options)
|
210
221
|
options[:versions][:scope] || -> { order(model.timestamp_sort_order) }
|
211
222
|
end
|
@@ -240,12 +251,8 @@ module PaperTrail
|
|
240
251
|
@model_class.paper_trail_options = options.dup
|
241
252
|
|
242
253
|
%i[ignore skip only].each do |k|
|
243
|
-
@model_class.paper_trail_options[k] =
|
244
|
-
flatten.
|
245
|
-
compact.
|
246
|
-
map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
|
254
|
+
@model_class.paper_trail_options[k] = event_attribute_option(k)
|
247
255
|
end
|
248
|
-
|
249
256
|
@model_class.paper_trail_options[:meta] ||= {}
|
250
257
|
end
|
251
258
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PaperTrail
|
4
|
+
module Queries
|
5
|
+
module Versions
|
6
|
+
# For public API documentation, see `where_attribute_changes` in
|
7
|
+
# `paper_trail/version_concern.rb`.
|
8
|
+
# @api private
|
9
|
+
class WhereAttributeChanges
|
10
|
+
# - version_model_class - The class that VersionConcern was mixed into.
|
11
|
+
# - attribute - An attribute that changed. See the public API
|
12
|
+
# documentation for details.
|
13
|
+
# @api private
|
14
|
+
def initialize(version_model_class, attribute)
|
15
|
+
@version_model_class = version_model_class
|
16
|
+
@attribute = attribute
|
17
|
+
end
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
def execute
|
21
|
+
if PaperTrail.config.object_changes_adapter.respond_to?(:where_attribute_changes)
|
22
|
+
return PaperTrail.config.object_changes_adapter.where_attribute_changes(
|
23
|
+
@version_model_class, @attribute
|
24
|
+
)
|
25
|
+
end
|
26
|
+
column_type = @version_model_class.columns_hash["object_changes"].type
|
27
|
+
case column_type
|
28
|
+
when :jsonb, :json
|
29
|
+
json
|
30
|
+
else
|
31
|
+
raise UnsupportedColumnType.new(
|
32
|
+
method: "where_attribute_changes",
|
33
|
+
expected: "json or jsonb",
|
34
|
+
actual: column_type
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
def json
|
43
|
+
sql = "object_changes -> ? IS NOT NULL"
|
44
|
+
|
45
|
+
@version_model_class.where(sql, @attribute)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -19,7 +19,7 @@ module PaperTrail
|
|
19
19
|
# @api private
|
20
20
|
def execute
|
21
21
|
column = @version_model_class.columns_hash["object"]
|
22
|
-
raise "where_object
|
22
|
+
raise Error, "where_object requires an object column" unless column
|
23
23
|
|
24
24
|
case column.type
|
25
25
|
when :jsonb
|
@@ -28,13 +28,18 @@ module PaperTrail
|
|
28
28
|
@version_model_class, @attributes
|
29
29
|
)
|
30
30
|
end
|
31
|
-
|
31
|
+
column_type = @version_model_class.columns_hash["object_changes"].type
|
32
|
+
case column_type
|
32
33
|
when :jsonb
|
33
34
|
jsonb
|
34
35
|
when :json
|
35
36
|
json
|
36
37
|
else
|
37
|
-
|
38
|
+
raise UnsupportedColumnType.new(
|
39
|
+
method: "where_object_changes",
|
40
|
+
expected: "json or jsonb",
|
41
|
+
actual: column_type
|
42
|
+
)
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
@@ -59,16 +64,6 @@ module PaperTrail
|
|
59
64
|
@attributes.each { |field, value| @attributes[field] = [value] }
|
60
65
|
@version_model_class.where("object_changes @> ?", @attributes.to_json)
|
61
66
|
end
|
62
|
-
|
63
|
-
# @api private
|
64
|
-
def text
|
65
|
-
arel_field = @version_model_class.arel_table[:object_changes]
|
66
|
-
where_conditions = @attributes.map { |field, value|
|
67
|
-
::PaperTrail.serializer.where_object_changes_condition(arel_field, field, value)
|
68
|
-
}
|
69
|
-
where_conditions = where_conditions.reduce { |a, e| a.and(e) }
|
70
|
-
@version_model_class.where(where_conditions)
|
71
|
-
end
|
72
67
|
end
|
73
68
|
end
|
74
69
|
end
|
@@ -23,12 +23,16 @@ module PaperTrail
|
|
23
23
|
@version_model_class, @attributes
|
24
24
|
)
|
25
25
|
end
|
26
|
-
|
27
|
-
case
|
26
|
+
column_type = @version_model_class.columns_hash["object_changes"].type
|
27
|
+
case column_type
|
28
28
|
when :jsonb, :json
|
29
29
|
json
|
30
30
|
else
|
31
|
-
|
31
|
+
raise UnsupportedColumnType.new(
|
32
|
+
method: "where_object_changes_from",
|
33
|
+
expected: "json or jsonb",
|
34
|
+
actual: column_type
|
35
|
+
)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -47,18 +51,6 @@ module PaperTrail
|
|
47
51
|
sql = predicates.join(" and ")
|
48
52
|
@version_model_class.where(sql, *values)
|
49
53
|
end
|
50
|
-
|
51
|
-
# @api private
|
52
|
-
def text
|
53
|
-
arel_field = @version_model_class.arel_table[:object_changes]
|
54
|
-
|
55
|
-
where_conditions = @attributes.map do |field, value|
|
56
|
-
::PaperTrail.serializer.where_object_changes_from_condition(arel_field, field, value)
|
57
|
-
end
|
58
|
-
|
59
|
-
where_conditions = where_conditions.reduce { |a, e| a.and(e) }
|
60
|
-
@version_model_class.where(where_conditions)
|
61
|
-
end
|
62
54
|
end
|
63
55
|
end
|
64
56
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PaperTrail
|
4
|
+
module Queries
|
5
|
+
module Versions
|
6
|
+
# For public API documentation, see `where_object_changes_to` in
|
7
|
+
# `paper_trail/version_concern.rb`.
|
8
|
+
# @api private
|
9
|
+
class WhereObjectChangesTo
|
10
|
+
# - version_model_class - The class that VersionConcern was mixed into.
|
11
|
+
# - attributes - A `Hash` of attributes and values. See the public API
|
12
|
+
# documentation for details.
|
13
|
+
# @api private
|
14
|
+
def initialize(version_model_class, attributes)
|
15
|
+
@version_model_class = version_model_class
|
16
|
+
@attributes = attributes
|
17
|
+
end
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
def execute
|
21
|
+
if PaperTrail.config.object_changes_adapter.respond_to?(:where_object_changes_to)
|
22
|
+
return PaperTrail.config.object_changes_adapter.where_object_changes_to(
|
23
|
+
@version_model_class, @attributes
|
24
|
+
)
|
25
|
+
end
|
26
|
+
column_type = @version_model_class.columns_hash["object_changes"].type
|
27
|
+
case column_type
|
28
|
+
when :jsonb, :json
|
29
|
+
json
|
30
|
+
else
|
31
|
+
raise UnsupportedColumnType.new(
|
32
|
+
method: "where_object_changes_to",
|
33
|
+
expected: "json or jsonb",
|
34
|
+
actual: column_type
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
def json
|
43
|
+
predicates = []
|
44
|
+
values = []
|
45
|
+
@attributes.each do |field, value|
|
46
|
+
predicates.push(
|
47
|
+
"(object_changes->>? ILIKE ?)"
|
48
|
+
)
|
49
|
+
values.concat([field, "[%#{value.to_json}]"])
|
50
|
+
end
|
51
|
+
sql = predicates.join(" and ")
|
52
|
+
@version_model_class.where(sql, *values)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -194,15 +194,17 @@ module PaperTrail
|
|
194
194
|
# Save, and create a version record regardless of options such as `:on`,
|
195
195
|
# `:if`, or `:unless`.
|
196
196
|
#
|
197
|
-
#
|
197
|
+
# `in_after_callback`: Indicates if this method is being called within an
|
198
|
+
# `after` callback. Defaults to `false`.
|
199
|
+
# `options`: Optional arguments passed to `save`.
|
198
200
|
#
|
199
201
|
# This is an "update" event. That is, we record the same data we would in
|
200
202
|
# the case of a normal AR `update`.
|
201
|
-
def save_with_version(**options)
|
203
|
+
def save_with_version(in_after_callback: false, **options)
|
202
204
|
::PaperTrail.request(enabled: false) do
|
203
205
|
@record.save(**options)
|
204
206
|
end
|
205
|
-
record_update(force: true, in_after_callback:
|
207
|
+
record_update(force: true, in_after_callback: in_after_callback, is_touch: false)
|
206
208
|
end
|
207
209
|
|
208
210
|
# Like the `update_column` method from `ActiveRecord::Persistence`, but also
|
@@ -283,7 +285,7 @@ module PaperTrail
|
|
283
285
|
def log_version_errors(version, action)
|
284
286
|
version.logger&.warn(
|
285
287
|
"Unable to create version for #{action} of #{@record.class.name}" \
|
286
|
-
|
288
|
+
"##{@record.id}: " + version.errors.full_messages.join(", ")
|
287
289
|
)
|
288
290
|
end
|
289
291
|
|
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`.
|
@@ -31,24 +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
|
-
|
45
|
-
# Raises an exception as this operation is not allowed from text columns.
|
46
|
-
def where_object_changes_from_condition(*)
|
47
|
-
raise <<-STR.squish.freeze
|
48
|
-
where_object_changes_from does not support reading JSON from a text
|
49
|
-
column. The json and jsonb datatypes are supported.
|
50
|
-
STR
|
51
|
-
end
|
52
34
|
end
|
53
35
|
end
|
54
36
|
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
|
@@ -26,26 +26,6 @@ module PaperTrail
|
|
26
26
|
def where_object_condition(arel_field, field, value)
|
27
27
|
arel_field.matches("%\n#{field}: #{value}\n%")
|
28
28
|
end
|
29
|
-
|
30
|
-
# Returns a SQL LIKE condition to be used to match the given field and
|
31
|
-
# value in the serialized `object_changes`.
|
32
|
-
def where_object_changes_condition(*)
|
33
|
-
raise <<-STR.squish.freeze
|
34
|
-
where_object_changes no longer supports reading YAML from a text
|
35
|
-
column. The old implementation was inaccurate, returning more records
|
36
|
-
than you wanted. This feature was deprecated in 8.1.0 and removed in
|
37
|
-
9.0.0. The json and jsonb datatypes are still supported. See
|
38
|
-
discussion at https://github.com/paper-trail-gem/paper_trail/pull/997
|
39
|
-
STR
|
40
|
-
end
|
41
|
-
|
42
|
-
# Raises an exception as this operation is not allowed with YAML.
|
43
|
-
def where_object_changes_from_condition(*)
|
44
|
-
raise <<-STR.squish.freeze
|
45
|
-
where_object_changes_from does not support reading YAML from a text
|
46
|
-
column. The json and jsonb datatypes are supported.
|
47
|
-
STR
|
48
|
-
end
|
49
29
|
end
|
50
30
|
end
|
51
31
|
end
|
@@ -1,9 +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"
|
6
7
|
require "paper_trail/queries/versions/where_object_changes_from"
|
8
|
+
require "paper_trail/queries/versions/where_object_changes_to"
|
7
9
|
|
8
10
|
module PaperTrail
|
9
11
|
# Originally, PaperTrail did not provide this module, and all of this
|
@@ -14,17 +16,13 @@ module PaperTrail
|
|
14
16
|
extend ::ActiveSupport::Concern
|
15
17
|
|
16
18
|
included do
|
17
|
-
belongs_to :item, polymorphic: true, optional: true
|
19
|
+
belongs_to :item, polymorphic: true, optional: true, inverse_of: false
|
18
20
|
validates_presence_of :event
|
19
21
|
after_create :enforce_version_limit!
|
20
22
|
end
|
21
23
|
|
22
24
|
# :nodoc:
|
23
25
|
module ClassMethods
|
24
|
-
def item_subtype_column_present?
|
25
|
-
column_names.include?("item_subtype")
|
26
|
-
end
|
27
|
-
|
28
26
|
def with_item_keys(item_type, item_id)
|
29
27
|
where item_type: item_type, item_id: item_id
|
30
28
|
end
|
@@ -42,7 +40,7 @@ module PaperTrail
|
|
42
40
|
end
|
43
41
|
|
44
42
|
def not_creates
|
45
|
-
where
|
43
|
+
where.not(event: "create")
|
46
44
|
end
|
47
45
|
|
48
46
|
def between(start_time, end_time)
|
@@ -60,6 +58,18 @@ module PaperTrail
|
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
61
|
+
# Given an attribute like `"name"`, query the `versions.object_changes`
|
62
|
+
# column for any changes that modified the provided attribute.
|
63
|
+
#
|
64
|
+
# @api public
|
65
|
+
def where_attribute_changes(attribute)
|
66
|
+
unless attribute.is_a?(String) || attribute.is_a?(Symbol)
|
67
|
+
raise ArgumentError, "expected to receive a String or Symbol"
|
68
|
+
end
|
69
|
+
|
70
|
+
Queries::Versions::WhereAttributeChanges.new(self, attribute).execute
|
71
|
+
end
|
72
|
+
|
63
73
|
# Given a hash of attributes like `name: 'Joan'`, query the
|
64
74
|
# `versions.objects` column.
|
65
75
|
#
|
@@ -131,6 +141,21 @@ module PaperTrail
|
|
131
141
|
Queries::Versions::WhereObjectChangesFrom.new(self, args).execute
|
132
142
|
end
|
133
143
|
|
144
|
+
# Given a hash of attributes like `name: 'Joan'`, query the
|
145
|
+
# `versions.objects_changes` column for changes where the version changed
|
146
|
+
# to the hash of attributes from other values.
|
147
|
+
#
|
148
|
+
# This is useful for finding versions where the attribute started with an
|
149
|
+
# unknown value and changed to a known value. This is in comparison to
|
150
|
+
# `where_object_changes` which will find both the changes before and
|
151
|
+
# after.
|
152
|
+
#
|
153
|
+
# @api public
|
154
|
+
def where_object_changes_to(args = {})
|
155
|
+
raise ArgumentError, "expected to receive a Hash" unless args.is_a?(Hash)
|
156
|
+
Queries::Versions::WhereObjectChangesTo.new(self, args).execute
|
157
|
+
end
|
158
|
+
|
134
159
|
def primary_key_is_int?
|
135
160
|
@primary_key_is_int ||= columns_hash[primary_key].type == :integer
|
136
161
|
rescue StandardError # TODO: Rescue something more specific
|
@@ -237,7 +262,7 @@ module PaperTrail
|
|
237
262
|
#
|
238
263
|
def reify(options = {})
|
239
264
|
unless self.class.column_names.include? "object"
|
240
|
-
raise "reify
|
265
|
+
raise Error, "reify requires an object column"
|
241
266
|
end
|
242
267
|
return nil if object.nil?
|
243
268
|
::PaperTrail::Reifier.reify(self, options)
|
@@ -350,16 +375,23 @@ module PaperTrail
|
|
350
375
|
# The version limit can be global or per-model.
|
351
376
|
#
|
352
377
|
# @api private
|
353
|
-
#
|
354
|
-
# TODO: Duplication: similar `constantize` in Reifier#version_reification_class
|
355
378
|
def version_limit
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
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]
|
384
|
+
else
|
385
|
+
PaperTrail.config.version_limit
|
361
386
|
end
|
362
|
-
|
387
|
+
end
|
388
|
+
|
389
|
+
def limit_option?(klass)
|
390
|
+
klass.respond_to?(:paper_trail_options) && klass.paper_trail_options.key?(:limit)
|
391
|
+
end
|
392
|
+
|
393
|
+
def base_class_limit_option?(klass)
|
394
|
+
klass.respond_to?(:base_class) && limit_option?(klass.base_class)
|
363
395
|
end
|
364
396
|
end
|
365
397
|
end
|
data/lib/paper_trail.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
# can revisit this decision.
|
9
9
|
require "active_support/all"
|
10
10
|
|
11
|
+
require "paper_trail/errors"
|
11
12
|
require "paper_trail/cleaner"
|
12
13
|
require "paper_trail/compatibility"
|
13
14
|
require "paper_trail/config"
|
@@ -25,6 +26,8 @@ module PaperTrail
|
|
25
26
|
named created_at.
|
26
27
|
EOS
|
27
28
|
|
29
|
+
RAILS_GTE_7_0 = ::ActiveRecord.gem_version >= ::Gem::Version.new("7.0.0")
|
30
|
+
|
28
31
|
extend PaperTrail::Cleaner
|
29
32
|
|
30
33
|
class << self
|
@@ -68,7 +71,7 @@ module PaperTrail
|
|
68
71
|
#
|
69
72
|
# @api public
|
70
73
|
def request(options = nil, &block)
|
71
|
-
if options.nil? && !
|
74
|
+
if options.nil? && !block
|
72
75
|
Request
|
73
76
|
else
|
74
77
|
Request.with(options, &block)
|
@@ -78,7 +81,7 @@ module PaperTrail
|
|
78
81
|
# Set the field which records when a version was created.
|
79
82
|
# @api public
|
80
83
|
def timestamp_field=(_field_name)
|
81
|
-
raise
|
84
|
+
raise Error, E_TIMESTAMP_FIELD_CONFIG
|
82
85
|
end
|
83
86
|
|
84
87
|
# Set the PaperTrail serializer. This setting affects all threads.
|
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.3.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-03-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -46,42 +46,42 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
49
|
+
version: 2.4.1
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: 2.4.1
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: byebug
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
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
|
@@ -102,14 +102,14 @@ dependencies:
|
|
102
102
|
requirements:
|
103
103
|
- - "~>"
|
104
104
|
- !ruby/object:Gem::Version
|
105
|
-
version: 0.
|
105
|
+
version: 1.0.0
|
106
106
|
type: :development
|
107
107
|
prerelease: false
|
108
108
|
version_requirements: !ruby/object:Gem::Requirement
|
109
109
|
requirements:
|
110
110
|
- - "~>"
|
111
111
|
- !ruby/object:Gem::Version
|
112
|
-
version: 0.
|
112
|
+
version: 1.0.0
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: rails
|
115
115
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,118 +144,140 @@ dependencies:
|
|
144
144
|
requirements:
|
145
145
|
- - "~>"
|
146
146
|
- !ruby/object:Gem::Version
|
147
|
-
version:
|
147
|
+
version: 5.0.2
|
148
148
|
type: :development
|
149
149
|
prerelease: false
|
150
150
|
version_requirements: !ruby/object:Gem::Requirement
|
151
151
|
requirements:
|
152
152
|
- - "~>"
|
153
153
|
- !ruby/object:Gem::Version
|
154
|
-
version:
|
154
|
+
version: 5.0.2
|
155
155
|
- !ruby/object:Gem::Dependency
|
156
156
|
name: rubocop
|
157
157
|
requirement: !ruby/object:Gem::Requirement
|
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
|
-
name: rubocop-
|
170
|
+
name: rubocop-packaging
|
171
171
|
requirement: !ruby/object:Gem::Requirement
|
172
172
|
requirements:
|
173
173
|
- - "~>"
|
174
174
|
- !ruby/object:Gem::Version
|
175
|
-
version:
|
175
|
+
version: 0.5.1
|
176
176
|
type: :development
|
177
177
|
prerelease: false
|
178
178
|
version_requirements: !ruby/object:Gem::Requirement
|
179
179
|
requirements:
|
180
180
|
- - "~>"
|
181
181
|
- !ruby/object:Gem::Version
|
182
|
-
version:
|
182
|
+
version: 0.5.1
|
183
183
|
- !ruby/object:Gem::Dependency
|
184
|
-
name: rubocop-
|
184
|
+
name: rubocop-performance
|
185
185
|
requirement: !ruby/object:Gem::Requirement
|
186
186
|
requirements:
|
187
187
|
- - "~>"
|
188
188
|
- !ruby/object:Gem::Version
|
189
|
-
version:
|
189
|
+
version: 1.11.5
|
190
190
|
type: :development
|
191
191
|
prerelease: false
|
192
192
|
version_requirements: !ruby/object:Gem::Requirement
|
193
193
|
requirements:
|
194
194
|
- - "~>"
|
195
195
|
- !ruby/object:Gem::Version
|
196
|
-
version:
|
196
|
+
version: 1.11.5
|
197
197
|
- !ruby/object:Gem::Dependency
|
198
|
-
name: rubocop-
|
198
|
+
name: rubocop-rails
|
199
|
+
requirement: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - "~>"
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: 2.12.4
|
204
|
+
type: :development
|
205
|
+
prerelease: false
|
206
|
+
version_requirements: !ruby/object:Gem::Requirement
|
207
|
+
requirements:
|
208
|
+
- - "~>"
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: 2.12.4
|
211
|
+
- !ruby/object:Gem::Dependency
|
212
|
+
name: rubocop-rake
|
199
213
|
requirement: !ruby/object:Gem::Requirement
|
200
214
|
requirements:
|
201
215
|
- - "~>"
|
202
216
|
- !ruby/object:Gem::Version
|
203
|
-
version:
|
217
|
+
version: 0.6.0
|
204
218
|
type: :development
|
205
219
|
prerelease: false
|
206
220
|
version_requirements: !ruby/object:Gem::Requirement
|
207
221
|
requirements:
|
208
222
|
- - "~>"
|
209
223
|
- !ruby/object:Gem::Version
|
210
|
-
version:
|
224
|
+
version: 0.6.0
|
211
225
|
- !ruby/object:Gem::Dependency
|
212
226
|
name: rubocop-rspec
|
213
227
|
requirement: !ruby/object:Gem::Requirement
|
214
228
|
requirements:
|
215
229
|
- - "~>"
|
216
230
|
- !ruby/object:Gem::Version
|
217
|
-
version: 2.
|
231
|
+
version: 2.5.0
|
218
232
|
type: :development
|
219
233
|
prerelease: false
|
220
234
|
version_requirements: !ruby/object:Gem::Requirement
|
221
235
|
requirements:
|
222
236
|
- - "~>"
|
223
237
|
- !ruby/object:Gem::Version
|
224
|
-
version: 2.
|
238
|
+
version: 2.5.0
|
239
|
+
- !ruby/object:Gem::Dependency
|
240
|
+
name: simplecov
|
241
|
+
requirement: !ruby/object:Gem::Requirement
|
242
|
+
requirements:
|
243
|
+
- - "~>"
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: 0.21.2
|
246
|
+
type: :development
|
247
|
+
prerelease: false
|
248
|
+
version_requirements: !ruby/object:Gem::Requirement
|
249
|
+
requirements:
|
250
|
+
- - "~>"
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: 0.21.2
|
225
253
|
- !ruby/object:Gem::Dependency
|
226
254
|
name: mysql2
|
227
255
|
requirement: !ruby/object:Gem::Requirement
|
228
256
|
requirements:
|
229
257
|
- - "~>"
|
230
258
|
- !ruby/object:Gem::Version
|
231
|
-
version:
|
259
|
+
version: 0.5.3
|
232
260
|
type: :development
|
233
261
|
prerelease: false
|
234
262
|
version_requirements: !ruby/object:Gem::Requirement
|
235
263
|
requirements:
|
236
264
|
- - "~>"
|
237
265
|
- !ruby/object:Gem::Version
|
238
|
-
version:
|
266
|
+
version: 0.5.3
|
239
267
|
- !ruby/object:Gem::Dependency
|
240
268
|
name: pg
|
241
269
|
requirement: !ruby/object:Gem::Requirement
|
242
270
|
requirements:
|
243
|
-
- - "
|
244
|
-
- !ruby/object:Gem::Version
|
245
|
-
version: '0.18'
|
246
|
-
- - "<"
|
271
|
+
- - "~>"
|
247
272
|
- !ruby/object:Gem::Version
|
248
|
-
version: '2
|
273
|
+
version: '1.2'
|
249
274
|
type: :development
|
250
275
|
prerelease: false
|
251
276
|
version_requirements: !ruby/object:Gem::Requirement
|
252
277
|
requirements:
|
253
|
-
- - "
|
254
|
-
- !ruby/object:Gem::Version
|
255
|
-
version: '0.18'
|
256
|
-
- - "<"
|
278
|
+
- - "~>"
|
257
279
|
- !ruby/object:Gem::Version
|
258
|
-
version: '2
|
280
|
+
version: '1.2'
|
259
281
|
- !ruby/object:Gem::Dependency
|
260
282
|
name: sqlite3
|
261
283
|
requirement: !ruby/object:Gem::Requirement
|
@@ -297,6 +319,7 @@ files:
|
|
297
319
|
- lib/paper_trail/cleaner.rb
|
298
320
|
- lib/paper_trail/compatibility.rb
|
299
321
|
- lib/paper_trail/config.rb
|
322
|
+
- lib/paper_trail/errors.rb
|
300
323
|
- lib/paper_trail/events/base.rb
|
301
324
|
- lib/paper_trail/events/create.rb
|
302
325
|
- lib/paper_trail/events/destroy.rb
|
@@ -311,9 +334,11 @@ files:
|
|
311
334
|
- lib/paper_trail/frameworks/rspec/helpers.rb
|
312
335
|
- lib/paper_trail/has_paper_trail.rb
|
313
336
|
- lib/paper_trail/model_config.rb
|
337
|
+
- lib/paper_trail/queries/versions/where_attribute_changes.rb
|
314
338
|
- lib/paper_trail/queries/versions/where_object.rb
|
315
339
|
- lib/paper_trail/queries/versions/where_object_changes.rb
|
316
340
|
- lib/paper_trail/queries/versions/where_object_changes_from.rb
|
341
|
+
- lib/paper_trail/queries/versions/where_object_changes_to.rb
|
317
342
|
- lib/paper_trail/record_history.rb
|
318
343
|
- lib/paper_trail/record_trail.rb
|
319
344
|
- lib/paper_trail/reifier.rb
|
@@ -335,15 +360,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
335
360
|
requirements:
|
336
361
|
- - ">="
|
337
362
|
- !ruby/object:Gem::Version
|
338
|
-
version: 2.
|
363
|
+
version: 2.6.0
|
339
364
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
340
365
|
requirements:
|
341
366
|
- - ">="
|
342
367
|
- !ruby/object:Gem::Version
|
343
368
|
version: 1.3.6
|
344
369
|
requirements: []
|
345
|
-
|
346
|
-
rubygems_version: 2.7.6.2
|
370
|
+
rubygems_version: 3.2.22
|
347
371
|
signing_key:
|
348
372
|
specification_version: 4
|
349
373
|
summary: Track changes to your models.
|