paper_trail 12.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2ce7f019e3413c485beff4eefa957f759b084fe0d29b0d9f3451b6ba3e4befe
4
- data.tar.gz: 3f73870b42c582f683936eee21fe288b17d915d1bfbff5327ac50dd8e9766732
3
+ metadata.gz: 7e29e666977c2b4072eab98684b884cb43dba15e85367eb8221b9294ebad945c
4
+ data.tar.gz: 750c5670a52675ab4dcc17bfd5389eaf87ebe4d4a3a68ccbb7ed2da1bd43e52f
5
5
  SHA512:
6
- metadata.gz: 6134547d0c2c69f94962aea4f868aec8d456bbb0afc4588b9b07971074a8d50476f29a59acb41d3e058dea581678d0c7129d8e92a04c370fa2016dbd6bf544b7
7
- data.tar.gz: a6ca4e41cf2f6bce774894a9927dc0b3e4abbcbbdbb39fbf4671d029398f26999ce8927143f1f14279a6ad8aa70194025f5b6e653780560a0cc4870dce9b754e
6
+ metadata.gz: b44b40b4683d987d67faf3fabb87d603cd6d99dad2c0c3b6b2859c5d30fd862fe3058e2fa1a1cea982a15ec45a4b8b194a55590b8d523aa8630d3b0644374b8e
7
+ data.tar.gz: '0882176106dfa57ce49b0cf0c1267e2465e134a07719fc3436beec7cad5e10a23c6ff7d409b3332123cf8a5b7ce99e854351e4d60072894026027772f1cc14e8'
@@ -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)
@@ -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.2" # not enforced in gemspec
21
+ ACTIVERECORD_LT = "< 7.0" # 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,11 @@ module PaperTrail
109
109
  @changed_in_latest_version ||= changes_in_latest_version.keys
110
110
  end
111
111
 
112
- # Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
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
- # Memoized to reduce memory usage
118
- @changes_in_latest_version ||= begin
119
- if @in_after_callback
120
- @record.saved_changes
121
- else
122
- @record.changes
123
- end
124
- end
116
+ @changes_in_latest_version ||= load_changes_in_latest_version
125
117
  end
126
118
 
127
119
  # An attributed is "ignored" if it is listed in the `:ignore` option
@@ -134,6 +126,18 @@ module PaperTrail
134
126
  ignored.any? && (changed_in_latest_version & ignored).any?
135
127
  end
136
128
 
129
+ # Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
130
+ # https://github.com/paper-trail-gem/paper_trail/pull/899
131
+ #
132
+ # @api private
133
+ def load_changes_in_latest_version
134
+ if @in_after_callback
135
+ @record.saved_changes
136
+ else
137
+ @record.changes
138
+ end
139
+ end
140
+
137
141
  # PT 10 has a new optional column, `item_subtype`
138
142
  #
139
143
  # @api private
@@ -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.
@@ -53,13 +48,7 @@ module PaperTrail
53
48
  #
54
49
  # @api public
55
50
  def on_destroy(recording_order = "before")
56
- unless %w[after before].include?(recording_order.to_s)
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
51
+ assert_valid_recording_order_for_on_destroy(recording_order)
63
52
 
