paper_trail 9.2.0 → 12.1.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -0
  3. data/lib/generators/paper_trail/install/USAGE +3 -0
  4. data/lib/generators/paper_trail/{install_generator.rb → install/install_generator.rb} +15 -38
  5. data/lib/generators/paper_trail/{templates → install/templates}/add_object_changes_to_versions.rb.erb +0 -0
  6. data/lib/generators/paper_trail/{templates → install/templates}/create_versions.rb.erb +2 -2
  7. data/lib/generators/paper_trail/migration_generator.rb +38 -0
  8. data/lib/generators/paper_trail/update_item_subtype/USAGE +4 -0
  9. data/lib/generators/paper_trail/update_item_subtype/templates/update_versions_for_item_subtype.rb.erb +85 -0
  10. data/lib/generators/paper_trail/update_item_subtype/update_item_subtype_generator.rb +19 -0
  11. data/lib/paper_trail/attribute_serializers/attribute_serializer_factory.rb +24 -10
  12. data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +8 -46
  13. data/lib/paper_trail/compatibility.rb +51 -0
  14. data/lib/paper_trail/config.rb +9 -2
  15. data/lib/paper_trail/errors.rb +33 -0
  16. data/lib/paper_trail/events/base.rb +305 -0
  17. data/lib/paper_trail/events/create.rb +32 -0
  18. data/lib/paper_trail/events/destroy.rb +42 -0
  19. data/lib/paper_trail/events/update.rb +60 -0
  20. data/lib/paper_trail/frameworks/active_record.rb +9 -2
  21. data/lib/paper_trail/frameworks/rails/controller.rb +1 -9
  22. data/lib/paper_trail/frameworks/rails/railtie.rb +30 -0
  23. data/lib/paper_trail/frameworks/rails.rb +1 -2
  24. data/lib/paper_trail/has_paper_trail.rb +20 -17
  25. data/lib/paper_trail/model_config.rb +103 -71
  26. data/lib/paper_trail/queries/versions/where_attribute_changes.rb +50 -0
  27. data/lib/paper_trail/queries/versions/where_object.rb +4 -1
  28. data/lib/paper_trail/queries/versions/where_object_changes.rb +8 -13
  29. data/lib/paper_trail/queries/versions/where_object_changes_from.rb +57 -0
  30. data/lib/paper_trail/queries/versions/where_object_changes_to.rb +57 -0
  31. data/lib/paper_trail/record_trail.rb +94 -411
  32. data/lib/paper_trail/reifier.rb +41 -25
  33. data/lib/paper_trail/request.rb +0 -3
  34. data/lib/paper_trail/serializers/json.rb +0 -10
  35. data/lib/paper_trail/serializers/yaml.rb +5 -12
  36. data/lib/paper_trail/type_serializers/postgres_array_serializer.rb +1 -15
  37. data/lib/paper_trail/version_concern.rb +141 -61
  38. data/lib/paper_trail/version_number.rb +2 -2
  39. data/lib/paper_trail.rb +16 -123
  40. metadata +159 -56
  41. data/lib/generators/paper_trail/USAGE +0 -2
  42. data/lib/paper_trail/frameworks/rails/engine.rb +0 -14
@@ -52,26 +52,29 @@ module PaperTrail
52
52
  # not the actual subclass. If `type` is present but empty, the class is
53
53
  # the base class.
54
54
  def init_model(attrs, options, version)
55
- if options[:dup] != true && version.item
56
- model = version.item
57
- if options[:unversioned_attributes] == :nil
58
- init_unversioned_attrs(attrs, model)
59
- end
60
- else
61
- klass = version_reification_class(version, attrs)
62
- # The `dup` option always returns a new object, otherwise we should
63
- # attempt to look for the item outside of default scope(s).
64
- find_cond = { klass.primary_key => version.item_id }
65
- if options[:dup] || (item_found = klass.unscoped.where(find_cond).first).nil?
66
- model = klass.new
67
- elsif options[:unversioned_attributes] == :nil
68
- model = item_found
69
- init_unversioned_attrs(attrs, model)
70
- end
55
+ klass = version_reification_class(version, attrs)
56
+
57
+ # The `dup` option and destroyed version always returns a new object,
58
+ # otherwise we should attempt to load item or to look for the item
59
+ # outside of default scope(s).
60
+ model = if options[:dup] == true || version.event == "destroy"
61
+ klass.new
62
+ else
63
+ version.item || init_model_by_finding_item_id(klass, version) || klass.new
64
+ end
65
+
66
+ if options[:unversioned_attributes] == :nil && !model.new_record?
67
+ init_unversioned_attrs(attrs, model)
71
68
  end
