paper_trail 11.0.0 → 12.2.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 (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
@@ -18,11 +18,6 @@ module PaperTrail
18
18
  `abstract_class`. This is fine, but all application models must be
19
19
  configured to use concrete (not abstract) version models.
20
20
  STR
21
- E_MODEL_LIMIT_REQUIRES_ITEM_SUBTYPE = <<~STR.squish.freeze
22
- To use PaperTrail's per-model limit in your %s model, you must have an
23
- item_subtype column in your versions table. See documentation sections
24
- 2.e.1 Per-model limit, and 4.b.1 The optional item_subtype column.
25
- STR
26
21
  DPR_PASSING_ASSOC_NAME_DIRECTLY_TO_VERSIONS_OPTION = <<~STR.squish
27
22
  Passing versions association name as `has_paper_trail versions: %{versions_name}`
28
23
  is deprecated. Use `has_paper_trail versions: {name: %{versions_name}}` instead.
@@ -45,22 +40,14 @@ module PaperTrail
45
40
  @model_class.after_create { |r|
46
41
  r.paper_trail.record_create if r.paper_trail.save_version?
47
42
  }
48
- return if @model_class.paper_trail_options[:on].include?(:create)
49
- @model_class.paper_trail_options[:on] << :create
43
+ append_option_uniquely(:on, :create)
50
44
  end
51
45
 
52
46
  # Adds a callback that records a version before or after a "destroy" event.
53
47
  #
54
48
  # @api public
55
49
  def on_destroy(recording_order = "before")
56
- 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
63
-
50
+ assert_valid_recording_order_for_on_destroy(recording_order)
64
51
  @model_class.send(
65
52
  "#{recording_order}_destroy",
66
53
  lambda do |r|
@@ -68,9 +55,7 @@ module PaperTrail
68
55
  r.paper_trail.record_destroy(recording_order)
69
56
  end
70
57
  )
71
-
72
- return if @model_class.paper_trail_options[:on].include?(:destroy)
73
- @model_class.paper_trail_options[:on] << :destroy
58
+ append_option_uniquely(:on, :destroy)
74
59
  end
75
60
 
76
61
  # Adds a callback that records a version after an "update" event.
@@ -92,19 +77,27 @@ module PaperTrail
92
77
  @model_class.after_update { |r|
93
78
  r.paper_trail.clear_version_instance
94
79
  }
95
- return if @model_class.paper_trail_options[:on].include?(:update)
96
- @model_class.paper_trail_options[:on] << :update
80
+ append_option_uniquely(:on, :update)
97
81
  end
98
82
 
99
83
  # Adds a callback that records a version after a "touch" event.
84
+ #
85
+ # Rails < 6.0 has a bug where dirty-tracking does not occur during
86
+ # a `touch`. (https://github.com/rails/rails/issues/33429) See also:
87
+ # https://github.com/paper-trail-gem/paper_trail/issues/1121
88
+ # https://github.com/paper-trail-gem/paper_trail/issues/1161
89
+ # https://github.com/paper-trail-gem/paper_trail/pull/1285
90
+ #
100
91
  # @api public
101
92
  def on_touch
102
93
  @model_class.after_touch { |r|
103
- r.paper_trail.record_update(
104
- force: true,
105
- in_after_callback: true,
106
- is_touch: true
107
- )
94
+ if r.paper_trail.save_version?
95
+ r.paper_trail.record_update(
96
+ force: RAILS_LT_6_0,
97
+ in_after_callback: true,
98
+ is_touch: true
99
+ )
100
+ end
108
101
  }
109
102
  end
110
103
 
@@ -117,37 +110,48 @@ module PaperTrail
117
110
  @model_class.send :include, ::PaperTrail::Model::InstanceMethods
118
111
  setup_options(options)
119
112
  setup_associations(options)
120
- check_presence_of_item_subtype_column(options)
121
113
  @model_class.after_rollback { paper_trail.clear_rolled_back_versions }
122
114
  setup_callbacks_from_options options[:on]
123
115
  end
124
116
 
117
+ # @api private
125
118
  def version_class
126
- @_version_class ||= @model_class.version_class_name.constantize
119
+ @version_class ||= @model_class.version_class_name.constantize
127
120
  end
128
121
 
129
122
  private
130
123
 
124
+ RAILS_LT_6_0 = ::ActiveRecord.gem_version < ::Gem::Version.new("6.0.0")
125
+ private_constant :RAILS_LT_6_0
126
+
127
+ # @api private
128
+ def append_option_uniquely(option, value)
129
+ collection = @model_class.paper_trail_options.fetch(option)
130
+ return if collection.include?(value)
131
+ collection << value
132
+ end
133
+
131
134
  # Raises an error if the provided class is an `abstract_class`.
132
135
  # @api private
133
136
  def assert_concrete_activerecord_class(class_name)
134
137
  if class_name.constantize.abstract_class?
135
- raise format(E_HPT_ABSTRACT_CLASS, @model_class, class_name)
138
+ raise Error, format(E_HPT_ABSTRACT_CLASS, @model_class, class_name)
136
139
  end
137
140
  end
138
141
 
139
- def cannot_record_after_destroy?
140
- ::ActiveRecord::Base.belongs_to_required_by_default
142
+ # @api private
143
+ def assert_valid_recording_order_for_on_destroy(recording_order)
144
+ unless %w[after before].include?(recording_order.to_s)
145
+ raise ArgumentError, 'recording order can only be "after" or "before"'
146
+ end
147
+
148
+ if recording_order.to_s == "after" && cannot_record_after_destroy?
149
+ raise Error, E_CANNOT_RECORD_AFTER_DESTROY
150
+ end
141
151
  end
142
152
 
143
- # Some options require the presence of the `item_subtype` column. Currently
144
- # only `limit`, but in the future there may be others.
145
- #
146
- # @api private
147
- def check_presence_of_item_subtype_column(options)
148
- return unless options.key?(:limit)
149
- return if version_class.item_subtype_column_present?
150
- raise format(E_MODEL_LIMIT_REQUIRES_ITEM_SUBTYPE, @model_class.name)
153
+ def cannot_record_after_destroy?
154
+ ::ActiveRecord::Base.belongs_to_required_by_default
151
155
  end
152
156
 
153
157
  def check_version_class_name(options)
@@ -205,6 +209,14 @@ module PaperTrail
205
209
  options
206
210
  end
207
211
 
212
+ # Process an `ignore`, `skip`, or `only` option.
213
+ def event_attribute_option(option_name)
214
+ [@model_class.paper_trail_options[option_name]].
215
+ flatten.
216
+ compact.
217
+ map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
218
+ end
219
+
208
220
  def get_versions_scope(options)
209
221
  options[:versions][:scope] || -> { order(model.timestamp_sort_order) }
210
222
  end
@@ -239,12 +251,8 @@ module PaperTrail
239
251
  @model_class.paper_trail_options = options.dup
240
252
 
241
253
  %i[ignore skip only].each do |k|
242
- @model_class.paper_trail_options[k] = [@model_class.paper_trail_options[k]].
243
- flatten.
244
- compact.
245
- map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
254
+ @model_class.paper_trail_options[k] = event_attribute_option(k)
246
255
  end
247
-
248
256
  @model_class.paper_trail_options[:meta] ||= {}
249
257
  end
250
258
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaperTrail
4
+ module Queries
5
+ module Versions
6
+ # For public API documentation, see `where_attribute_changes` in
7
+ # `paper_trail/version_concern.rb`.
8
+ # @api private
9
+ class WhereAttributeChanges
10
+ # - version_model_class - The class that VersionConcern was mixed into.
11
+ # - attribute - An attribute that changed. See the public API
12
+ # documentation for details.
13
+ # @api private
14
+ def initialize(version_model_class, attribute)
15
+ @version_model_class = version_model_class
16
+ @attribute = attribute
17
+ end
18
+
19
+ # @api private
20
+ def execute
21
+ if PaperTrail.config.object_changes_adapter.respond_to?(:where_attribute_changes)
22
+ return PaperTrail.config.object_changes_adapter.where_attribute_changes(
23
+ @version_model_class, @attribute
24
+ )
25
+ end
26
+ column_type = @version_model_class.columns_hash["object_changes"].type
27
+ case column_type
28
+ when :jsonb, :json
29
+ json
30
+ else
31
+ raise UnsupportedColumnType.new(
32
+ method: "where_attribute_changes",
33
+ expected: "json or jsonb",
34
+ actual: column_type
35
+ )
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ # @api private
42
+ def json
43
+ sql = "object_changes -> ? IS NOT NULL"
44
+
45
+ @version_model_class.where(sql, @attribute)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -19,7 +19,7 @@ module PaperTrail
19
19
  # @api private
20
20
  def execute
21
21
  column = @version_model_class.columns_hash["object"]
22
- raise "where_object 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
@@ -23,18 +23,23 @@ module PaperTrail
23
23
 
24
24
  # @api private
25
25
  def execute
26
- if PaperTrail.config.object_changes_adapter&.respond_to?(:where_object_changes)
26
+ if PaperTrail.config.object_changes_adapter.respond_to?(:where_object_changes)
27
27
  return PaperTrail.config.object_changes_adapter.where_object_changes(
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
@@ -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_from` in
7
+ # `paper_trail/version_concern.rb`.
8
+ # @api private
9
+ class WhereObjectChangesFrom
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_from)
22
+ return PaperTrail.config.object_changes_adapter.where_object_changes_from(
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_from",
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
@@ -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
@@ -7,8 +7,6 @@ require "paper_trail/events/update"
7
7
  module PaperTrail
8
8
  # Represents the "paper trail" for a single record.
9
9
  class RecordTrail
10
- RAILS_GTE_5_1 = ::ActiveRecord.gem_version >= ::Gem::Version.new("5.1.0.beta1")
11
-
12
10
  def initialize(record)
13
11
  @record = record
14
12
  end
@@ -200,9 +198,9 @@ module PaperTrail
200
198
  #
201
199
  # This is an "update" event. That is, we record the same data we would in
202
200
  # the case of a normal AR `update`.
203
- def save_with_version(*args)
201
+ def save_with_version(**options)
204
202
  ::PaperTrail.request(enabled: false) do
205
- @record.save(*args)
203
+ @record.save(**options)
206
204
  end
207
205
  record_update(force: true, in_after_callback: false, is_touch: false)
208
206
  end
@@ -285,7 +283,7 @@ module PaperTrail
285
283
  def log_version_errors(version, action)
286
284
  version.logger&.warn(
287
285
  "Unable to create version for #{action} of #{@record.class.name}" \
288
- "##{@record.id}: " + version.errors.full_messages.join(", ")
286
+ "##{@record.id}: " + version.errors.full_messages.join(", ")
289
287
  )
290
288
  end
291
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,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
@@ -9,7 +9,7 @@ module PaperTrail
9
9
  extend self # makes all instance methods become module methods as well
10
10
 
11
11
  def load(string)
12
- ::YAML.load string
12
+ ::YAML.respond_to?(:unsafe_load) ? ::YAML.unsafe_load(string) : ::YAML.load(string)
13
13
  end
14
14
 
15
15
  # @param object (Hash | HashWithIndifferentAccess) - Coming from
@@ -26,18 +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
29
  end
42
30
  end
43
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,16 +25,6 @@ module PaperTrail
28
25
 
29
26
  private
30
27
 
31
- def active_record_pre_502?
32
- ::ActiveRecord.gem_version < Gem::Version.new("5.0.2")
33
- end
34
-
35
- def serialize_with_ar(array)
36
- ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.
37
- new(@subtype, @delimiter).
38
- serialize(array)
39
- end
40
-
41
28
  def deserialize_with_ar(array)
42
29
  ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.
43
30
  new(@subtype, @delimiter).