paper_trail 11.1.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 +19 -5
- 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/attribute_serializer_factory.rb +24 -10
- data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +10 -10
- data/lib/paper_trail/compatibility.rb +2 -2
- data/lib/paper_trail/errors.rb +33 -0
- data/lib/paper_trail/events/base.rb +60 -63
- data/lib/paper_trail/events/destroy.rb +1 -1
- data/lib/paper_trail/events/update.rb +23 -4
- data/lib/paper_trail/frameworks/active_record.rb +9 -2
- data/lib/paper_trail/frameworks/rails/controller.rb +0 -6
- data/lib/paper_trail/frameworks/rails/railtie.rb +30 -0
- data/lib/paper_trail/frameworks/rails.rb +1 -2
- data/lib/paper_trail/model_config.rb +51 -43
- 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 +8 -13
- 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 +7 -7
- data/lib/paper_trail/reifier.rb +27 -10
- data/lib/paper_trail/request.rb +0 -3
- data/lib/paper_trail/serializers/json.rb +0 -10
- data/lib/paper_trail/serializers/yaml.rb +1 -13
- data/lib/paper_trail/type_serializers/postgres_array_serializer.rb +1 -14
- data/lib/paper_trail/version_concern.rb +64 -21
- data/lib/paper_trail/version_number.rb +2 -2
- data/lib/paper_trail.rb +17 -40
- metadata +87 -35
- data/Gemfile +0 -4
- data/lib/paper_trail/frameworks/rails/engine.rb +0 -45
- data/paper_trail.gemspec +0 -69
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,12 +44,19 @@ 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
|
-
|
44
|
-
|
45
|
-
|
55
|
+
if mysql?
|
56
|
+
", null: false, limit: 191"
|
57
|
+
else
|
58
|
+
", null: false"
|
59
|
+
end
|
46
60
|
end
|
47
61
|
|
48
62
|
def mysql?
|
@@ -66,7 +80,7 @@ module PaperTrail
|
|
66
80
|
#
|
67
81
|
def versions_table_options
|
68
82
|
if mysql?
|
69
|
-
',
|
83
|
+
', options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"'
|
70
84
|
else
|
71
85
|
""
|
72
86
|
end
|
@@ -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)
|
@@ -8,18 +8,32 @@ module PaperTrail
|
|
8
8
|
# not suited for writing JSON to a text column. This factory
|
9
9
|
# replaces certain default Active Record serializers
|
10
10
|
# with custom PaperTrail ones.
|
11
|
+
#
|
12
|
+
# @api private
|
11
13
|
module AttributeSerializerFactory
|
12
|
-
|
14
|
+
class << self
|
15
|
+
# @api private
|
16
|
+
def for(klass, attr)
|
17
|
+
active_record_serializer = klass.type_for_attribute(attr)
|
18
|
+
if ar_pg_array?(active_record_serializer)
|
19
|
+
TypeSerializers::PostgresArraySerializer.new(
|
20
|
+
active_record_serializer.subtype,
|
21
|
+
active_record_serializer.delimiter
|
22
|
+
)
|
23
|
+
else
|
24
|
+
active_record_serializer
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
13
29
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
else
|
22
|
-
active_record_serializer
|
30
|
+
# @api private
|
31
|
+
def ar_pg_array?(obj)
|
32
|
+
if defined?(::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array)
|
33
|
+
obj.instance_of?(::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array)
|
34
|
+
else
|
35
|
+
false
|
36
|
+
end
|
23
37
|
end
|
24
38
|
end
|
25
39
|
end
|
@@ -8,9 +8,6 @@ module PaperTrail
|
|
8
8
|
# The `CastAttributeSerializer` (de)serializes model attribute values. For
|
9
9
|
# example, the string "1.99" serializes into the integer `1` when assigned
|
10
10
|
# to an attribute of type `ActiveRecord::Type::Integer`.
|
11
|
-
#
|
12
|
-
# This implementation depends on the `type_for_attribute` method, which was
|
13
|
-
# introduced in rails 4.2. As of PT 8, we no longer support rails < 4.2.
|
14
11
|
class CastAttributeSerializer
|
15
12
|
def initialize(klass)
|
16
13
|
@klass = klass
|
@@ -30,22 +27,25 @@ module PaperTrail
|
|
30
27
|
def defined_enums
|
31
28
|
@defined_enums ||= (@klass.respond_to?(:defined_enums) ? @klass.defined_enums : {})
|
32
29
|
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Uses AR 5's `serialize` and `deserialize`.
|
36
|
-
class CastAttributeSerializer
|
37
|
-
def serialize(attr, val)
|
38
|
-
AttributeSerializerFactory.for(@klass, attr).serialize(val)
|
39
|
-
end
|
40
30
|
|
41
31
|
def deserialize(attr, val)
|
42
32
|
if defined_enums[attr] && val.is_a?(::String)
|
43
33
|
# Because PT 4 used to save the string version of enums to `object_changes`
|
44
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)
|
45
41
|
else
|
46
42
|
AttributeSerializerFactory.for(@klass, attr).deserialize(val)
|
47
43
|
end
|
48
44
|
end
|
45
|
+
|
46
|
+
def serialize(attr, val)
|
47
|
+
AttributeSerializerFactory.for(@klass, attr).serialize(val)
|
48
|
+
end
|
49
49
|
end
|
50
50
|
end
|
51
51
|
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
|
@@ -22,8 +22,6 @@ module PaperTrail
|
|
22
22
|
#
|
23
23
|
# @api private
|
24
24
|
class Base
|
25
|
-
RAILS_GTE_5_1 = ::ActiveRecord.gem_version >= ::Gem::Version.new("5.1.0.beta1")
|
26
|
-
|
27
25
|
# @api private
|
28
26
|
def initialize(record, in_after_callback)
|
29
27
|
@record = record
|
@@ -51,7 +49,7 @@ module PaperTrail
|
|
51
49
|
#
|
52
50
|
# @api private
|
53
51
|
def attribute_changed_in_latest_version?(attr_name)
|
54
|
-
if @in_after_callback
|
52
|
+
if @in_after_callback
|
55
53
|
@record.saved_change_to_attribute?(attr_name.to_s)
|
56
54
|
else
|
57
55
|
@record.attribute_changed?(attr_name.to_s)
|
@@ -60,30 +58,14 @@ module PaperTrail
|
|
60
58
|
|
61
59
|
# @api private
|
62
60
|
def nonskipped_attributes_before_change(is_touch)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
if @record.class.column_names.include?(k)
|
68
|
-
record_attributes[k] = attribute_in_previous_version(k, is_touch)
|
69
|
-
end
|
61
|
+
record_attributes = @record.attributes.except(*@record.paper_trail_options[:skip])
|
62
|
+
record_attributes.each_key do |k|
|
63
|
+
if @record.class.column_names.include?(k)
|
64
|
+
record_attributes[k] = attribute_in_previous_version(k, is_touch)
|
70
65
|
end
|
71
66
|
end
|
72
67
|
end
|
73
68
|
|
74
|
-
# Rails 5.1 changed the API of `ActiveRecord::Dirty`.
|
75
|
-
# @api private
|
76
|
-
def cache_changed_attributes(&block)
|
77
|
-
if RAILS_GTE_5_1
|
78
|
-
# Everything works fine as it is
|
79
|
-
yield
|
80
|
-
else
|
81
|
-
# Any particular call to `changed_attributes` produces the huge memory allocation.
|
82
|
-
# Lets use the generic AR workaround for that.
|
83
|
-
@record.send(:cache_changed_attributes, &block)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
69
|
# Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
|
88
70
|
# https://github.com/paper-trail-gem/paper_trail/pull/899
|
89
71
|
#
|
@@ -91,18 +73,14 @@ module PaperTrail
|
|
91
73
|
#
|
92
74
|
# @api private
|
93
75
|
def attribute_in_previous_version(attr_name, is_touch)
|
94
|
-
if
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
@record.attribute_before_last_save(attr_name.to_s)
|
99
|
-
else
|
100
|
-
# We are either performing a `record_destroy` or a
|
101
|
-
# `record_update(is_touch: true)`.
|
102
|
-
@record.attribute_in_database(attr_name.to_s)
|
103
|
-
end
|
76
|
+
if @in_after_callback && !is_touch
|
77
|
+
# For most events, we want the original value of the attribute, before
|
78
|
+
# the last save.
|
79
|
+
@record.attribute_before_last_save(attr_name.to_s)
|
104
80
|
else
|
105
|
-
|
81
|
+
# We are either performing a `record_destroy` or a
|
82
|
+
# `record_update(is_touch: true)`.
|
83
|
+
@record.attribute_in_database(attr_name.to_s)
|
106
84
|
end
|
107
85
|
end
|
108
86
|
|
@@ -131,19 +109,25 @@ module PaperTrail
|
|
131
109
|
@changed_in_latest_version ||= changes_in_latest_version.keys
|
132
110
|
end
|
133
111
|
|
134
|
-
#
|
135
|
-
# https://github.com/paper-trail-gem/paper_trail/pull/899
|
112
|
+
# Memoized to reduce memory usage
|
136
113
|
#
|
137
114
|
# @api private
|
138
115
|
def changes_in_latest_version
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
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
|
+
}
|
146
129
|
end
|
130
|
+
only
|
147
131
|
end
|
148
132
|
|
149
133
|
# An attributed is "ignored" if it is listed in the `:ignore` option
|
@@ -156,6 +140,18 @@ module PaperTrail
|
|
156
140
|
ignored.any? && (changed_in_latest_version & ignored).any?
|
157
141
|
end
|
158
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
|
+
|
159
155
|
# PT 10 has a new optional column, `item_subtype`
|
160
156
|
#
|
161
157
|
# @api private
|
@@ -200,20 +196,28 @@ module PaperTrail
|
|
200
196
|
if value.respond_to?(:call)
|
201
197
|
value.call(@record)
|
202
198
|
elsif value.is_a?(Symbol) && @record.respond_to?(value, true)
|
203
|
-
|
204
|
-
# be sure to grab the current version.
|
205
|
-
if event != "create" &&
|
206
|
-
@record.has_attribute?(value) &&
|
207
|
-
attribute_changed_in_latest_version?(value)
|
208
|
-
attribute_in_previous_version(value, false)
|
209
|
-
else
|
210
|
-
@record.send(value)
|
211
|
-
end
|
199
|
+
metadatum_from_model_method(event, value)
|
212
200
|
else
|
213
201
|
value
|
214
202
|
end
|
215
203
|
end
|
216
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
|
+
|
217
221
|
# @api private
|
218
222
|
def notable_changes
|
219
223
|
changes_in_latest_version.delete_if { |k, _v|
|
@@ -225,16 +229,9 @@ module PaperTrail
|
|
225
229
|
def notably_changed
|
226
230
|
# Memoized to reduce memory usage
|
227
231
|
@notably_changed ||= begin
|
228
|
-
only =
|
229
|
-
|
230
|
-
|
231
|
-
only.delete_if do |obj|
|
232
|
-
obj.is_a?(Hash) &&
|
233
|
-
obj.each { |attr, condition|
|
234
|
-
only << attr if condition.respond_to?(:call) && condition.call(@record)
|
235
|
-
}
|
236
|
-
end
|
237
|
-
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)
|
238
235
|
end
|
239
236
|
end
|
240
237
|
|
@@ -263,7 +260,7 @@ module PaperTrail
|
|
263
260
|
# @api private
|
264
261
|
# @param changes HashWithIndifferentAccess
|
265
262
|
def recordable_object_changes(changes)
|
266
|
-
if PaperTrail.config.object_changes_adapter
|
263
|
+
if PaperTrail.config.object_changes_adapter.respond_to?(:diff)
|
267
264
|
# We'd like to avoid the `to_hash` here, because it increases memory
|
268
265
|
# usage, but that would be a breaking change because
|
269
266
|
# `object_changes_adapter` expects a plain `Hash`, not a
|
@@ -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`.
|
@@ -1,5 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
3
|
+
# Either ActiveRecord has already been loaded by the Lazy Load Hook in our
|
4
|
+
# Railtie, or else we load it now.
|
5
|
+
require "active_record"
|
6
|
+
::PaperTrail::Compatibility.check_activerecord(::ActiveRecord.gem_version)
|
7
|
+
|
8
|
+
# Now we can load the parts of PT that depend on AR.
|
9
|
+
require "paper_trail/has_paper_trail"
|
10
|
+
require "paper_trail/reifier"
|
5
11
|
require "paper_trail/frameworks/active_record/models/paper_trail/version"
|
12
|
+
ActiveRecord::Base.include PaperTrail::Model
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PaperTrail
|
4
|
+
# Represents code to load within Rails framework. See documentation in
|
5
|
+
# `railties/lib/rails/railtie.rb`.
|
6
|
+
# @api private
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
# PaperTrail only has one initializer.
|
9
|
+
#
|
10
|
+
# We specify `before: "load_config_initializers"` to ensure that the PT
|
11
|
+
# initializer happens before "app initializers" (those defined in
|
12
|
+
# the app's `config/initalizers`).
|
13
|
+
initializer "paper_trail", before: "load_config_initializers" do
|
14
|
+
# `on_load` is a "lazy load hook". It "declares a block that will be
|
15
|
+
# executed when a Rails component is fully loaded". (See
|
16
|
+
# `active_support/lazy_load_hooks.rb`)
|
17
|
+
ActiveSupport.on_load(:action_controller) do
|
18
|
+
require "paper_trail/frameworks/rails/controller"
|
19
|
+
|
20
|
+
# Mix our extensions into `ActionController::Base`, which is `self`
|
21
|
+
# because of the `class_eval` in `lazy_load_hooks.rb`.
|
22
|
+
include PaperTrail::Rails::Controller
|
23
|
+
end
|
24
|
+
|
25
|
+
ActiveSupport.on_load(:active_record) do
|
26
|
+
require "paper_trail/frameworks/active_record"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|