69
+
72
70
  model
73
71
  end
74
72
 
73
+ # @api private
74
+ def init_model_by_finding_item_id(klass, version)
75
+ klass.unscoped.where(klass.primary_key => version.item_id).first
76
+ end
77
+
75
78
  # Look for attributes that exist in `model` and not in this version.
76
79
  # These attributes should be set to nil. Modifies `attrs`.
77
80
  # @api private
@@ -88,9 +91,7 @@ module PaperTrail
88
91
  #
89
92
  # @api private
90
93
  def reify_attribute(k, v, model, version)
91
- enums = model.class.respond_to?(:defined_enums) ? model.class.defined_enums : {}
92
- is_enum_without_type_caster = ::ActiveRecord::VERSION::MAJOR < 5 && enums.key?(k)
93
- if model.has_attribute?(k) && !is_enum_without_type_caster
94
+ if model.has_attribute?(k)
94
95
  model[k.to_sym] = v
95
96
  elsif model.respond_to?("#{k}=")
96
97
  model.send("#{k}=", v)
@@ -111,20 +112,35 @@ module PaperTrail
111
112
  end
112
113
 
113
114
  # Given a `version`, return the class to reify. This method supports
114
- # Single Table Inheritance (STI) with custom inheritance columns.
115
+ # Single Table Inheritance (STI) with custom inheritance columns and
116
+ # custom inheritance column values.
115
117
  #
116
118
  # For example, imagine a `version` whose `item_type` is "Animal". The
117
119
  # `animals` table is an STI table (it has cats and dogs) and it has a
118
120
  # custom inheritance column, `species`. If `attrs["species"]` is "Dog",
119
121
  # this method returns the constant `Dog`. If `attrs["species"]` is blank,
120
- # this method returns the constant `Animal`. You can see this particular
121
- # example in action in `spec/models/animal_spec.rb`.
122
+ # this method returns the constant `Animal`.
123
+ #
124
+ # The values contained in the inheritance columns may be non-camelized
125
+ # strings (e.g. 'dog' instead of 'Dog'). To reify classes in this case
126
+ # we need to call the parents class `sti_class_for` method to retrieve
127
+ # the correct record class.
122
128
  #
129
+ # You can see these particular examples in action in
130
+ # `spec/models/animal_spec.rb` and `spec/models/plant_spec.rb`
123
131
  def version_reification_class(version, attrs)
124
- inheritance_column_name = version.item_type.constantize.inheritance_column
132
+ clazz = version.item_type.constantize
133
+ inheritance_column_name = clazz.inheritance_column
125
134
  inher_col_value = attrs[inheritance_column_name]
126
- class_name = inher_col_value.blank? ? version.item_type : inher_col_value
127
- class_name.constantize
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)
128
144
  end
129
145
  end
130
146
  end
@@ -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,16 +31,6 @@ module PaperTrail
31
31
  arel_field.matches("%\"#{field}\":#{json_value}%")
32
32
  end
33
33
  end
34
-
35
- def where_object_changes_condition(*)
36
- raise <<-STR.squish.freeze
37
- where_object_changes no longer supports reading JSON from a text
38
- column. The old implementation was inaccurate, returning more records
39
- than you wanted. This feature was deprecated in 7.1.0 and removed in
40
- 8.0.0. The json and jsonb datatypes are still supported. See the
41
- discussion at https://github.com/paper-trail-gem/paper_trail/issues/803
42
- STR
43
- end
44
34
  end
45
35
  end
46
36
  end
@@ -12,7 +12,12 @@ module PaperTrail
12
12
  ::YAML.load string
13
13
  end
14
14
 
