avromatic 3.0.0 → 4.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 +4 -4
- data/.circleci/config.yml +11 -12
- data/.github/CODEOWNERS +1 -0
- data/.rubocop.yml +2 -2
- data/.ruby-version +1 -1
- data/Appraisals +15 -15
- data/CHANGELOG.md +18 -0
- data/README.md +24 -3
- data/avromatic.gemspec +15 -6
- data/gemfiles/{avro1_9_rails5_2.gemfile → avro1_10_rails7_0.gemfile} +3 -3
- data/gemfiles/{avro1_9_rails6_1.gemfile → avro1_11_rails6_1.gemfile} +1 -1
- data/gemfiles/{avro1_9_rails6_0.gemfile → avro1_11_rails7_0.gemfile} +3 -3
- data/lib/avromatic/io/datum_writer.rb +1 -3
- data/lib/avromatic/messaging.rb +2 -4
- data/lib/avromatic/model/attributes.rb +30 -13
- data/lib/avromatic/model/configurable.rb +3 -1
- data/lib/avromatic/model/configuration.rb +9 -1
- data/lib/avromatic/model/message_decoder.rb +3 -1
- data/lib/avromatic/model/messaging_serialization.rb +9 -6
- data/lib/avromatic/model/nested_models.rb +4 -2
- data/lib/avromatic/model/raw_serialization.rb +6 -5
- data/lib/avromatic/model/types/array_type.rb +1 -0
- data/lib/avromatic/model/types/custom_type.rb +6 -1
- data/lib/avromatic/model/types/enum_type.rb +1 -0
- data/lib/avromatic/model/types/fixed_type.rb +1 -0
- data/lib/avromatic/model/types/map_type.rb +1 -0
- data/lib/avromatic/model/types/record_type.rb +1 -0
- data/lib/avromatic/model/types/type_factory.rb +7 -3
- data/lib/avromatic/model/types/union_type.rb +2 -3
- data/lib/avromatic/model/validation.rb +1 -3
- data/lib/avromatic/model_registry.rb +13 -2
- data/lib/avromatic/rspec.rb +1 -0
- data/lib/avromatic/version.rb +1 -1
- data/lib/avromatic.rb +6 -0
- metadata +21 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: edd31aa475804bf20a1f5b4ddbe90e8c98460617daeaf2e1641316c08cce505b
|
|
4
|
+
data.tar.gz: b20ae31b2aeff034f9fa99e2a90d4bb78dfe894967ab8e0267b1df6ee954a15d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6e4d441e7645b52840725041d361f699266a9e5dd974e8cd588c8f4750ba21eb4efd016b9c6c20e034a98ed79b673f9aa12a5f0b3a56312a57b344659b93606d
|
|
7
|
+
data.tar.gz: 5b8ba9cc0049f80a31f88399ca504796997038b969d728be5867d6fd5bc6868786e4ae9dffc0de8a7c1db99e129f9398e4f867794dbd449d54f74c69650735bb
|
data/.circleci/config.yml
CHANGED
|
@@ -2,14 +2,14 @@ version: 2.1
|
|
|
2
2
|
jobs:
|
|
3
3
|
lint:
|
|
4
4
|
docker:
|
|
5
|
-
- image: salsify/ruby_ci:2.
|
|
5
|
+
- image: salsify/ruby_ci:2.7.4
|
|
6
6
|
working_directory: ~/avromatic
|
|
7
7
|
steps:
|
|
8
8
|
- checkout
|
|
9
9
|
- restore_cache:
|
|
10
10
|
keys:
|
|
11
|
-
- v2-gems-ruby-2.
|
|
12
|
-
- v2-gems-ruby-2.
|
|
11
|
+
- v2-gems-ruby-2.7.4-{{ checksum "avromatic.gemspec" }}-{{ checksum "Gemfile" }}
|
|
12
|
+
- v2-gems-ruby-2.7.4-
|
|
13
13
|
- run:
|
|
14
14
|
name: Install Gems
|
|
15
15
|
command: |
|
|
@@ -18,7 +18,7 @@ jobs:
|
|
|
18
18
|
bundle clean
|
|
19
19
|
fi
|
|
20
20
|
- save_cache:
|
|
21
|
-
key: v2-gems-ruby-2.
|
|
21
|
+
key: v2-gems-ruby-2.7.4-{{ checksum "avromatic.gemspec" }}-{{ checksum "Gemfile" }}
|
|
22
22
|
paths:
|
|
23
23
|
- "vendor/bundle"
|
|
24
24
|
- "gemfiles/vendor/bundle"
|
|
@@ -69,21 +69,20 @@ workflows:
|
|
|
69
69
|
matrix:
|
|
70
70
|
parameters:
|
|
71
71
|
gemfile:
|
|
72
|
-
- "gemfiles/avro1_9_rails5_2.gemfile"
|
|
73
72
|
- "gemfiles/avro1_10_rails5_2.gemfile"
|
|
74
|
-
- "gemfiles/avro1_9_rails6_0.gemfile"
|
|
75
73
|
- "gemfiles/avro1_10_rails6_0.gemfile"
|
|
76
74
|
- "gemfiles/avro1_10_rails6_1.gemfile"
|
|
77
|
-
- "gemfiles/
|
|
75
|
+
- "gemfiles/avro1_10_rails7_0.gemfile"
|
|
76
|
+
- "gemfiles/avro1_11_rails7_0.gemfile"
|
|
78
77
|
ruby-version:
|
|
79
|
-
- "2.
|
|
80
|
-
- "2.6.6"
|
|
81
|
-
- "2.7.2"
|
|
78
|
+
- "2.7.4"
|
|
82
79
|
- test:
|
|
83
80
|
matrix:
|
|
84
81
|
parameters:
|
|
85
82
|
gemfile:
|
|
86
83
|
- "gemfiles/avro1_10_rails6_1.gemfile"
|
|
87
|
-
- "gemfiles/
|
|
84
|
+
- "gemfiles/avro1_10_rails7_0.gemfile"
|
|
85
|
+
- "gemfiles/avro1_11_rails7_0.gemfile"
|
|
88
86
|
ruby-version:
|
|
89
|
-
- "3.0.
|
|
87
|
+
- "3.0.3"
|
|
88
|
+
- "3.1.0"
|
data/.github/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @jturkel @kphelps @tjwp
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.7.4
|
data/Appraisals
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
appraise 'avro1_9-rails5_2' do
|
|
4
|
-
gem 'avro', '1.9.2'
|
|
5
|
-
gem 'activesupport', '~> 5.2.0'
|
|
6
|
-
gem 'activemodel', '~> 5.2.0'
|
|
7
|
-
end
|
|
8
|
-
|
|
9
3
|
appraise 'avro1_10-rails5_2' do
|
|
10
4
|
gem 'avro', '~> 1.10.0'
|
|
11
5
|
gem 'activesupport', '~> 5.2.0'
|
|
12
6
|
gem 'activemodel', '~> 5.2.0'
|
|
13
7
|
end
|
|
14
8
|
|
|
15
|
-
appraise 'avro1_9-rails6_0' do
|
|
16
|
-
gem 'avro', '1.9.2'
|
|
17
|
-
gem 'activesupport', '~> 6.0.0'
|
|
18
|
-
gem 'activemodel', '~> 6.0.0'
|
|
19
|
-
end
|
|
20
|
-
|
|
21
9
|
appraise 'avro1_10-rails6_0' do
|
|
22
10
|
gem 'avro', '~> 1.10.0'
|
|
23
11
|
gem 'activesupport', '~> 6.0.0'
|
|
24
12
|
gem 'activemodel', '~> 6.0.0'
|
|
25
13
|
end
|
|
26
14
|
|
|
27
|
-
appraise '
|
|
28
|
-
gem 'avro', '1.
|
|
15
|
+
appraise 'avro1_10-rails6_1' do
|
|
16
|
+
gem 'avro', '~> 1.10.0'
|
|
29
17
|
gem 'activesupport', '~> 6.1.0'
|
|
30
18
|
gem 'activemodel', '~> 6.1.0'
|
|
31
19
|
end
|
|
32
20
|
|
|
33
|
-
appraise 'avro1_10-
|
|
21
|
+
appraise 'avro1_10-rails7_0' do
|
|
34
22
|
gem 'avro', '~> 1.10.0'
|
|
23
|
+
gem 'activesupport', '~> 7.0.0'
|
|
24
|
+
gem 'activemodel', '~> 7.0.0'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
appraise 'avro1_11-rails6_1' do
|
|
28
|
+
gem 'avro', '~> 1.11.0'
|
|
35
29
|
gem 'activesupport', '~> 6.1.0'
|
|
36
30
|
gem 'activemodel', '~> 6.1.0'
|
|
37
31
|
end
|
|
32
|
+
|
|
33
|
+
appraise 'avro1_11-rails7_0' do
|
|
34
|
+
gem 'avro', '~> 1.11.0'
|
|
35
|
+
gem 'activesupport', '~> 7.0.0'
|
|
36
|
+
gem 'activemodel', '~> 7.0.0'
|
|
37
|
+
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# avromatic changelog
|
|
2
2
|
|
|
3
|
+
## 4.1.0
|
|
4
|
+
- Add support for specifying a subject for the avro schema when building an Avromatic model
|
|
5
|
+
|
|
6
|
+
## 4.0.0
|
|
7
|
+
- Drop support for Ruby 2.6.
|
|
8
|
+
- Drop support for Avro 1.9.
|
|
9
|
+
- Add support for Avro 1.11.
|
|
10
|
+
- Add support for Rails 7.0.
|
|
11
|
+
|
|
12
|
+
## 3.0.2
|
|
13
|
+
- Reset the schema registry client between RSpec tests to ensure any cached values are
|
|
14
|
+
consistent with the fake schema registry.
|
|
15
|
+
|
|
16
|
+
## 3.0.1
|
|
17
|
+
- Raise an error when registering a nested model that has already been auto-generated.
|
|
18
|
+
This avoids hard to troubleshoot coercion errors when instantiating models and fixes
|
|
19
|
+
a regression introduced in Avromatic 2.2.2.
|
|
20
|
+
|
|
3
21
|
## 3.0.0
|
|
4
22
|
- Drop support for Ruby 2.4.
|
|
5
23
|
- Add support for Ruby 3.0.
|
data/README.md
CHANGED
|
@@ -72,7 +72,9 @@ and the [Messaging API](#messaging-api).
|
|
|
72
72
|
so that they can be referenced by id. Either `schema_registry` or
|
|
73
73
|
`registry_url` must be configured.
|
|
74
74
|
* **registry_url**: URL for the schema registry. Either `schema_registry` or
|
|
75
|
-
`registry_url` must be configured.
|
|
75
|
+
`registry_url` must be configured. The `build_schema_registry!` method may
|
|
76
|
+
be used to create a caching schema registry client instance based on other
|
|
77
|
+
configuration values.
|
|
76
78
|
* **use_schema_fingerprint_lookup**: Avromatic supports a Schema Registry
|
|
77
79
|
[extension](https://github.com/salsify/avro-schema-registry#extensions) that
|
|
78
80
|
provides an endpoint to lookup existing schema ids by fingerprint.
|
|
@@ -91,6 +93,7 @@ Example using a schema registry:
|
|
|
91
93
|
Avromatic.configure do |config|
|
|
92
94
|
config.schema_store = AvroTurf::SchemaStore.new(path: 'avro/schemas')
|
|
93
95
|
config.registry_url = Rails.configuration.x.avro_schema_registry_url
|
|
96
|
+
config.build_schema_registry!
|
|
94
97
|
config.build_messaging!
|
|
95
98
|
end
|
|
96
99
|
```
|
|
@@ -121,7 +124,7 @@ The Avro schema can be specified by name and loaded using the schema store:
|
|
|
121
124
|
|
|
122
125
|
```ruby
|
|
123
126
|
class MyModel
|
|
124
|
-
include Avromatic::Model.build(schema_name :my_model)
|
|
127
|
+
include Avromatic::Model.build(schema_name: :my_model)
|
|
125
128
|
end
|
|
126
129
|
|
|
127
130
|
# Construct instances by passing in a hash of attributes
|
|
@@ -153,12 +156,20 @@ class MyModel
|
|
|
153
156
|
end
|
|
154
157
|
```
|
|
155
158
|
|
|
159
|
+
A specific subject name can be associated with the schema:
|
|
160
|
+
```ruby
|
|
161
|
+
class MyModel
|
|
162
|
+
include Avromatic::Model.build(schema_name: 'my_model',
|
|
163
|
+
schema_subject: 'my_model-value')
|
|
164
|
+
end
|
|
165
|
+
```
|
|
166
|
+
|
|
156
167
|
Models are generated as immutable value
|
|
157
168
|
objects by default, but can optionally be defined as mutable:
|
|
158
169
|
|
|
159
170
|
```ruby
|
|
160
171
|
class MyModel
|
|
161
|
-
include Avromatic::Model.build(schema_name :my_model, mutable: true)
|
|
172
|
+
include Avromatic::Model.build(schema_name: :my_model, mutable: true)
|
|
162
173
|
end
|
|
163
174
|
```
|
|
164
175
|
|
|
@@ -192,6 +203,16 @@ class MyTopic
|
|
|
192
203
|
end
|
|
193
204
|
```
|
|
194
205
|
|
|
206
|
+
A specific subject name can be associated with both the value and key schemas:
|
|
207
|
+
```ruby
|
|
208
|
+
class MyTopic
|
|
209
|
+
include Avromatic::Model.build(value_schema_name: :topic_value,
|
|
210
|
+
value_schema_subject: 'topic_value-value',
|
|
211
|
+
key_schema_name: :topic_key,
|
|
212
|
+
key_schema_subject: 'topic_key-value')
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
195
216
|
A model can also be generated as an anonymous class that can be assigned to a
|
|
196
217
|
constant:
|
|
197
218
|
|
data/avromatic.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path('
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'avromatic/version'
|
|
6
6
|
|
|
@@ -15,16 +15,25 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
spec.homepage = 'https://github.com/salsify/avromatic.git'
|
|
16
16
|
spec.license = 'MIT'
|
|
17
17
|
|
|
18
|
+
if spec.respond_to?(:metadata)
|
|
19
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
20
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
21
|
+
else
|
|
22
|
+
raise 'RubyGems 2.0 or newer is required to set allowed_push_host.'
|
|
23
|
+
end
|
|
24
|
+
|
|
18
25
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
19
26
|
spec.bindir = 'exe'
|
|
20
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
21
28
|
spec.require_paths = ['lib']
|
|
22
29
|
|
|
23
|
-
spec.
|
|
30
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
31
|
+
|
|
32
|
+
spec.required_ruby_version = '>= 2.7'
|
|
24
33
|
|
|
25
|
-
spec.add_runtime_dependency 'activemodel', '>= 5.2', '<
|
|
26
|
-
spec.add_runtime_dependency 'activesupport', '>= 5.2', '<
|
|
27
|
-
spec.add_runtime_dependency 'avro', '>= 1.
|
|
34
|
+
spec.add_runtime_dependency 'activemodel', '>= 5.2', '< 7.1'
|
|
35
|
+
spec.add_runtime_dependency 'activesupport', '>= 5.2', '< 7.1'
|
|
36
|
+
spec.add_runtime_dependency 'avro', '>= 1.10.0', '< 1.12'
|
|
28
37
|
spec.add_runtime_dependency 'avro_schema_registry-client', '>= 0.4.0'
|
|
29
38
|
spec.add_runtime_dependency 'avro_turf'
|
|
30
39
|
spec.add_runtime_dependency 'ice_nine'
|
|
@@ -36,7 +45,7 @@ Gem::Specification.new do |spec|
|
|
|
36
45
|
spec.add_development_dependency 'rake', '~> 13.0'
|
|
37
46
|
spec.add_development_dependency 'rspec', '~> 3.8'
|
|
38
47
|
spec.add_development_dependency 'rspec_junit_formatter'
|
|
39
|
-
spec.add_development_dependency 'salsify_rubocop', '~>
|
|
48
|
+
spec.add_development_dependency 'salsify_rubocop', '~> 1.1.0'
|
|
40
49
|
spec.add_development_dependency 'simplecov'
|
|
41
50
|
spec.add_development_dependency 'webmock'
|
|
42
51
|
# For AvroSchemaRegistry::FakeServer
|
|
@@ -21,9 +21,7 @@ module Avromatic
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
unless index_of_schema
|
|
25
|
-
raise Avro::IO::AvroTypeError.new(writers_schema, datum)
|
|
26
|
-
end
|
|
24
|
+
raise Avro::IO::AvroTypeError.new(writers_schema, datum) unless index_of_schema
|
|
27
25
|
|
|
28
26
|
encoder.write_long(index_of_schema)
|
|
29
27
|
write_data(writers_schema.schemas[index_of_schema], datum, encoder)
|
data/lib/avromatic/messaging.rb
CHANGED
|
@@ -16,12 +16,10 @@ module Avromatic
|
|
|
16
16
|
# The first byte is MAGIC!!!
|
|
17
17
|
magic_byte = decoder.read(1)
|
|
18
18
|
|
|
19
|
-
if magic_byte != MAGIC_BYTE
|
|
20
|
-
raise "Expected data to begin with a magic byte, got `#{magic_byte.inspect}`"
|
|
21
|
-
end
|
|
19
|
+
raise "Expected data to begin with a magic byte, got `#{magic_byte.inspect}`" if magic_byte != MAGIC_BYTE
|
|
22
20
|
|
|
23
21
|
# The schema id is a 4-byte big-endian integer.
|
|
24
|
-
schema_id = decoder.read(4).
|
|
22
|
+
schema_id = decoder.read(4).unpack1('N')
|
|
25
23
|
|
|
26
24
|
writers_schema = @schemas_by_id.fetch(schema_id) do
|
|
27
25
|
schema_json = @registry.fetch(schema_id)
|
|
@@ -22,6 +22,7 @@ module Avromatic
|
|
|
22
22
|
|
|
23
23
|
class AttributeDefinition
|
|
24
24
|
attr_reader :name, :name_string, :setter_name, :type, :field, :default, :owner
|
|
25
|
+
|
|
25
26
|
delegate :serialize, to: :type
|
|
26
27
|
|
|
27
28
|
def initialize(owner:, field:, type:)
|
|
@@ -58,21 +59,31 @@ module Avromatic
|
|
|
58
59
|
def coerce(input)
|
|
59
60
|
type.coerce(input)
|
|
60
61
|
rescue Avromatic::Model::UnknownAttributeError => e
|
|
61
|
-
raise Avromatic::Model::CoercionError.new(
|
|
62
|
+
raise Avromatic::Model::CoercionError.new(
|
|
63
|
+
"Value for #{owner.name}##{name} could not be coerced to a #{type.name} " \
|
|
62
64
|
"because the following unexpected attributes were provided: #{e.unknown_attributes.join(', ')}. " \
|
|
63
65
|
"Only the following attributes are allowed: #{e.allowed_attributes.join(', ')}. " \
|
|
64
|
-
"Provided argument: #{input.inspect}"
|
|
66
|
+
"Provided argument: #{input.inspect}"
|
|
67
|
+
)
|
|
65
68
|
rescue StandardError
|
|
66
69
|
if type.input_classes && type.input_classes.none? { |input_class| input.is_a?(input_class) }
|
|
67
|
-
raise Avromatic::Model::CoercionError.new(
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
+
raise Avromatic::Model::CoercionError.new(
|
|
71
|
+
"Value for #{owner.name}##{name} could not be coerced to a #{type.name} " \
|
|
72
|
+
"because a #{input.class.name} was provided but expected a #{type.input_classes.map(&:name).to_sentence(
|
|
73
|
+
two_words_connector: ' or ', last_word_connector: ', or '
|
|
74
|
+
)}. " \
|
|
75
|
+
"Provided argument: #{input.inspect}"
|
|
76
|
+
)
|
|
70
77
|
elsif input.is_a?(Hash) && type.is_a?(Avromatic::Model::Types::UnionType)
|
|
71
|
-
raise Avromatic::Model::CoercionError.new(
|
|
72
|
-
"
|
|
78
|
+
raise Avromatic::Model::CoercionError.new(
|
|
79
|
+
"Value for #{owner.name}##{name} could not be coerced to a #{type.name} " \
|
|
80
|
+
"because no union member type matches the provided attributes: #{input.inspect}"
|
|
81
|
+
)
|
|
73
82
|
else
|
|
74
|
-
raise Avromatic::Model::CoercionError.new(
|
|
75
|
-
"
|
|
83
|
+
raise Avromatic::Model::CoercionError.new(
|
|
84
|
+
"Value for #{owner.name}##{name} could not be coerced to a #{type.name}. " \
|
|
85
|
+
"Provided argument: #{input.inspect}"
|
|
86
|
+
)
|
|
76
87
|
end
|
|
77
88
|
end
|
|
78
89
|
end
|
|
@@ -106,7 +117,8 @@ module Avromatic
|
|
|
106
117
|
unknown_attributes = (data.keys.map(&:to_s) - _attributes.keys.map(&:to_s)).sort
|
|
107
118
|
allowed_attributes = attribute_definitions.keys.map(&:to_s).sort
|
|
108
119
|
message = "Unexpected arguments for #{self.class.name}#initialize: #{unknown_attributes.join(', ')}. " \
|
|
109
|
-
"Only the following arguments are allowed: #{allowed_attributes.join(', ')}.
|
|
120
|
+
"Only the following arguments are allowed: #{allowed_attributes.join(', ')}. " \
|
|
121
|
+
"Provided arguments: #{data.inspect}"
|
|
110
122
|
raise Avromatic::Model::UnknownAttributeError.new(message, unknown_attributes: unknown_attributes,
|
|
111
123
|
allowed_attributes: allowed_attributes)
|
|
112
124
|
end
|
|
@@ -136,8 +148,8 @@ module Avromatic
|
|
|
136
148
|
begin
|
|
137
149
|
define_avro_attributes(key_avro_schema, generated_methods_module,
|
|
138
150
|
allow_optional: config.allow_optional_key_fields)
|
|
139
|
-
rescue OptionalFieldError =>
|
|
140
|
-
raise "Optional field '#{
|
|
151
|
+
rescue OptionalFieldError => e
|
|
152
|
+
raise "Optional field '#{e.field.name}' not allowed in key schema."
|
|
141
153
|
end
|
|
142
154
|
end
|
|
143
155
|
define_avro_attributes(avro_schema, generated_methods_module)
|
|
@@ -155,6 +167,7 @@ module Avromatic
|
|
|
155
167
|
conflicts =
|
|
156
168
|
(key_avro_field_names & value_avro_field_names).each_with_object([]) do |name, msgs|
|
|
157
169
|
next unless schema_fields_differ?(name)
|
|
170
|
+
|
|
158
171
|
msgs << "Field '#{name}' has a different type in each schema: "\
|
|
159
172
|
"value #{value_avro_fields_by_name[name]}, "\
|
|
160
173
|
"key #{key_avro_fields_by_name[name]}"
|
|
@@ -190,7 +203,11 @@ module Avromatic
|
|
|
190
203
|
|
|
191
204
|
# Add all generated methods to a module so they can be overridden
|
|
192
205
|
generated_methods_module.send(:define_method, field.name) { _attributes[symbolized_field_name] }
|
|
193
|
-
|
|
206
|
+
if FieldHelper.boolean?(field)
|
|
207
|
+
generated_methods_module.send(:define_method, "#{field.name}?") do
|
|
208
|
+
!!_attributes[symbolized_field_name]
|
|
209
|
+
end
|
|
210
|
+
end
|
|
194
211
|
|
|
195
212
|
generated_methods_module.send(:define_method, "#{field.name}=") do |value|
|
|
196
213
|
_attributes[symbolized_field_name] = attribute_definition.coerce(value)
|
|
@@ -24,7 +24,8 @@ module Avromatic
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
module ClassMethods
|
|
27
|
-
delegate :avro_schema, :value_avro_schema, :key_avro_schema, :mutable?, :immutable?,
|
|
27
|
+
delegate :avro_schema, :value_avro_schema, :key_avro_schema, :mutable?, :immutable?,
|
|
28
|
+
:avro_schema_subject, :value_avro_schema_subject, :key_avro_schema_subject, to: :config
|
|
28
29
|
|
|
29
30
|
def value_avro_field_names
|
|
30
31
|
@value_avro_field_names ||= value_avro_schema.fields.map(&:name).map(&:to_sym).freeze
|
|
@@ -68,6 +69,7 @@ module Avromatic
|
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
delegate :avro_schema, :value_avro_schema, :key_avro_schema,
|
|
72
|
+
:avro_schema_subject, :value_avro_schema_subject, :key_avro_schema_subject,
|
|
71
73
|
:value_avro_field_names, :key_avro_field_names,
|
|
72
74
|
:value_avro_field_references, :key_avro_field_references,
|
|
73
75
|
:mutable?, :immutable?,
|
|
@@ -7,7 +7,7 @@ module Avromatic
|
|
|
7
7
|
class Configuration
|
|
8
8
|
|
|
9
9
|
attr_reader :avro_schema, :key_avro_schema, :nested_models, :mutable,
|
|
10
|
-
:allow_optional_key_fields
|
|
10
|
+
:allow_optional_key_fields, :avro_schema_subject, :key_avro_schema_subject
|
|
11
11
|
alias_method :mutable?, :mutable
|
|
12
12
|
delegate :schema_store, to: Avromatic
|
|
13
13
|
|
|
@@ -17,23 +17,30 @@ module Avromatic
|
|
|
17
17
|
# @param options [Hash]
|
|
18
18
|
# @option options [Avro::Schema] :schema
|
|
19
19
|
# @option options [String, Symbol] :schema_name
|
|
20
|
+
# @option options [String, Symbol] :schema_subject
|
|
20
21
|
# @option options [Avro::Schema] :value_schema
|
|
21
22
|
# @option options [String, Symbol] :value_schema_name
|
|
23
|
+
# @option options [String, Symbol] :value_schema_subject
|
|
22
24
|
# @option options [Avro::Schema] :key_schema
|
|
23
25
|
# @option options [String, Symbol] :key_schema_name
|
|
26
|
+
# @option options [String, Symbol] :key_schema_subject
|
|
24
27
|
# @option options [Avromatic::ModelRegistry] :nested_models
|
|
25
28
|
# @option options [Boolean] :mutable, default false
|
|
26
29
|
# @option options [Boolean] :allow_optional_key_fields, default false
|
|
27
30
|
def initialize(**options)
|
|
28
31
|
@avro_schema = find_avro_schema(**options)
|
|
32
|
+
@avro_schema_subject = options[:schema_subject] || options[:value_schema_subject]
|
|
29
33
|
raise ArgumentError.new('value_schema(_name) or schema(_name) must be specified') unless avro_schema
|
|
34
|
+
|
|
30
35
|
@key_avro_schema = find_schema_by_option(:key_schema, **options)
|
|
36
|
+
@key_avro_schema_subject = options[:key_schema_subject]
|
|
31
37
|
@nested_models = options[:nested_models]
|
|
32
38
|
@mutable = options.fetch(:mutable, false)
|
|
33
39
|
@allow_optional_key_fields = options.fetch(:allow_optional_key_fields, false)
|
|
34
40
|
end
|
|
35
41
|
|
|
36
42
|
alias_method :value_avro_schema, :avro_schema
|
|
43
|
+
alias_method :value_avro_schema_subject, :avro_schema_subject
|
|
37
44
|
|
|
38
45
|
def immutable?
|
|
39
46
|
!mutable?
|
|
@@ -46,6 +53,7 @@ module Avromatic
|
|
|
46
53
|
(options[:schema] || options[:schema_name])
|
|
47
54
|
raise ArgumentError.new('Only one of value_schema(_name) and schema(_name) can be specified')
|
|
48
55
|
end
|
|
56
|
+
|
|
49
57
|
find_schema_by_option(:value_schema, **options) || find_schema_by_option(:schema, **options)
|
|
50
58
|
end
|
|
51
59
|
|
|
@@ -89,6 +89,7 @@ module Avromatic
|
|
|
89
89
|
message_key, message_value = extract_key_and_value(*args)
|
|
90
90
|
model_key = model_key_for_message(message_key, message_value)
|
|
91
91
|
raise UnexpectedKeyError.new(*model_key) unless model_map.key?(model_key)
|
|
92
|
+
|
|
92
93
|
[model_map[model_key], message_key, message_value]
|
|
93
94
|
end
|
|
94
95
|
|
|
@@ -106,7 +107,7 @@ module Avromatic
|
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
def extract_schema_id(data)
|
|
109
|
-
data[1..4].
|
|
110
|
+
data[1..4].unpack1('N')
|
|
110
111
|
end
|
|
111
112
|
|
|
112
113
|
def validate_magic_byte!(data)
|
|
@@ -118,6 +119,7 @@ module Avromatic
|
|
|
118
119
|
models.each_with_object(Hash.new) do |model, map|
|
|
119
120
|
key = model_key(model)
|
|
120
121
|
raise DuplicateKeyError.new(map[key], model) if map.key?(key) && !model.equal?(map[key])
|
|
122
|
+
|
|
121
123
|
map[key] = model
|
|
122
124
|
end
|
|
123
125
|
end
|
|
@@ -16,15 +16,18 @@ module Avromatic
|
|
|
16
16
|
def avro_message_value
|
|
17
17
|
avro_messaging.encode(
|
|
18
18
|
value_attributes_for_avro,
|
|
19
|
-
schema_name: value_avro_schema.fullname
|
|
19
|
+
schema_name: value_avro_schema.fullname,
|
|
20
|
+
subject: value_avro_schema_subject
|
|
20
21
|
)
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def avro_message_key
|
|
24
25
|
raise 'Model has no key schema' unless key_avro_schema
|
|
26
|
+
|
|
25
27
|
avro_messaging.encode(
|
|
26
28
|
key_attributes_for_avro,
|
|
27
|
-
schema_name: key_avro_schema.fullname
|
|
29
|
+
schema_name: key_avro_schema.fullname,
|
|
30
|
+
subject: key_avro_schema_subject
|
|
28
31
|
)
|
|
29
32
|
end
|
|
30
33
|
end
|
|
@@ -55,15 +58,15 @@ module Avromatic
|
|
|
55
58
|
|
|
56
59
|
module Registration
|
|
57
60
|
def register_schemas!
|
|
58
|
-
register_schema(key_avro_schema) if key_avro_schema
|
|
59
|
-
register_schema(value_avro_schema)
|
|
61
|
+
register_schema(key_avro_schema, subject: key_avro_schema_subject) if key_avro_schema
|
|
62
|
+
register_schema(value_avro_schema, subject: value_avro_schema_subject)
|
|
60
63
|
nil
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
private
|
|
64
67
|
|
|
65
|
-
def register_schema(schema)
|
|
66
|
-
avro_messaging.registry.register(schema.fullname, schema)
|
|
68
|
+
def register_schema(schema, subject: nil)
|
|
69
|
+
avro_messaging.registry.register(subject || schema.fullname, schema)
|
|
67
70
|
end
|
|
68
71
|
end
|
|
69
72
|
|
|
@@ -14,12 +14,14 @@ module Avromatic
|
|
|
14
14
|
def register!
|
|
15
15
|
return unless key_avro_schema.nil? && value_avro_schema.type_sym == :record
|
|
16
16
|
|
|
17
|
+
processed = Set.new
|
|
17
18
|
roots = [self]
|
|
18
19
|
until roots.empty?
|
|
19
20
|
model = roots.shift
|
|
20
|
-
|
|
21
|
+
# Avoid any nested model dependency cycles by ignoring already processed models
|
|
22
|
+
next unless processed.add?(model)
|
|
21
23
|
|
|
22
|
-
nested_models.
|
|
24
|
+
nested_models.ensure_registered_model(model)
|
|
23
25
|
roots.concat(model.referenced_model_classes)
|
|
24
26
|
end
|
|
25
27
|
end
|
|
@@ -36,6 +36,7 @@ module Avromatic
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
raise 'Model has no key schema' unless key_avro_schema
|
|
39
|
+
|
|
39
40
|
avro_raw_encode(key_attributes_for_avro, :key)
|
|
40
41
|
end
|
|
41
42
|
|
|
@@ -118,7 +119,7 @@ module Avromatic
|
|
|
118
119
|
# If supplied then the key_schema and value_schema are used as the writer's
|
|
119
120
|
# schema for the corresponding value. The model's schemas are always used
|
|
120
121
|
# as the reader's schemas.
|
|
121
|
-
def avro_raw_decode(key: nil,
|
|
122
|
+
def avro_raw_decode(value:, key: nil, key_schema: nil, value_schema: nil)
|
|
122
123
|
key_attributes = key && decode_avro_datum(key, key_schema, :key)
|
|
123
124
|
value_attributes = decode_avro_datum(value, value_schema, :value)
|
|
124
125
|
value_attributes.merge!(key_attributes) if key_attributes
|
|
@@ -150,10 +151,10 @@ module Avromatic
|
|
|
150
151
|
|
|
151
152
|
def datum_writer
|
|
152
153
|
@datum_writer ||= begin
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
hash = { value: datum_writer_class.new(value_avro_schema) }
|
|
155
|
+
hash[:key] = datum_writer_class.new(key_avro_schema) if key_avro_schema
|
|
156
|
+
hash
|
|
157
|
+
end
|
|
157
158
|
end
|
|
158
159
|
|
|
159
160
|
def datum_reader
|
|
@@ -11,6 +11,7 @@ module Avromatic
|
|
|
11
11
|
attr_reader :custom_type_configuration, :value_classes, :default_type
|
|
12
12
|
|
|
13
13
|
def initialize(custom_type_configuration:, default_type:)
|
|
14
|
+
super()
|
|
14
15
|
@custom_type_configuration = custom_type_configuration
|
|
15
16
|
@default_type = default_type
|
|
16
17
|
@deserializer = custom_type_configuration.deserializer || IDENTITY_PROC
|
|
@@ -27,7 +28,11 @@ module Avromatic
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def name
|
|
30
|
-
|
|
31
|
+
if custom_type_configuration.value_class
|
|
32
|
+
custom_type_configuration.value_class.name.to_s.freeze
|
|
33
|
+
else
|
|
34
|
+
default_type.name
|
|
35
|
+
end
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
def coerce(input)
|
|
@@ -59,10 +59,12 @@ module Avromatic
|
|
|
59
59
|
when :enum
|
|
60
60
|
Avromatic::Model::Types::EnumType.new(schema.symbols)
|
|
61
61
|
when :array
|
|
62
|
-
value_type = create(schema: schema.items, nested_models: nested_models,
|
|
62
|
+
value_type = create(schema: schema.items, nested_models: nested_models,
|
|
63
|
+
use_custom_types: use_custom_types)
|
|
63
64
|
Avromatic::Model::Types::ArrayType.new(value_type: value_type)
|
|
64
65
|
when :map
|
|
65
|
-
value_type = create(schema: schema.values, nested_models: nested_models,
|
|
66
|
+
value_type = create(schema: schema.values, nested_models: nested_models,
|
|
67
|
+
use_custom_types: use_custom_types)
|
|
66
68
|
Avromatic::Model::Types::MapType.new(
|
|
67
69
|
key_type: Avromatic::Model::Types::StringType.new,
|
|
68
70
|
value_type: value_type
|
|
@@ -97,8 +99,10 @@ module Avromatic
|
|
|
97
99
|
if nested_models.registered?(fullname)
|
|
98
100
|
nested_model = nested_models[fullname]
|
|
99
101
|
unless schema_fingerprint(schema) == schema_fingerprint(nested_model.avro_schema)
|
|
100
|
-
raise "The #{nested_model.name} model is already registered with an incompatible version of the
|
|
102
|
+
raise "The #{nested_model.name} model is already registered with an incompatible version of the " \
|
|
103
|
+
"#{schema.fullname} schema"
|
|
101
104
|
end
|
|
105
|
+
|
|
102
106
|
nested_model
|
|
103
107
|
else
|
|
104
108
|
Avromatic::Model.model(schema: schema, nested_models: nested_models)
|
|
@@ -10,6 +10,7 @@ module Avromatic
|
|
|
10
10
|
attr_reader :member_types, :value_classes, :input_classes
|
|
11
11
|
|
|
12
12
|
def initialize(member_types:)
|
|
13
|
+
super()
|
|
13
14
|
@member_types = member_types
|
|
14
15
|
@value_classes = member_types.flat_map(&:value_classes)
|
|
15
16
|
@input_classes = member_types.flat_map(&:input_classes).uniq
|
|
@@ -31,9 +32,7 @@ module Avromatic
|
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
if result.nil?
|
|
35
|
-
raise ArgumentError.new("Could not coerce '#{input.inspect}' to #{name}")
|
|
36
|
-
end
|
|
35
|
+
raise ArgumentError.new("Could not coerce '#{input.inspect}' to #{name}") if result.nil?
|
|
37
36
|
|
|
38
37
|
result
|
|
39
38
|
end
|
|
@@ -24,8 +24,10 @@ module Avromatic
|
|
|
24
24
|
|
|
25
25
|
def register(model)
|
|
26
26
|
raise 'models with a key schema are not supported' if model.key_avro_schema
|
|
27
|
+
|
|
27
28
|
name = model_fullname(model)
|
|
28
29
|
raise "'#{name}' has already been registered" if registered?(name)
|
|
30
|
+
|
|
29
31
|
@hash[name] = model
|
|
30
32
|
end
|
|
31
33
|
|
|
@@ -42,8 +44,11 @@ module Avromatic
|
|
|
42
44
|
def ensure_registered_model(model)
|
|
43
45
|
name = model_fullname(model)
|
|
44
46
|
if registered?(name)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
existing_model = fetch(name)
|
|
48
|
+
unless existing_model.equal?(model)
|
|
49
|
+
raise "Attempted to replace existing Avromatic model #{model_debug_name(existing_model)} with new model " \
|
|
50
|
+
"#{model_debug_name(model)} as '#{name}'. Perhaps '#{model_debug_name(model)}' needs to be eager loaded " \
|
|
51
|
+
'via the Avromatic eager_load_models setting?'
|
|
47
52
|
end
|
|
48
53
|
else
|
|
49
54
|
register(model)
|
|
@@ -65,5 +70,11 @@ module Avromatic
|
|
|
65
70
|
|
|
66
71
|
value.start_with?('.') ? value.from(1) : value
|
|
67
72
|
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def model_debug_name(model)
|
|
77
|
+
model.name || model.to_s
|
|
78
|
+
end
|
|
68
79
|
end
|
|
69
80
|
end
|
data/lib/avromatic/rspec.rb
CHANGED
data/lib/avromatic/version.rb
CHANGED
data/lib/avromatic.rb
CHANGED
|
@@ -34,6 +34,7 @@ module Avromatic
|
|
|
34
34
|
|
|
35
35
|
def self.build_schema_registry
|
|
36
36
|
raise 'Avromatic must be configured with a registry_url' unless registry_url
|
|
37
|
+
|
|
37
38
|
if use_schema_fingerprint_lookup
|
|
38
39
|
AvroSchemaRegistry::CachedClient.new(
|
|
39
40
|
AvroSchemaRegistry::Client.new(registry_url, logger: logger)
|
|
@@ -45,8 +46,13 @@ module Avromatic
|
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
49
|
+
def self.build_schema_registry!
|
|
50
|
+
self.schema_registry = build_schema_registry
|
|
51
|
+
end
|
|
52
|
+
|
|
48
53
|
def self.build_messaging
|
|
49
54
|
raise 'Avromatic must be configured with a schema_store' unless schema_store
|
|
55
|
+
|
|
50
56
|
Avromatic::Messaging.new(
|
|
51
57
|
registry: schema_registry || build_schema_registry,
|
|
52
58
|
schema_store: schema_store,
|
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:
|
|
4
|
+
version: 4.1.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: 2022-02-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|
|
@@ -19,7 +19,7 @@ dependencies:
|
|
|
19
19
|
version: '5.2'
|
|
20
20
|
- - "<"
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: '
|
|
22
|
+
version: '7.1'
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -29,7 +29,7 @@ dependencies:
|
|
|
29
29
|
version: '5.2'
|
|
30
30
|
- - "<"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '7.1'
|
|
33
33
|
- !ruby/object:Gem::Dependency
|
|
34
34
|
name: activesupport
|
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
version: '5.2'
|
|
40
40
|
- - "<"
|
|
41
41
|
- !ruby/object:Gem::Version
|
|
42
|
-
version: '
|
|
42
|
+
version: '7.1'
|
|
43
43
|
type: :runtime
|
|
44
44
|
prerelease: false
|
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -49,27 +49,27 @@ dependencies:
|
|
|
49
49
|
version: '5.2'
|
|
50
50
|
- - "<"
|
|
51
51
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: '
|
|
52
|
+
version: '7.1'
|
|
53
53
|
- !ruby/object:Gem::Dependency
|
|
54
54
|
name: avro
|
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
|
56
56
|
requirements:
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 1.
|
|
59
|
+
version: 1.10.0
|
|
60
60
|
- - "<"
|
|
61
61
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: '1.
|
|
62
|
+
version: '1.12'
|
|
63
63
|
type: :runtime
|
|
64
64
|
prerelease: false
|
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
66
66
|
requirements:
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 1.
|
|
69
|
+
version: 1.10.0
|
|
70
70
|
- - "<"
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
|
-
version: '1.
|
|
72
|
+
version: '1.12'
|
|
73
73
|
- !ruby/object:Gem::Dependency
|
|
74
74
|
name: avro_schema_registry-client
|
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -216,14 +216,14 @@ dependencies:
|
|
|
216
216
|
requirements:
|
|
217
217
|
- - "~>"
|
|
218
218
|
- !ruby/object:Gem::Version
|
|
219
|
-
version:
|
|
219
|
+
version: 1.1.0
|
|
220
220
|
type: :development
|
|
221
221
|
prerelease: false
|
|
222
222
|
version_requirements: !ruby/object:Gem::Requirement
|
|
223
223
|
requirements:
|
|
224
224
|
- - "~>"
|
|
225
225
|
- !ruby/object:Gem::Version
|
|
226
|
-
version:
|
|
226
|
+
version: 1.1.0
|
|
227
227
|
- !ruby/object:Gem::Dependency
|
|
228
228
|
name: simplecov
|
|
229
229
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -274,6 +274,7 @@ extensions: []
|
|
|
274
274
|
extra_rdoc_files: []
|
|
275
275
|
files:
|
|
276
276
|
- ".circleci/config.yml"
|
|
277
|
+
- ".github/CODEOWNERS"
|
|
277
278
|
- ".gitignore"
|
|
278
279
|
- ".overcommit.yml"
|
|
279
280
|
- ".rspec"
|
|
@@ -293,9 +294,9 @@ files:
|
|
|
293
294
|
- gemfiles/avro1_10_rails5_2.gemfile
|
|
294
295
|
- gemfiles/avro1_10_rails6_0.gemfile
|
|
295
296
|
- gemfiles/avro1_10_rails6_1.gemfile
|
|
296
|
-
- gemfiles/
|
|
297
|
-
- gemfiles/
|
|
298
|
-
- gemfiles/
|
|
297
|
+
- gemfiles/avro1_10_rails7_0.gemfile
|
|
298
|
+
- gemfiles/avro1_11_rails6_1.gemfile
|
|
299
|
+
- gemfiles/avro1_11_rails7_0.gemfile
|
|
299
300
|
- lib/avromatic.rb
|
|
300
301
|
- lib/avromatic/io.rb
|
|
301
302
|
- lib/avromatic/io/datum_reader.rb
|
|
@@ -345,7 +346,9 @@ files:
|
|
|
345
346
|
homepage: https://github.com/salsify/avromatic.git
|
|
346
347
|
licenses:
|
|
347
348
|
- MIT
|
|
348
|
-
metadata:
|
|
349
|
+
metadata:
|
|
350
|
+
allowed_push_host: https://rubygems.org
|
|
351
|
+
rubygems_mfa_required: 'true'
|
|
349
352
|
post_install_message:
|
|
350
353
|
rdoc_options: []
|
|
351
354
|
require_paths:
|
|
@@ -354,14 +357,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
354
357
|
requirements:
|
|
355
358
|
- - ">="
|
|
356
359
|
- !ruby/object:Gem::Version
|
|
357
|
-
version: '2.
|
|
360
|
+
version: '2.7'
|
|
358
361
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
359
362
|
requirements:
|
|
360
363
|
- - ">="
|
|
361
364
|
- !ruby/object:Gem::Version
|
|
362
365
|
version: '0'
|
|
363
366
|
requirements: []
|
|
364
|
-
rubygems_version: 3.
|
|
367
|
+
rubygems_version: 3.2.22
|
|
365
368
|
signing_key:
|
|
366
369
|
specification_version: 4
|
|
367
370
|
summary: Generate Ruby models from Avro schemas
|