avromatic 0.9.0.rc1 → 0.9.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +2 -1
- data/README.md +71 -1
- data/lib/avromatic.rb +3 -1
- data/lib/avromatic/model/attributes.rb +1 -8
- data/lib/avromatic/model/builder.rb +2 -0
- data/lib/avromatic/model/configurable.rb +4 -0
- data/lib/avromatic/model/configuration.rb +3 -2
- data/lib/avromatic/model/nested_models.rb +29 -0
- data/lib/avromatic/model/value_object.rb +0 -1
- data/lib/avromatic/model_registry.rb +45 -0
- data/lib/avromatic/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 349bd4de9cfdaffd91c737ef6330d9b9d20ff8ed
|
4
|
+
data.tar.gz: cc1b8f6f5275cea982902ce4ae5d055e504a69a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1d4474e40c761995be5512600d9e84f6f743501b9f496901900686058cd4e5190c78712723125bf66d3e7a571cc786ea579fcc91021bcf35506a88f7ef69be7
|
7
|
+
data.tar.gz: 72e71deb56ff37c1f85a4c11b04d37f2672cc0d3b406ee574180257f690a6f7d057fe53250cfbd513610740120fe7e191d7d73970f7140be4c6b7b16d711c122
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# avromatic changelog
|
2
2
|
|
3
3
|
## v0.9.0 (unreleased)
|
4
|
-
- Add support for more than one non-null type in a union.
|
4
|
+
- Experimental: Add support for more than one non-null type in a union.
|
5
|
+
- Allow nested models to be referenced and reused.
|
5
6
|
- Fix the serialization of nested complex types.
|
6
7
|
|
7
8
|
## v0.8.0
|
data/README.md
CHANGED
@@ -37,7 +37,11 @@ Or install it yourself as:
|
|
37
37
|
returns an `Avro::Schema` object. An `AvroTurf::SchemaStore` can be used.
|
38
38
|
The `schema_store` is unnecessary if models are generated directly from
|
39
39
|
`Avro::Schema` objects. See [Models](#models).
|
40
|
-
|
40
|
+
* **nested_models**: An optional [ModelRegistry](https://github.com/salsify/avromatic/blob/master/lib/avromatic/model_registry.rb)
|
41
|
+
that is used to store, by full schema name, the generated models that are
|
42
|
+
embedded within top-level models. By default a new `Avromatic::ModelRegistry`
|
43
|
+
is created.
|
44
|
+
|
41
45
|
#### Using a Schema Registry/Messaging API
|
42
46
|
|
43
47
|
The configuration options below are required when using a schema registry
|
@@ -109,6 +113,72 @@ constant:
|
|
109
113
|
MyModel = Avromatic::Model.model(schema_name :my_model)
|
110
114
|
```
|
111
115
|
|
116
|
+
#### Experimental: Union Support
|
117
|
+
|
118
|
+
Avromatic contains experimental support for unions containing more than one
|
119
|
+
non-null member type. This feature is experimental because Virtus attributes
|
120
|
+
may attempt to coerce between types too aggressively.
|
121
|
+
|
122
|
+
For now, if a union contains [nested models](#nested-models) then it is
|
123
|
+
recommended that you assign model instances.
|
124
|
+
|
125
|
+
Some combination of the ordering of member types in the union and relying on
|
126
|
+
model validation may be required so that the correct member is selected,
|
127
|
+
especially when deserializing from Avro.
|
128
|
+
|
129
|
+
In the future, the type coercion used in the gem will be replaced to better
|
130
|
+
support the union use case.
|
131
|
+
|
132
|
+
#### Nested Models
|
133
|
+
|
134
|
+
Nested models are models that are embedded within top-level models generated
|
135
|
+
using Avromatic. Normally these nested models are automatically generated.
|
136
|
+
|
137
|
+
By default, nested models are stored in `Avromatic.nested_models`. This is an
|
138
|
+
`Avromatic::ModelRegistry` instance that provides access to previously generated
|
139
|
+
nested models by the full name of their Avro schema.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
Avromatic.nested_models['com.my_company.test.example']
|
143
|
+
#=> <model class>
|
144
|
+
```
|
145
|
+
|
146
|
+
The `ModelRegistry` can be customized to remove a namespace prefix:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
Avromatic.nested_models =
|
150
|
+
Avromatic::ModelRegistry.new(remove_namespace_prefix: 'com.my_company'
|
151
|
+
```
|
152
|
+
|
153
|
+
The `:remove_namespace_prefix` value can be a string or a regexp.
|
154
|
+
|
155
|
+
By default, top-level generated models reuse `Avromatic.nested_models`. This
|
156
|
+
allows nested models to be shared across different generated models.
|
157
|
+
A `:nested_models` option can be specified when generating a model. This allows
|
158
|
+
the reuse of nested models to be scoped:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
Avromatic::Model.model(schema_name, :my_model
|
162
|
+
nested_models: ModelRegistry.new)
|
163
|
+
```
|
164
|
+
|
165
|
+
It is also possible to explicitly generate a nested model that should be reused
|
166
|
+
and add it to the registry. This is useful when the nested model is extended:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class UsefulSubrecord
|
170
|
+
include Avromatic::Model.build(schema_name: 'useful_subrecord')
|
171
|
+
|
172
|
+
def do_something_custom
|
173
|
+
...
|
174
|
+
end
|
175
|
+
end
|
176
|
+
Avromatic.nested_models.register(UsefulSubrecord)
|
177
|
+
```
|
178
|
+
|
179
|
+
With Rails, it may be necessary to perform this explicit registration in an
|
180
|
+
initializer so that lazy class loading works correctly in development.
|
181
|
+
|
112
182
|
#### Custom Types
|
113
183
|
|
114
184
|
Custom types can be configured for fields of named types (record, enum, fixed).
|
data/lib/avromatic.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
require 'avromatic/version'
|
2
2
|
require 'avromatic/model'
|
3
|
+
require 'avromatic/model_registry'
|
3
4
|
require 'avro_turf'
|
4
5
|
require 'avro_turf/messaging'
|
5
6
|
|
6
7
|
module Avromatic
|
7
8
|
class << self
|
8
9
|
attr_accessor :schema_registry, :registry_url, :schema_store, :logger,
|
9
|
-
:messaging, :type_registry
|
10
|
+
:messaging, :type_registry, :nested_models
|
10
11
|
|
11
12
|
delegate :register_type, to: :type_registry
|
12
13
|
end
|
13
14
|
|
15
|
+
self.nested_models = ModelRegistry.new
|
14
16
|
self.logger = Logger.new($stdout)
|
15
17
|
self.type_registry = Avromatic::Model::TypeRegistry.new
|
16
18
|
|
@@ -126,14 +126,7 @@ module Avromatic
|
|
126
126
|
when :union
|
127
127
|
union_field_class(field_type)
|
128
128
|
when :record
|
129
|
-
|
130
|
-
# A hash of generated models should be kept by name for reuse.
|
131
|
-
Avromatic::Model.model(schema: field_type).tap do |record_class|
|
132
|
-
# Register the generated model with Axiom to prevent it being
|
133
|
-
# treated as a BasicObject.
|
134
|
-
# See https://github.com/solnic/virtus/issues/284#issuecomment-56405137
|
135
|
-
Axiom::Types::Object.new { primitive(record_class) }
|
136
|
-
end
|
129
|
+
build_nested_model(field_type)
|
137
130
|
else
|
138
131
|
raise "Unsupported type #{field_type}"
|
139
132
|
end
|
@@ -4,6 +4,7 @@ require 'active_model'
|
|
4
4
|
require 'avromatic/model/configuration'
|
5
5
|
require 'avromatic/model/value_object'
|
6
6
|
require 'avromatic/model/configurable'
|
7
|
+
require 'avromatic/model/nested_models'
|
7
8
|
require 'avromatic/model/attribute/union'
|
8
9
|
require 'avromatic/model/attributes'
|
9
10
|
require 'avromatic/model/attribute/record'
|
@@ -42,6 +43,7 @@ module Avromatic
|
|
42
43
|
ActiveModel::Validations,
|
43
44
|
Virtus.value_object,
|
44
45
|
Avromatic::Model::Configurable,
|
46
|
+
Avromatic::Model::NestedModels,
|
45
47
|
Avromatic::Model::Attributes,
|
46
48
|
Avromatic::Model::ValueObject,
|
47
49
|
Avromatic::Model::RawSerialization,
|
@@ -4,7 +4,7 @@ module Avromatic
|
|
4
4
|
# This class holds configuration for a model built from Avro schema(s).
|
5
5
|
class Configuration
|
6
6
|
|
7
|
-
attr_reader :avro_schema, :key_avro_schema
|
7
|
+
attr_reader :avro_schema, :key_avro_schema, :nested_models
|
8
8
|
delegate :schema_store, to: Avromatic
|
9
9
|
|
10
10
|
# Either schema(_name) or value_schema(_name), but not both, must be
|
@@ -17,10 +17,12 @@ module Avromatic
|
|
17
17
|
# @option options [String, Symbol] :value_schema_name
|
18
18
|
# @option options [Avro::Schema] :key_schema
|
19
19
|
# @option options [String, Symbol] :key_schema_name
|
20
|
+
# @option options [Avromatic::ModelRegistry] :nested_models
|
20
21
|
def initialize(**options)
|
21
22
|
@avro_schema = find_avro_schema(**options)
|
22
23
|
raise ArgumentError.new('value_schema(_name) or schema(_name) must be specified') unless avro_schema
|
23
24
|
@key_avro_schema = find_schema_by_option(:key_schema, **options)
|
25
|
+
@nested_models = options[:nested_models]
|
24
26
|
end
|
25
27
|
|
26
28
|
alias_method :value_avro_schema, :avro_schema
|
@@ -39,7 +41,6 @@ module Avromatic
|
|
39
41
|
schema_name_option = :"#{option_name}_name"
|
40
42
|
options[option_name] ||
|
41
43
|
(options[schema_name_option] && schema_store.find(options[schema_name_option]))
|
42
|
-
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'active_support/inflector/methods'
|
2
|
+
|
3
|
+
module Avromatic
|
4
|
+
module Model
|
5
|
+
# This module handles integration with the ModelRegistry and support
|
6
|
+
# for nested model reuse.
|
7
|
+
module NestedModels
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def build_nested_model(schema)
|
12
|
+
fullname = schema.fullname
|
13
|
+
|
14
|
+
if nested_models.registered?(fullname)
|
15
|
+
nested_models[fullname]
|
16
|
+
else
|
17
|
+
nested_model = Avromatic::Model.model(schema: schema,
|
18
|
+
nested_models: nested_models)
|
19
|
+
# Register the generated model with Axiom to prevent it being
|
20
|
+
# treated as a BasicObject.
|
21
|
+
# See https://github.com/solnic/virtus/issues/284#issuecomment-56405137
|
22
|
+
Axiom::Types::Object.new { primitive(nested_model) }
|
23
|
+
nested_models.register(nested_model)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'active_support/core_ext/string/access'
|
2
|
+
|
3
|
+
module Avromatic
|
4
|
+
# The ModelRegistry class is used to store and fetch nested models by
|
5
|
+
# their fullname. An optional namespace prefix can be removed from the full
|
6
|
+
# name that is used to store and fetch models.
|
7
|
+
class ModelRegistry
|
8
|
+
|
9
|
+
def initialize(remove_namespace_prefix: nil)
|
10
|
+
@prefix = remove_namespace_prefix
|
11
|
+
@hash = Hash.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](fullname)
|
15
|
+
@hash.fetch(fullname)
|
16
|
+
end
|
17
|
+
|
18
|
+
def register(model)
|
19
|
+
raise 'models with a key schema are not supported' if model.key_avro_schema
|
20
|
+
name = model.avro_schema.fullname
|
21
|
+
name = remove_prefix(name) if @prefix
|
22
|
+
@hash[name] = model
|
23
|
+
end
|
24
|
+
|
25
|
+
def registered?(fullname)
|
26
|
+
@hash.key?(fullname)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def remove_prefix(name)
|
32
|
+
value =
|
33
|
+
case @prefix
|
34
|
+
when String
|
35
|
+
name.from(@prefix.length) if name.start_with?(@prefix)
|
36
|
+
when Regexp
|
37
|
+
name.sub(@prefix, '')
|
38
|
+
else
|
39
|
+
raise "unsupported `remove_namespace_prefix` value: #{@prefix}"
|
40
|
+
end
|
41
|
+
|
42
|
+
value.start_with?('.') ? value.from(1) : value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
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: 0.9.0.
|
4
|
+
version: 0.9.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Salsify Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: avro
|
@@ -257,11 +257,13 @@ files:
|
|
257
257
|
- lib/avromatic/model/logical_types.rb
|
258
258
|
- lib/avromatic/model/message_decoder.rb
|
259
259
|
- lib/avromatic/model/messaging_serialization.rb
|
260
|
+
- lib/avromatic/model/nested_models.rb
|
260
261
|
- lib/avromatic/model/null_custom_type.rb
|
261
262
|
- lib/avromatic/model/passthrough_serializer.rb
|
262
263
|
- lib/avromatic/model/raw_serialization.rb
|
263
264
|
- lib/avromatic/model/type_registry.rb
|
264
265
|
- lib/avromatic/model/value_object.rb
|
266
|
+
- lib/avromatic/model_registry.rb
|
265
267
|
- lib/avromatic/railtie.rb
|
266
268
|
- lib/avromatic/rspec.rb
|
267
269
|
- lib/avromatic/version.rb
|