15
+ # @param object (Hash | HashWithIndifferentAccess) - Coming from
16
+ # `recordable_object` `object` will be a plain `Hash`. However, due to
17
+ # recent [memory optimizations](https://git.io/fjeYv), when coming from
18
+ # `recordable_object_changes`, it will be a `HashWithIndifferentAccess`.
15
19
  def dump(object)
20
+ object = object.to_hash if object.is_a?(HashWithIndifferentAccess)
16
21
  ::YAML.dump object
17
22
  end
18
23
 
@@ -21,18 +26,6 @@ module PaperTrail
21
26
  def where_object_condition(arel_field, field, value)
22
27
  arel_field.matches("%\n#{field}: #{value}\n%")
23
28
  end
24
-
25
- # Returns a SQL LIKE condition to be used to match the given field and
26
- # value in the serialized `object_changes`.
27
- def where_object_changes_condition(*)
28
- raise <<-STR.squish.freeze
29
- where_object_changes no longer supports reading YAML from a text
30
- column. The old implementation was inaccurate, returning more records
31
- than you wanted. This feature was deprecated in 8.1.0 and removed in
32
- 9.0.0. The json and jsonb datatypes are still supported. See
33
- discussion at https://github.com/paper-trail-gem/paper_trail/pull/997
34
- STR
35
- end
36
29
  end
37
30
  end
38
31
  end
@@ -11,15 +11,12 @@ module PaperTrail
11
11
  end
12
12
 
13
13
  def serialize(array)
14
- return serialize_with_ar(array) if active_record_pre_502?
15
14
  array
16
15
  end
17
16
 
18
17
  def deserialize(array)
19
- return deserialize_with_ar(array) if active_record_pre_502?
20
-
21
18
  case array
22
- # Needed for legacy reasons. If serialized array is a string
19
+ # Needed for legacy data. If serialized array is a string
23
20
  # then it was serialized with Rails < 5.0.2.
24
21
  when ::String then deserialize_with_ar(array)
25
22
  else array
@@ -28,17 +25,6 @@ module PaperTrail
28
25
 
29
26
  private
30
27
 
31
- def active_record_pre_502?
32
- ::ActiveRecord::VERSION::MAJOR < 5 ||
33
- (::ActiveRecord::VERSION::MINOR.zero? && ::ActiveRecord::VERSION::TINY < 2)
34
- end
35
-
36
- def serialize_with_ar(array)
37
- ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.
38
- new(@subtype, @delimiter).
39
- serialize(array)
40
- end
41
-
42
28
  def deserialize_with_ar(array)
43
29
  ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.
44
30
  new(@subtype, @delimiter).
@@ -1,8 +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"
7
+ require "paper_trail/queries/versions/where_object_changes_from"
8
+ require "paper_trail/queries/versions/where_object_changes_to"
6
9
 
7
10
  module PaperTrail
8
11
  # Originally, PaperTrail did not provide this module, and all of this
@@ -13,12 +16,7 @@ module PaperTrail
13
16
  extend ::ActiveSupport::Concern
14
17
 
15
18
  included do
16
- if ::ActiveRecord.gem_version >= Gem::Version.new("5.0")
17
- belongs_to :item, polymorphic: true, optional: true
18
- else
19
- belongs_to :item, polymorphic: true
20
- end
21
-
19
+ belongs_to :item, polymorphic: true, optional: true
22
20
  validates_presence_of :event
23
21
  after_create :enforce_version_limit!
24
22
  end
@@ -42,40 +40,7 @@ module PaperTrail
42
40
  end
43
41
 
44
42
  def not_creates
45
- where "event <> ?", "create"
46
- end
47
-
48
- # Returns versions after `obj`.
49
- #
50
- # @param obj - a `Version` or a timestamp
51
- # @param timestamp_arg - boolean - When true, `obj` is a timestamp.
52
- # Default: false.
53
- # @return `ActiveRecord::Relation`
54
- # @api public
55
- def subsequent(obj, timestamp_arg = false)
56
- if timestamp_arg != true && primary_key_is_int?
57
- return where(arel_table[primary_key].gt(obj.id)).order(arel_table[primary_key].asc)
58
- end
59
-
60
- obj = obj.send(:created_at) if obj.is_a?(self)
61
- where(arel_table[:created_at].gt(obj)).order(timestamp_sort_order)
62
- end
63
-
64
- # Returns versions before `obj`.
65
- #
66
- # @param obj - a `Version` or a timestamp
67
- # @param timestamp_arg - boolean - When true, `obj` is a timestamp.
68
- # Default: false.
69
- # @return `ActiveRecord::Relation`
70
- # @api public
71
- def preceding(obj, timestamp_arg = false)
72
- if timestamp_arg != true && primary_key_is_int?
73
- return where(arel_table[primary_key].lt(obj.id)).order(arel_table[primary_key].desc)
74
- end
75
-
76
- obj = obj.send(:created_at) if obj.is_a?(self)
77
- where(arel_table[:created_at].lt(obj)).
78
- order(timestamp_sort_order("desc"))
43
+ where.not(event: "create")
79
44
  end
