paper_trail 11.0.0 → 12.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -0
  3. data/lib/generators/paper_trail/install/install_generator.rb +6 -4
  4. data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +3 -1
  5. data/lib/generators/paper_trail/update_item_subtype/update_item_subtype_generator.rb +4 -2
  6. data/lib/paper_trail/attribute_serializers/attribute_serializer_factory.rb +24 -10
  7. data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +10 -10
  8. data/lib/paper_trail/compatibility.rb +2 -2
  9. data/lib/paper_trail/errors.rb +33 -0
  10. data/lib/paper_trail/events/base.rb +60 -63
  11. data/lib/paper_trail/events/destroy.rb +1 -1
  12. data/lib/paper_trail/events/update.rb +9 -4
  13. data/lib/paper_trail/frameworks/active_record.rb +9 -2
  14. data/lib/paper_trail/frameworks/rails/controller.rb +0 -6
  15. data/lib/paper_trail/frameworks/rails/railtie.rb +30 -0
  16. data/lib/paper_trail/frameworks/rails.rb +1 -2
  17. data/lib/paper_trail/has_paper_trail.rb +1 -1
  18. data/lib/paper_trail/model_config.rb +51 -43
  19. data/lib/paper_trail/queries/versions/where_attribute_changes.rb +50 -0
  20. data/lib/paper_trail/queries/versions/where_object.rb +1 -1
  21. data/lib/paper_trail/queries/versions/where_object_changes.rb +8 -13
  22. data/lib/paper_trail/queries/versions/where_object_changes_from.rb +57 -0
  23. data/lib/paper_trail/queries/versions/where_object_changes_to.rb +57 -0
  24. data/lib/paper_trail/record_trail.rb +3 -5
  25. data/lib/paper_trail/reifier.rb +27 -10
  26. data/lib/paper_trail/request.rb +0 -3
  27. data/lib/paper_trail/serializers/json.rb +0 -10
  28. data/lib/paper_trail/serializers/yaml.rb +1 -13
  29. data/lib/paper_trail/type_serializers/postgres_array_serializer.rb +1 -14
  30. data/lib/paper_trail/version_concern.rb +64 -21
  31. data/lib/paper_trail/version_number.rb +2 -2
  32. data/lib/paper_trail.rb +17 -40
  33. metadata +102 -33
  34. data/lib/paper_trail/frameworks/rails/engine.rb +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8f7237a39b0645932b394ee0332846be680f6a725ed02c7a126aa892d840ccc
4
- data.tar.gz: b0356d622a6e6f3ba0938c4d9fe0ff211b347a0c65e2d3a6574bc8bf5fb04df6
3
+ metadata.gz: d64732632c8d2b579619cb3e4ec4f754a3bd82310f464aa715d79709fc0ba58d
4
+ data.tar.gz: 245ca1378370715e907ef2c7c9eaad6375a77aef0306729e98c2a046d4cb7c89
5
5
  SHA512:
6
- metadata.gz: 46ad3d73231d4ab6c3d978925e7b838af2697b2b998b9a7948d078266fbdbec33b6dbdcbfb93751f2aa961be6a3499f499a71d56e3fbc6138174cb752feae41a
7
- data.tar.gz: 9ec2fc044229898aa2c5ab70dc41b549b6896c61af42633af0760e6b99aadd375f5f7e39160ad713131ecb439b0f5aff8cb6696f276f4c5225eb40e371f43035
6
+ metadata.gz: 85ff44a62d2ca043e38805e510ac7bea9b5b2faba00e3e75b79262404b422730a2810e0e95adc0a30e867dd8d20fa21eb63d0b329908934272a591a14df0ce03
7
+ data.tar.gz: 8454773dd1a683fed0f79f6464a4d2f9944c399b81e4ce3ec205720a27db17ee4daade6793cddf5fe63e8422c3f6564893721ad02bef6abbd42d8e6e8a881b08
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Andy Stewart, AirBlade Software Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -40,9 +40,11 @@ module PaperTrail
40
40
  # MySQL 5.6 utf8mb4 limit is 191 chars for keys used in indexes.
41
41
  # See https://github.com/paper-trail-gem/paper_trail/issues/651
42
42
  def item_type_options
43
- opt = { null: false }
44
- opt[:limit] = 191 if mysql?
45
- ", #{opt}"
43
+ if mysql?
44
+ ", { null: false, limit: 191 }"
45
+ else
46
+ ", { null: false }"
47
+ end
46
48
  end
47
49
 
48
50
  def mysql?
@@ -66,7 +68,7 @@ module PaperTrail
66
68
  #
67
69
  def versions_table_options
68
70
  if mysql?
69
- ', { options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" }'
71
+ ', options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"'
70
72
  else