64
53
  @model_class.send(
65
54
  "#{recording_order}_destroy",
@@ -97,11 +86,18 @@ module PaperTrail
97
86
  end
98
87
 
99
88
  # Adds a callback that records a version after a "touch" event.
89
+ #
90
+ # Rails < 6.0 has a bug where dirty-tracking does not occur during
91
+ # a `touch`. (https://github.com/rails/rails/issues/33429) See also:
92
+ # https://github.com/paper-trail-gem/paper_trail/issues/1121
93
+ # https://github.com/paper-trail-gem/paper_trail/issues/1161
94
+ # https://github.com/paper-trail-gem/paper_trail/pull/1285
95
+ #
100
96
  # @api public
101
97
  def on_touch
102
98
  @model_class.after_touch { |r|
103
99
  r.paper_trail.record_update(
104
- force: true,
100
+ force: RAILS_LT_6_0,
105
101
  in_after_callback: true,
106
102
  is_touch: true
107
103
  )
@@ -117,7 +113,6 @@ module PaperTrail
117
113
  @model_class.send :include, ::PaperTrail::Model::InstanceMethods
118
114
  setup_options(options)
119
115
  setup_associations(options)
120
- check_presence_of_item_subtype_column(options)
121
116
  @model_class.after_rollback { paper_trail.clear_rolled_back_versions }
122
117
  setup_callbacks_from_options options[:on]
123
118
  end
@@ -129,26 +124,30 @@ module PaperTrail
129
124
 
130
125
  private
131
126
 
127
+ RAILS_LT_6_0 = ::ActiveRecord.gem_version < ::Gem::Version.new("6.0.0")
128
+ private_constant :RAILS_LT_6_0
129
+
132
130
  # Raises an error if the provided class is an `abstract_class`.
133
131
  # @api private
134
132
  def assert_concrete_activerecord_class(class_name)
135
133
  if class_name.constantize.abstract_class?
136
- raise format(E_HPT_ABSTRACT_CLASS, @model_class, class_name)
134
+ raise Error, format(E_HPT_ABSTRACT_CLASS, @model_class, class_name)
137
135
  end
138
136
  end
139
137
 
140
- def cannot_record_after_destroy?
141
- ::ActiveRecord::Base.belongs_to_required_by_default
138
+ # @api private
139
+ def assert_valid_recording_order_for_on_destroy(recording_order)
140
+ unless %w[after before].include?(recording_order.to_s)
141
+ raise ArgumentError, 'recording order can only be "after" or "before"'
142
+ end
143
+
144
+ if recording_order.to_s == "after" && cannot_record_after_destroy?
145
+ raise Error, E_CANNOT_RECORD_AFTER_DESTROY
146
+ end
142
147
  end
143
148
 
144
- # Some options require the presence of the `item_subtype` column. Currently
145
- # only `limit`, but in the future there may be others.
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)
149
+ def cannot_record_after_destroy?
150
+ ::ActiveRecord::Base.belongs_to_required_by_default
152
151
  end
153
152
 
154
153
  def check_version_class_name(options)
@@ -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 can't be called without an object column" unless column
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
- case @version_model_class.columns_hash["object_changes"].type
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
- text
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 @version_model_class.columns_hash["object_changes"].type
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
- text
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
@@ -283,7 +283,7 @@ module PaperTrail
283
283
  def log_version_errors(version, action)
284
284
  version.logger&.warn(
285
285
  "Unable to create version for #{action} of #{@record.class.name}" \
286
- "##{@record.id}: " + version.errors.full_messages.join(", ")
286
+ "##{@record.id}: " + version.errors.full_messages.join(", ")
287
287
  )
288
288
  end
289
289
 
@@ -60,9 +60,7 @@ module PaperTrail
60
60
  model = if options[:dup] == true || version.event == "destroy"
61
61
  klass.new
62
62
  else
63
- find_cond = { klass.primary_key => version.item_id }
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`. You can see this particular
119
- # example in action in `spec/models/animal_spec.rb`.
122
+ # this method returns the constant `Animal`.
120
123
  #
121
- # TODO: Duplication: similar `constantize` in VersionConcern#version_limit
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
- inheritance_column_name = version.item_type.constantize.inheritance_column
132
+ clazz = version.item_type.constantize
133
+ inheritance_column_name = clazz.inheritance_column
124
134
  inher_col_value = attrs[inheritance_column_name]
125
- class_name = inher_col_value.blank? ? version.item_type : inher_col_value
126
- 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)
127
144
  end
128
145
  end
129
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,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
@@ -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
@@ -21,10 +23,6 @@ module PaperTrail
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 "event <> ?", "create"
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 can't be called without an object column"
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,22 @@ 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
- if self.class.item_subtype_column_present?
357
- klass = (item_subtype || item_type).constantize
358
- if klass&.paper_trail_options&.key?(:limit)
359
- return klass.paper_trail_options[:limit]
360
- end
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
361
385
  end
362
- PaperTrail.config.version_limit
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)
363
394
  end
364
395
  end
365
396
  end
@@ -8,7 +8,7 @@ module PaperTrail
8
8
  # People are encouraged to use `PaperTrail.gem_version` instead.
9
9
  module VERSION
10
10
  MAJOR = 12
11
- MINOR = 0
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,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"
@@ -68,7 +69,7 @@ module PaperTrail
68
69
  #
69
70
  # @api public
70
71
  def request(options = nil, &block)
71
- if options.nil? && !block_given?
72
+ if options.nil? && !block
72
73
  Request
73
74
  else
74
75
  Request.with(options, &block)
@@ -78,7 +79,7 @@ module PaperTrail
78
79
  # Set the field which records when a version was created.
79
80
  # @api public
80
81
  def timestamp_field=(_field_name)
81
- raise(E_TIMESTAMP_FIELD_CONFIG)
82
+ raise Error, E_TIMESTAMP_FIELD_CONFIG
82
83
  end
83
84
 
84
85
  # 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.0.0
4
+ version: 12.1.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: 2021-03-29 00:00:00.000000000 Z
13
+ date: 2021-08-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -46,14 +46,14 @@ dependencies:
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '2.2'
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: '2.2'
56
+ version: 2.4.1
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: byebug
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -74,14 +74,14 @@ dependencies:
74
74
  requirements:
75
75
  - - "~>"
76
76
  - !ruby/object:Gem::Version
77
- version: '2.11'
77
+ version: 2.19.0
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.11'
84
+ version: 2.19.0
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.9.14
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.9.14
112
+ version: 1.0.0
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rails
115
115
  requirement: !ruby/object:Gem::Requirement
@@ -144,84 +144,118 @@ dependencies:
144
144
  requirements:
145
145
  - - "~>"
146
146
  - !ruby/object:Gem::Version
147
- version: '4.0'
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: '4.0'
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.11.0
161
+ version: 1.20.0
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.11.0
168
+ version: 1.20.0
169
169
  - !ruby/object:Gem::Dependency
170
- name: rubocop-rails
170
+ name: rubocop-packaging
171
171
  requirement: !ruby/object:Gem::Requirement
172
172
  requirements:
173
173
  - - "~>"
174
174
  - !ruby/object:Gem::Version
175
- version: 2.9.1
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: 2.9.1
182
+ version: 0.5.1
183
183
  - !ruby/object:Gem::Dependency
184
- name: rubocop-packaging
184
+ name: rubocop-performance
185
185
  requirement: !ruby/object:Gem::Requirement
186
186
  requirements:
187
187
  - - "~>"
188
188
  - !ruby/object:Gem::Version
189
- version: 0.5.1
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: 0.5.1
196
+ version: 1.11.5
197
197
  - !ruby/object:Gem::Dependency
198
- name: rubocop-performance
198
+ name: rubocop-rails
199
+ requirement: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - "~>"
202
+ - !ruby/object:Gem::Version
203
+ version: 2.11.3
204
+ type: :development
205
+ prerelease: false
206
+ version_requirements: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - "~>"
209
+ - !ruby/object:Gem::Version
210
+ version: 2.11.3
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: 1.10.1
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: 1.10.1
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.2.0
231
+ version: 2.4.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.2.0
238
+ version: 2.4.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'
246
+ - - "<"
247
+ - !ruby/object:Gem::Version
248
+ version: '0.22'
249
+ type: :development
250
+ prerelease: false
251
+ version_requirements: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ">="
254
+ - !ruby/object:Gem::Version
255
+ version: '0.21'
256
+ - - "<"
257
+ - !ruby/object:Gem::Version
258
+ version: '0.22'
225
259
  - !ruby/object:Gem::Dependency
226
260
  name: mysql2
227
261
  requirement: !ruby/object:Gem::Requirement
@@ -297,6 +331,7 @@ files:
297
331
  - lib/paper_trail/cleaner.rb
298
332
  - lib/paper_trail/compatibility.rb
299
333
  - lib/paper_trail/config.rb
334
+ - lib/paper_trail/errors.rb
300
335
  - lib/paper_trail/events/base.rb
301
336
  - lib/paper_trail/events/create.rb
302
337
  - lib/paper_trail/events/destroy.rb
@@ -311,9 +346,11 @@ files:
311
346
  - lib/paper_trail/frameworks/rspec/helpers.rb
312
347
  - lib/paper_trail/has_paper_trail.rb
313
348
  - lib/paper_trail/model_config.rb
349
+ - lib/paper_trail/queries/versions/where_attribute_changes.rb
314
350
  - lib/paper_trail/queries/versions/where_object.rb
315
351
  - lib/paper_trail/queries/versions/where_object_changes.rb
316
352
  - lib/paper_trail/queries/versions/where_object_changes_from.rb
353
+ - lib/paper_trail/queries/versions/where_object_changes_to.rb
317
354
  - lib/paper_trail/record_history.rb
318
355
  - lib/paper_trail/record_trail.rb
319
356
  - lib/paper_trail/reifier.rb
@@ -342,8 +379,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
342
379
  - !ruby/object:Gem::Version
343
380
  version: 1.3.6
344
381
  requirements: []
345
- rubyforge_project:
346
- rubygems_version: 2.7.6.2
382
+ rubygems_version: 3.2.22
347
383
  signing_key:
348
384
  specification_version: 4
349
385
  summary: Track changes to your models.