80
45
 
81
46
  def between(start_time, end_time)
@@ -93,6 +58,18 @@ module PaperTrail
93
58
  end
94
59
  end
95
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
+
96
73
  # Given a hash of attributes like `name: 'Joan'`, query the
97
74
  # `versions.objects` column.
98
75
  #
@@ -149,6 +126,36 @@ module PaperTrail
149
126
  Queries::Versions::WhereObjectChanges.new(self, args).execute
150
127
  end
151
128
 
129
+ # Given a hash of attributes like `name: 'Joan'`, query the
130
+ # `versions.objects_changes` column for changes where the version changed
131
+ # from the hash of attributes to other values.
132
+ #
133
+ # This is useful for finding versions where the attribute started with a
134
+ # known value and changed to something else. This is in comparison to
135
+ # `where_object_changes` which will find both the changes before and
136
+ # after.
137
+ #
138
+ # @api public
139
+ def where_object_changes_from(args = {})
140
+ raise ArgumentError, "expected to receive a Hash" unless args.is_a?(Hash)
141
+ Queries::Versions::WhereObjectChangesFrom.new(self, args).execute
142
+ end
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
+
152
159
  def primary_key_is_int?
153
160
  @primary_key_is_int ||= columns_hash[primary_key].type == :integer
154
161
  rescue StandardError # TODO: Rescue something more specific
@@ -166,6 +173,65 @@ module PaperTrail
166
173
  def object_changes_col_is_json?
167
174
  %i[json jsonb].include?(columns_hash["object_changes"].try(:type))
168
175
  end
176
+
177
+ # Returns versions before `obj`.
178
+ #
179
+ # @param obj - a `Version` or a timestamp
180
+ # @param timestamp_arg - boolean - When true, `obj` is a timestamp.
181
+ # Default: false.
182
+ # @return `ActiveRecord::Relation`
183
+ # @api public
184
+ # rubocop:disable Style/OptionalBooleanParameter
185
+ def preceding(obj, timestamp_arg = false)
186
+ if timestamp_arg != true && primary_key_is_int?
187
+ preceding_by_id(obj)
188
+ else
189
+ preceding_by_timestamp(obj)
190
+ end
191
+ end
192
+ # rubocop:enable Style/OptionalBooleanParameter
193
+
194
+ # Returns versions after `obj`.
195
+ #
196
+ # @param obj - a `Version` or a timestamp
197
+ # @param timestamp_arg - boolean - When true, `obj` is a timestamp.
198
+ # Default: false.
199
+ # @return `ActiveRecord::Relation`
200
+ # @api public
201
+ # rubocop:disable Style/OptionalBooleanParameter
202
+ def subsequent(obj, timestamp_arg = false)
203
+ if timestamp_arg != true && primary_key_is_int?
204
+ subsequent_by_id(obj)
205
+ else
206
+ subsequent_by_timestamp(obj)
207
+ end
208
+ end
209
+ # rubocop:enable Style/OptionalBooleanParameter
210
+
211
+ private
212
+
213
+ # @api private
214
+ def preceding_by_id(obj)
215
+ where(arel_table[primary_key].lt(obj.id)).order(arel_table[primary_key].desc)
216
+ end
217
+
218
+ # @api private
219
+ def preceding_by_timestamp(obj)
220
+ obj = obj.send(:created_at) if obj.is_a?(self)
221
+ where(arel_table[:created_at].lt(obj)).
222
+ order(timestamp_sort_order("desc"))
223
+ end
224
+
225
+ # @api private
226
+ def subsequent_by_id(version)
227
+ where(arel_table[primary_key].gt(version.id)).order(arel_table[primary_key].asc)
228
+ end
229
+
230
+ # @api private
231
+ def subsequent_by_timestamp(obj)
232
+ obj = obj.send(:created_at) if obj.is_a?(self)
233
+ where(arel_table[:created_at].gt(obj)).order(timestamp_sort_order)
234
+ end
169
235
  end