71
73
  ""
72
74
  end
@@ -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 "Generates (but does not run) a migration to update item_subtype for STI entries in an "\
11
- "existing versions table."
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
- AR_PG_ARRAY_CLASS = "ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array"
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
- def self.for(klass, attr)
15
- active_record_serializer = klass.type_for_attribute(attr)
16
- if active_record_serializer.class.name == AR_PG_ARRAY_CLASS
17
- TypeSerializers::PostgresArraySerializer.new(
18
- active_record_serializer.subtype,
19
- active_record_serializer.delimiter
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 `.travis.yml`.
11
+ # tested against. See `.github/workflows/test.yml`.
12
12
  #
13
13
  # However, as of
14
14
  # [#1213](https://github.com/paper-trail-gem/paper_trail/pull/1213) our
@@ -18,7 +18,7 @@ module PaperTrail
18
18
  # versions.
19
19
  module Compatibility
20
20
  ACTIVERECORD_GTE = ">= 5.2" # enforced in gemspec
21
- ACTIVERECORD_LT = "< 6.1" # not enforced in gemspec
21
+ ACTIVERECORD_LT = "< 7.1" # not enforced in gemspec
22
22
 
23
23
  E_INCOMPATIBLE_AR = <<-EOS
24
24
  PaperTrail %s is not compatible with ActiveRecord %s. We allow PT
@@ -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 && RAILS_GTE_5_1
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
- cache_changed_attributes do
64
- record_attributes = @record.attributes.except(*@record.paper_trail_options[:skip])
65
-
66
- record_attributes.each_key do |k|
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 RAILS_GTE_5_1
95
- if @in_after_callback && !is_touch
96
- # For most events, we want the original value of the attribute, before
97
- # the last save.
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
- @record.attribute_was(attr_name.to_s)
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
- # Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
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
- # Memoized to reduce memory usage
140
- @changes_in_latest_version ||= begin
141
- if @in_after_callback && RAILS_GTE_5_1
142
- @record.saved_changes
143
- else
144
- @record.changes
145
- end
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
- # If it is an attribute that is changing in an existing object,
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 = @record.paper_trail_options[:only].dup
229
- # Remove Hash arguments and then evaluate whether the attributes (the
230
- # keys of the hash) should also get pushed into the collection.
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&.respond_to?(:diff)
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,7 +35,7 @@ module PaperTrail
35
35
  #
36
36
  # @override
37
37
  def changes_in_latest_version
38
- @record.attributes.map { |attr, value| [attr, [value, nil]] }.to_h
38
+ @record.attributes.transform_values { |value| [value, nil] }
39
39
  end
40
40
  end
41
41
  end
@@ -35,16 +35,21 @@ module PaperTrail
35
35
  if record_object?
36
36
  data[:object] = recordable_object(@is_touch)
37
37
  end
38
- if record_object_changes?
39
- changes = @force_changes.nil? ? notable_changes : @force_changes
40
- data[:object_changes] = prepare_object_changes(changes)
41
- end
38
+ merge_object_changes_into(data)
42
39
  merge_item_subtype_into(data)
43
40
  merge_metadata_into(data)
44
41
  end
45
42
 
46
43
  private
47
44
 
45
+ # @api private
46
+ def merge_object_changes_into(data)
47
+ if record_object_changes?
48
+ changes = @force_changes.nil? ? notable_changes : @force_changes
49
+ data[:object_changes] = prepare_object_changes(changes)
50
+ end
51
+ end
52
+
48
53
  # `touch` cannot record `object_changes` because rails' `touch` does not
49
54
  # perform dirty-tracking. Specifically, methods from `Dirty`, like
50
55
  # `saved_changes`, return the same values before and after `touch`.
@@ -1,5 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This file only needs to be loaded if the gem is being used outside of Rails,
4
- # since otherwise the model(s) will get loaded in via the `Rails::Engine`.
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
@@ -101,9 +101,3 @@ module PaperTrail
101
101
  end
102
102
  end
103
103
  end
104
-
105
- if defined?(::ActionController)
106
- ::ActiveSupport.on_load(:action_controller) do
107
- include ::PaperTrail::Rails::Controller
108
- end
109
- end
@@ -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
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "paper_trail/frameworks/rails/controller"
4
- require "paper_trail/frameworks/rails/engine"
3
+ require "paper_trail/frameworks/rails/railtie"
@@ -12,7 +12,7 @@ module PaperTrail
12
12
  # `.paper_trail` and `#paper_trail`.
13
13
  module Model
14
14
  def self.included(base)
15
- base.send :extend, ClassMethods
15
+ base.extend ClassMethods
16
16
  end
17
17
 
18
18
  # :nodoc: