avromatic 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/avromatic/model/attributes.rb +22 -3
- data/lib/avromatic/model/configurable.rb +6 -2
- data/lib/avromatic/model/configuration.rb +5 -0
- data/lib/avromatic/model/field_helper.rb +5 -1
- data/lib/avromatic/model/raw_serialization.rb +63 -23
- data/lib/avromatic/model/types/record_type.rb +3 -2
- data/lib/avromatic/model/validation.rb +2 -2
- data/lib/avromatic/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7401c0e72992925f02234f5d3d2ab8e762a36bc62aa25c631569d6f4d9918d2
|
4
|
+
data.tar.gz: f2121b2a62bf60893ea0eb143ed83a142ea069d07839fb8121d0618483b469d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42be85747686fca4ec66d6e178f7e5aab6d9e9ab88cd4d107ed1c5de8a83017f083a510889ced33a2eb284f45865b3c32b3a9edad200011aed5b17c284f3a593
|
7
|
+
data.tar.gz: be13122bca8693d33e20d1317ae5cd88d8c1c975c08d94ed522d0330d70f202bc43d79d7f2941032bc7540ad83b2d647d3c7d29bb5b72c03a560dfedb85e62f7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# avromatic changelog
|
2
2
|
|
3
|
+
## v2.4.0
|
4
|
+
- Ignore the `validate` argument and always validate during serialization. This
|
5
|
+
argument will be removed in Avromatic 3.0.
|
6
|
+
- Optimize model validation during serialization.
|
7
|
+
- Don't cache immutable model validation results or serialized Avro attributes if a model has mutable children.
|
8
|
+
|
3
9
|
## v2.3.0
|
4
10
|
- Add support for Rails 6.1.
|
5
11
|
- Optimize nested model serialization.
|
@@ -27,7 +27,10 @@ module Avromatic
|
|
27
27
|
def initialize(owner:, field:, type:)
|
28
28
|
@owner = owner
|
29
29
|
@field = field
|
30
|
+
@required = FieldHelper.required?(field)
|
31
|
+
@nullable = FieldHelper.nullable?(field)
|
30
32
|
@type = type
|
33
|
+
@values_immutable = type.referenced_model_classes.all?(&:recursively_immutable?)
|
31
34
|
@name = field.name.to_sym
|
32
35
|
@name_string = field.name.to_s.dup.freeze
|
33
36
|
@setter_name = "#{field.name}=".to_sym
|
@@ -40,8 +43,16 @@ module Avromatic
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
46
|
+
def nullable?
|
47
|
+
@nullable
|
48
|
+
end
|
49
|
+
|
43
50
|
def required?
|
44
|
-
|
51
|
+
@required
|
52
|
+
end
|
53
|
+
|
54
|
+
def values_immutable?
|
55
|
+
@values_immutable
|
45
56
|
end
|
46
57
|
|
47
58
|
def coerce(input)
|
@@ -69,6 +80,8 @@ module Avromatic
|
|
69
80
|
included do
|
70
81
|
class_attribute :attribute_definitions, instance_writer: false
|
71
82
|
self.attribute_definitions = {}
|
83
|
+
|
84
|
+
delegate :recursively_immutable?, to: :class
|
72
85
|
end
|
73
86
|
|
74
87
|
def initialize(data = {})
|
@@ -130,6 +143,12 @@ module Avromatic
|
|
130
143
|
define_avro_attributes(avro_schema, generated_methods_module)
|
131
144
|
end
|
132
145
|
|
146
|
+
def recursively_immutable?
|
147
|
+
return @recursively_immutable if defined?(@recursively_immutable)
|
148
|
+
|
149
|
+
@recursively_immutable = immutable? && attribute_definitions.each_value.all?(&:values_immutable?)
|
150
|
+
end
|
151
|
+
|
133
152
|
private
|
134
153
|
|
135
154
|
def check_for_field_conflicts!
|
@@ -174,10 +193,10 @@ module Avromatic
|
|
174
193
|
generated_methods_module.send(:define_method, "#{field.name}?") { !!_attributes[symbolized_field_name] } if FieldHelper.boolean?(field)
|
175
194
|
|
176
195
|
generated_methods_module.send(:define_method, "#{field.name}=") do |value|
|
177
|
-
_attributes[symbolized_field_name] =
|
196
|
+
_attributes[symbolized_field_name] = attribute_definition.coerce(value)
|
178
197
|
end
|
179
198
|
|
180
|
-
unless
|
199
|
+
unless mutable? # rubocop:disable Style/Next
|
181
200
|
generated_methods_module.send(:private, "#{field.name}=")
|
182
201
|
generated_methods_module.send(:define_method, :clone) { self }
|
183
202
|
generated_methods_module.send(:define_method, :dup) { self }
|
@@ -19,9 +19,12 @@ module Avromatic
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
included do
|
23
|
+
class_attribute :config, instance_accessor: false, instance_predicate: false
|
24
|
+
end
|
25
|
+
|
22
26
|
module ClassMethods
|
23
|
-
|
24
|
-
delegate :avro_schema, :value_avro_schema, :key_avro_schema, to: :config
|
27
|
+
delegate :avro_schema, :value_avro_schema, :key_avro_schema, :mutable?, :immutable?, to: :config
|
25
28
|
|
26
29
|
def value_avro_field_names
|
27
30
|
@value_avro_field_names ||= value_avro_schema.fields.map(&:name).map(&:to_sym).freeze
|
@@ -67,6 +70,7 @@ module Avromatic
|
|
67
70
|
delegate :avro_schema, :value_avro_schema, :key_avro_schema,
|
68
71
|
:value_avro_field_names, :key_avro_field_names,
|
69
72
|
:value_avro_field_references, :key_avro_field_references,
|
73
|
+
:mutable?, :immutable?,
|
70
74
|
to: :class
|
71
75
|
end
|
72
76
|
end
|
@@ -8,6 +8,7 @@ module Avromatic
|
|
8
8
|
|
9
9
|
attr_reader :avro_schema, :key_avro_schema, :nested_models, :mutable,
|
10
10
|
:allow_optional_key_fields
|
11
|
+
alias_method :mutable?, :mutable
|
11
12
|
delegate :schema_store, to: Avromatic
|
12
13
|
|
13
14
|
# Either schema(_name) or value_schema(_name), but not both, must be
|
@@ -34,6 +35,10 @@ module Avromatic
|
|
34
35
|
|
35
36
|
alias_method :value_avro_schema, :avro_schema
|
36
37
|
|
38
|
+
def immutable?
|
39
|
+
!mutable?
|
40
|
+
end
|
41
|
+
|
37
42
|
private
|
38
43
|
|
39
44
|
def find_avro_schema(**options)
|
@@ -16,9 +16,13 @@ module Avromatic
|
|
16
16
|
!optional?(field)
|
17
17
|
end
|
18
18
|
|
19
|
+
def nullable?(field)
|
20
|
+
optional?(field) || field.type.type_sym == :null
|
21
|
+
end
|
22
|
+
|
19
23
|
def boolean?(field)
|
20
24
|
field.type.type_sym == :boolean ||
|
21
|
-
(
|
25
|
+
(optional?(field) && field.type.schemas.last.type_sym == :boolean)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support/deprecation'
|
4
|
+
|
3
5
|
module Avromatic
|
4
6
|
module Model
|
5
7
|
|
@@ -11,55 +13,93 @@ module Avromatic
|
|
11
13
|
module Encode
|
12
14
|
extend ActiveSupport::Concern
|
13
15
|
|
16
|
+
UNSPECIFIED = Object.new
|
17
|
+
|
14
18
|
delegate :datum_writer, :datum_reader, to: :class
|
15
19
|
private :datum_writer, :datum_reader
|
16
20
|
|
17
|
-
def avro_raw_value(validate:
|
18
|
-
|
19
|
-
|
21
|
+
def avro_raw_value(validate: UNSPECIFIED)
|
22
|
+
unless validate == UNSPECIFIED
|
23
|
+
ActiveSupport::Deprecation.warn("The 'validate' argument to #{__method__} is deprecated.")
|
24
|
+
end
|
25
|
+
|
26
|
+
if self.class.recursively_immutable?
|
27
|
+
@avro_raw_value ||= avro_raw_encode(value_attributes_for_avro, :value)
|
20
28
|
else
|
21
|
-
|
29
|
+
avro_raw_encode(value_attributes_for_avro, :value)
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
25
|
-
def avro_raw_key(validate:
|
33
|
+
def avro_raw_key(validate: UNSPECIFIED)
|
34
|
+
unless validate == UNSPECIFIED
|
35
|
+
ActiveSupport::Deprecation.warn("The 'validate' argument to #{__method__} is deprecated.")
|
36
|
+
end
|
37
|
+
|
26
38
|
raise 'Model has no key schema' unless key_avro_schema
|
27
|
-
avro_raw_encode(key_attributes_for_avro
|
39
|
+
avro_raw_encode(key_attributes_for_avro, :key)
|
28
40
|
end
|
29
41
|
|
30
|
-
def value_attributes_for_avro(validate:
|
31
|
-
|
32
|
-
|
42
|
+
def value_attributes_for_avro(validate: UNSPECIFIED)
|
43
|
+
unless validate == UNSPECIFIED
|
44
|
+
ActiveSupport::Deprecation.warn("The 'validate' argument to #{__method__} is deprecated.")
|
45
|
+
end
|
46
|
+
|
47
|
+
if self.class.recursively_immutable?
|
48
|
+
@value_attributes_for_avro ||= avro_hash(value_avro_field_references)
|
33
49
|
else
|
34
|
-
|
50
|
+
avro_hash(value_avro_field_references)
|
35
51
|
end
|
36
52
|
end
|
37
53
|
|
38
|
-
def key_attributes_for_avro(validate:
|
39
|
-
|
54
|
+
def key_attributes_for_avro(validate: UNSPECIFIED)
|
55
|
+
unless validate == UNSPECIFIED
|
56
|
+
ActiveSupport::Deprecation.warn("The 'validate' argument to #{__method__} is deprecated.")
|
57
|
+
end
|
58
|
+
|
59
|
+
avro_hash(key_avro_field_references)
|
40
60
|
end
|
41
61
|
|
42
|
-
def avro_value_datum(validate:
|
43
|
-
|
44
|
-
|
62
|
+
def avro_value_datum(validate: UNSPECIFIED)
|
63
|
+
unless validate == UNSPECIFIED
|
64
|
+
ActiveSupport::Deprecation.warn("The 'validate' argument to #{__method__} is deprecated.")
|
65
|
+
end
|
66
|
+
|
67
|
+
if self.class.recursively_immutable?
|
68
|
+
@avro_value_datum ||= avro_hash(value_avro_field_references, strict: true)
|
45
69
|
else
|
46
|
-
|
70
|
+
avro_hash(value_avro_field_references, strict: true)
|
47
71
|
end
|
48
72
|
end
|
49
73
|
|
50
|
-
def avro_key_datum(validate:
|
51
|
-
|
74
|
+
def avro_key_datum(validate: UNSPECIFIED)
|
75
|
+
unless validate == UNSPECIFIED
|
76
|
+
ActiveSupport::Deprecation.warn("The 'validate' argument to #{__method__} is deprecated.")
|
77
|
+
end
|
78
|
+
|
79
|
+
avro_hash(key_avro_field_references, strict: true)
|
52
80
|
end
|
53
81
|
|
54
82
|
private
|
55
83
|
|
56
|
-
def avro_hash(field_references, strict: false
|
57
|
-
avro_validate! if validate
|
84
|
+
def avro_hash(field_references, strict: false)
|
58
85
|
field_references.each_with_object(Hash.new) do |field_reference, result|
|
59
|
-
|
60
|
-
|
86
|
+
attribute_definition = self.class.attribute_definitions[field_reference.name_sym]
|
61
87
|
value = _attributes[field_reference.name_sym]
|
62
|
-
|
88
|
+
|
89
|
+
if value.nil? && !attribute_definition.nullable?
|
90
|
+
# We're missing a required attribute so perform an explicit validation to generate
|
91
|
+
# a more complete error message
|
92
|
+
avro_validate!
|
93
|
+
elsif _attributes.include?(field_reference.name_sym)
|
94
|
+
begin
|
95
|
+
result[field_reference.name] = attribute_definition.serialize(value, strict)
|
96
|
+
rescue Avromatic::Model::ValidationError
|
97
|
+
# Perform an explicit validation to generate a more complete error message
|
98
|
+
avro_validate!
|
99
|
+
# We should never get here but just in case...
|
100
|
+
raise
|
101
|
+
end
|
102
|
+
end
|
63
103
|
end
|
64
104
|
end
|
65
105
|
|
@@ -42,9 +42,10 @@ module Avromatic
|
|
42
42
|
def serialize(value, strict)
|
43
43
|
if value.nil?
|
44
44
|
value
|
45
|
+
elsif strict
|
46
|
+
value.avro_value_datum
|
45
47
|
else
|
46
|
-
|
47
|
-
strict ? value.avro_value_datum(validate: false) : value.value_attributes_for_avro(validate: false)
|
48
|
+
value.value_attributes_for_avro
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
data/lib/avromatic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avromatic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Salsify Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|