170
236
 
171
237
  # @api private
@@ -179,18 +245,8 @@ module PaperTrail
179
245
 
180
246
  # Restore the item from this version.
181
247
  #
182
- # Optionally this can also restore all :has_one and :has_many (including
183
- # has_many :through) associations as they were "at the time", if they are
184
- # also being versioned by PaperTrail.
185
- #
186
248
  # Options:
187
249
  #
188
- # - :has_one
189
- # - `true` - Also reify has_one associations.
190
- # - `false - Default.
191
- # - :has_many
192
- # - `true` - Also reify has_many and has_many :through associations.
193
- # - `false` - Default.
194
250
  # - :mark_for_destruction
195
251
  # - `true` - Mark the has_one/has_many associations that did not exist in
196
252
  # the reified version for destruction, instead of removing them.
@@ -205,6 +261,9 @@ module PaperTrail
205
261
  # - `:preserve` - Attributes undefined in version record are not modified.
206
262
  #
207
263
  def reify(options = {})
264
+ unless self.class.column_names.include? "object"
265
+ raise Error, "reify requires an object column"
266
+ end
208
267
  return nil if object.nil?
209
268
  ::PaperTrail::Reifier.reify(self, options)
210
269
  end
@@ -229,13 +288,6 @@ module PaperTrail
229
288
  end
230
289
  alias version_author terminator
231
290
 
232
- def sibling_versions(reload = false)
233
- if reload || !defined?(@sibling_versions) || @sibling_versions.nil?
234
- @sibling_versions = self.class.with_item_keys(item_type, item_id)
235
- end
236
- @sibling_versions
237
- end
238
-
239
291
  def next
240
292
  @next ||= sibling_versions.subsequent(self).first
241
293
  end
@@ -245,8 +297,9 @@ module PaperTrail
245
297
  end
246
298
 
247
299
  # Returns an integer representing the chronological position of the
248
- # version among its siblings (see `sibling_versions`). The "create" event,
249
- # for example, has an index of 0.
300
+ # version among its siblings. The "create" event, for example, has an index
301
+ # of 0.
302
+ #
250
303
  # @api public
251
304
  def index
252
305
  @index ||= RecordHistory.new(sibling_versions, self.class).index(self)
@@ -256,7 +309,7 @@ module PaperTrail
256
309
 
257
310
  # @api private
258
311
  def load_changeset
259
- if PaperTrail.config.object_changes_adapter
312
+ if PaperTrail.config.object_changes_adapter.respond_to?(:load_changeset)
260
313
  return PaperTrail.config.object_changes_adapter.load_changeset(self)
261
314
  end
262
315
 
@@ -304,7 +357,7 @@ module PaperTrail
304
357
  # Enforces the `version_limit`, if set. Default: no limit.
305
358
  # @api private
306
359
  def enforce_version_limit!
307
- limit = PaperTrail.config.version_limit
360
+ limit = version_limit
308
361
  return unless limit.is_a? Numeric
309
362
  previous_versions = sibling_versions.not_creates.
310
363
  order(self.class.timestamp_sort_order("asc"))
@@ -312,5 +365,32 @@ module PaperTrail
312
365
  excess_versions = previous_versions - previous_versions.last(limit)
313
366
  excess_versions.map(&:destroy)
314
367
  end
368
+
369
+ # @api private
370
+ def sibling_versions
371
+ @sibling_versions ||= self.class.with_item_keys(item_type, item_id)
372
+ end
373
+
374
+ # See docs section 2.e. Limiting the Number of Versions Created.
375
+ # The version limit can be global or per-model.
376
+ #
377
+ # @api private
378
+ def version_limit
379
+ if limit_option?(item.class)
380
+ item.class.paper_trail_options[:limit]
381
+ elsif base_class_limit_option?(item.class)
382
+ item.class.base_class.paper_trail_options[:limit]
383
+ else
384
+ PaperTrail.config.version_limit
385
+ end
386
+ end
387
+
388
+ def limit_option?(klass)
389
+ klass.respond_to?(:paper_trail_options) && klass.paper_trail_options.key?(:limit)
390
+ end
391
+
392
+ def base_class_limit_option?(klass)
393
+ klass.respond_to?(:base_class) && limit_option?(klass.base_class)
394
+ end
315
395
  end
316
396
  end
@@ -7,8 +7,8 @@ module PaperTrail
7
7
  # because of this confusion, but it's not worth the breaking change.
8
8
  # People are encouraged to use `PaperTrail.gem_version` instead.
9
9
  module VERSION
10
- MAJOR = 9
11
- MINOR = 2
10
+ MAJOR = 12
11
+ MINOR = 1
12
12
  TINY = 0
13
13
 
14
14
  # Set PRE to nil unless it's a pre-release (beta, rc, etc.)
data/lib/paper_trail.rb CHANGED
@@ -8,33 +8,18 @@
8
8
  # can revisit this decision.
9
9
  require "active_support/all"
10
10
 
11
- # AR is required for, eg. has_paper_trail.rb, so we could put this `require` in
12
- # all of those files, but it seems easier to troubleshoot if we just make sure
13
- # AR is loaded here before loading *any* of PT. See discussion of
14
- # performance/simplicity tradeoff for activesupport above.
15
- require "active_record"
16
-
17
- require "request_store"
11
+ require "paper_trail/errors"
18
12
  require "paper_trail/cleaner"
13
+ require "paper_trail/compatibility"
19
14
  require "paper_trail/config"
20
- require "paper_trail/has_paper_trail"
21
15
  require "paper_trail/record_history"
22
- require "paper_trail/reifier"
23
16
  require "paper_trail/request"
24
- require "paper_trail/version_concern"
25
17
  require "paper_trail/version_number"
26
18
  require "paper_trail/serializers/json"
27
- require "paper_trail/serializers/yaml"
28
19
 
29
20
  # An ActiveRecord extension that tracks changes to your models, for auditing or
30
21
  # versioning.
31
22
  module PaperTrail
32
- E_RAILS_NOT_LOADED = <<-EOS.squish.freeze
33
- PaperTrail has been loaded too early, before rails is loaded. This can
34
- happen when another gem defines the ::Rails namespace, then PT is loaded,
35
- all before rails is loaded. You may want to reorder your Gemfile, or defer
36
- the loading of PT by using `require: false` and a manual require elsewhere.
37
- EOS
38
23
  E_TIMESTAMP_FIELD_CONFIG = <<-EOS.squish.freeze
39
24
  PaperTrail.timestamp_field= has been removed, without replacement. It is no
40
25
  longer configurable. The timestamp column in the versions table must now be
@@ -57,46 +42,6 @@ module PaperTrail
57
42
  !!PaperTrail.config.enabled
58
43
  end
59
44
 
60
- # @deprecated
61
- def enabled_for_controller=(value)
62
- ::ActiveSupport::Deprecation.warn(
63
- "PaperTrail.enabled_for_controller= is deprecated, " \
64
- "use PaperTrail.request.enabled=",
65
- caller(1)
66
- )
67
- request.enabled = value
68
- end
69
-
70
- # @deprecated
71
- def enabled_for_controller?
72
- ::ActiveSupport::Deprecation.warn(
73
- "PaperTrail.enabled_for_controller? is deprecated, " \
74
- "use PaperTrail.request.enabled?",
75
- caller(1)
76
- )
77
- request.enabled?
78
- end
79
-
80
- # @deprecated
81
- def enabled_for_model(model, value)
82
- ::ActiveSupport::Deprecation.warn(
83
- "PaperTrail.enabled_for_model is deprecated, " \
84
- "use PaperTrail.request.enabled_for_model",
85
- caller(1)
86
- )
87
- request.enabled_for_model(model, value)
88
- end
89
-
90
- # @deprecated
91
- def enabled_for_model?(model)
92
- ::ActiveSupport::Deprecation.warn(
93
- "PaperTrail.enabled_for_model? is deprecated, " \
94
- "use PaperTrail.request.enabled_for_model?",
95
- caller(1)
96
- )
97
- request.enabled_for_model?(model)
98
- end
99
-
100
45
  # Returns PaperTrail's `::Gem::Version`, convenient for comparisons. This is
101
46
  # recommended over `::PaperTrail::VERSION::STRING`.
102
47
  #
@@ -124,7 +69,7 @@ module PaperTrail
124
69
  #
125
70
  # @api public
126
71
  def request(options = nil, &block)
127
- if options.nil? && !block_given?
72
+ if options.nil? && !block
128
73
  Request
129
74
  else
130
75
  Request.with(options, &block)
@@ -134,54 +79,7 @@ module PaperTrail
134
79
  # Set the field which records when a version was created.
135
80
  # @api public
136
81
  def timestamp_field=(_field_name)
137
- raise(E_TIMESTAMP_FIELD_CONFIG)
138
- end
139
-
140
- # @deprecated
141
- def whodunnit=(value)
142
- ::ActiveSupport::Deprecation.warn(
143
- "PaperTrail.whodunnit= is deprecated, use PaperTrail.request.whodunnit=",
144
- caller(1)
145
- )
146
- request.whodunnit = value
147
- end
148
-
149
- # @deprecated
150
- def whodunnit(value = nil, &block)
151
- if value.nil?
152
- ::ActiveSupport::Deprecation.warn(
153
- "PaperTrail.whodunnit is deprecated, use PaperTrail.request.whodunnit",
154
- caller(1)
155
- )
156
- request.whodunnit
157
- elsif block_given?
158
- ::ActiveSupport::Deprecation.warn(
159
- "Passing a block to PaperTrail.whodunnit is deprecated, " \
160
- 'use PaperTrail.request(whodunnit: "John") do .. end',
161
- caller(1)
162
- )
163
- request(whodunnit: value, &block)
164
- else
165
- raise ArgumentError, "Invalid arguments"
166
- end
167
- end
168
-
169
- # @deprecated
170
- def controller_info=(value)
171
- ::ActiveSupport::Deprecation.warn(
172
- "PaperTrail.controller_info= is deprecated, use PaperTrail.request.controller_info=",
173
- caller(1)
174
- )
175
- request.controller_info = value
176
- end
177
-
178
- # @deprecated
179
- def controller_info
180
- ::ActiveSupport::Deprecation.warn(
181
- "PaperTrail.controller_info is deprecated, use PaperTrail.request.controller_info",
182
- caller(1)
183
- )
184
- request.controller_info
82
+ raise Error, E_TIMESTAMP_FIELD_CONFIG
185
83
  end
186
84
 
187
85
  # Set the PaperTrail serializer. This setting affects all threads.
@@ -212,23 +110,18 @@ module PaperTrail
212
110
  end
213
111
  end
214
112
 
215
- ActiveSupport.on_load(:active_record) do
216
- include PaperTrail::Model
217
- end
218
-
219
- # Require frameworks
220
- if defined?(::Rails)
221
- # Rails module is sometimes defined by gems like rails-html-sanitizer
222
- # so we check for presence of Rails.application.
223
- if defined?(::Rails.application)
224
- require "paper_trail/frameworks/rails"
225
- else
226
- ::Kernel.warn(::PaperTrail::E_RAILS_NOT_LOADED)
227
- end
113
+ # PT is built on ActiveRecord, but does not require Rails. If Rails is defined,
114
+ # our Railtie makes sure not to load the AR-dependent parts of PT until AR is
115
+ # ready. A typical Rails `application.rb` has:
116
+ #
117
+ # ```
118
+ # require 'rails/all' # Defines `Rails`
119
+ # Bundler.require(*Rails.groups) # require 'paper_trail' (this file)
120
+ # ```
121
+ #
122
+ # Non-rails applications should take similar care to load AR before PT.
123
+ if defined?(Rails)
124
+ require "paper_trail/frameworks/rails"
228
125
  else
229
126
  require "paper_trail/frameworks/active_record"
230
127
  end
231
-
232
- # https://github.com/paper-trail-gem/paper_trail/issues/1070
233
- # https://github.com/westonganger/paper_trail-association_tracking/issues/2
234
- require "paper_trail-association_tracking"