avromatic 2.0.0 → 2.0.1

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: 25174d8c67bde4e8a9d7a53dc357ed72db2e1faa08bbf8945d1f93dd69c46942
4
- data.tar.gz: b0b2fce3ddb92a463fade05c2cb29cdadd60037357432c99ece5f892d3b54f45
3
+ metadata.gz: 281093ac30d6f1f5bf7fa5949466ce74b2223968db553e15e473e09c81fc574d
4
+ data.tar.gz: 0a89d649b7b86d8a1cc55dba25af9dfdab2f7789f2c4daa996b0dab6ba7fd210
5
5
  SHA512:
6
- metadata.gz: 6566f793b850761a3d7dc2fa88b403c20ab8402e57d062322843038b473c7daf98b5e2484107063dbc2e9014919fabe1b5ac2e140c8e78f81a552356cbf8c5a2
7
- data.tar.gz: 25071f9751683a41bb23fc7932e8570b663c87e903a4ad5d953da863e92c47f0e464355278ec712af41490b7abdc6ac6f11f004472ef3b802e274c8ddf83f503
6
+ metadata.gz: e13e24a119085b1bf8e6f31d83cda3a8d99092026006601a48d21c29516eefb511d1cccaa3080f346bb91b91397433787638b13ee8e2980286b8c06cf0300d07
7
+ data.tar.gz: 8151877e50ab9e2ca498ea52f990c3fce6e5a87a31972c09cea6bbe1c5654265f52e2a7c5dd577d934b0fdd1b8adf7eee1123481333714c4dedef42afd5d83e4
@@ -1,6 +1,11 @@
1
1
  # avromatic changelog
2
2
 
3
- ## v2.0.0 (unreleased)
3
+ ## v2.0.1
4
+ - Allow generated model attribute accessors to be overridden. This was a regression in Avromatic 2.0.0.
5
+ - Ensure that timestamp-millis are coerced when the number of microseconds is divisible by 1,000 but the
6
+ number of nanoseconds is not divisible by 1,000,000.
7
+
8
+ ## v2.0.0
4
9
  - Remove [virtus](https://github.com/solnic/virtus) dependency resulting in a 3x performance improvement in model instantation and 1.4x - 2.0x performance improvement in Avro serialization and Avromatic code simplification.
5
10
  - Raise `Avromatic::Model::CoercionError` when attribute values can't be coerced to the target type in model constructors and attribute setters. Previously coercion errors weren't detected until Avro serialization or an explicit call to `valid?`.
6
11
  - Prevent model instances from being constructed with unknown attributes. Previously unknown attributes were ignored.
data/README.md CHANGED
@@ -8,8 +8,8 @@
8
8
  `Avromatic` generates Ruby models from [Avro](http://avro.apache.org/) schemas
9
9
  and provides utilities to encode and decode them.
10
10
 
11
- **This README reflects unreleased changes in Avromatic 2.0. Please see the
12
- [1-0-stable](https://github.com/salsify/avromatic/blob/1-0-stable/README.md) branch for the latest stable release.**
11
+ **This README reflects Avromatic 2.0. Please see the
12
+ [1-0-stable](https://github.com/salsify/avromatic/blob/1-0-stable/README.md) branch for Avromatic 1.0.**
13
13
 
14
14
  ## Installation
15
15
 
@@ -21,7 +21,7 @@ module Avromatic
21
21
  end
22
22
 
23
23
  class AttributeDefinition
24
- attr_reader :name, :type, :field, :default, :owner
24
+ attr_reader :name, :setter_name, :type, :field, :default, :owner
25
25
  delegate :serialize, to: :type
26
26
 
27
27
  def initialize(owner:, field:, type:)
@@ -29,6 +29,7 @@ module Avromatic
29
29
  @field = field
30
30
  @type = type
31
31
  @name = field.name.to_sym
32
+ @setter_name = "#{field.name}=".to_sym
32
33
  @default = if field.default == :no_default
33
34
  nil
34
35
  elsif field.default.duplicable?
@@ -77,13 +78,13 @@ module Avromatic
77
78
  if data.include?(attribute_name)
78
79
  valid_keys << attribute_name
79
80
  value = data.fetch(attribute_name)
80
- _attributes[attribute_name] = attribute_definition.coerce(value)
81
+ send(attribute_definition.setter_name, value)
81
82
  elsif data.include?(attribute_name.to_s)
82
83
  valid_keys << attribute_name
83
84
  value = data[attribute_name.to_s]
84
- _attributes[attribute_name] = attribute_definition.coerce(value)
85
+ send(attribute_definition.setter_name, value)
85
86
  elsif !attributes.include?(attribute_name)
86
- _attributes[attribute_name] = attribute_definition.default
87
+ send(attribute_definition.setter_name, attribute_definition.default)
87
88
  end
88
89
  end
89
90
 
@@ -111,7 +112,7 @@ module Avromatic
111
112
  end
112
113
 
113
114
  module ClassMethods
114
- def add_avro_fields
115
+ def add_avro_fields(generated_methods_module)
115
116
  # models are registered in Avromatic.nested_models at this point to
116
117
  # ensure that they are available as fields for recursive models.
117
118
  register!
@@ -119,13 +120,13 @@ module Avromatic
119
120
  if key_avro_schema
120
121
  check_for_field_conflicts!
121
122
  begin
122
- define_avro_attributes(key_avro_schema,
123
+ define_avro_attributes(key_avro_schema, generated_methods_module,
123
124
  allow_optional: config.allow_optional_key_fields)
124
125
  rescue OptionalFieldError => ex
125
126
  raise "Optional field '#{ex.field.name}' not allowed in key schema."
126
127
  end
127
128
  end
128
- define_avro_attributes(avro_schema)
129
+ define_avro_attributes(avro_schema, generated_methods_module)
129
130
  end
130
131
 
131
132
  private
@@ -151,7 +152,7 @@ module Avromatic
151
152
  value_avro_fields_by_name[name].to_avro
152
153
  end
153
154
 
154
- def define_avro_attributes(schema, allow_optional: true)
155
+ def define_avro_attributes(schema, generated_methods_module, allow_optional: true)
155
156
  if schema.type_sym != :record
156
157
  raise "Unsupported schema type '#{schema.type_sym}', only 'record' schemas are supported."
157
158
  end
@@ -163,33 +164,25 @@ module Avromatic
163
164
  attribute_definition = AttributeDefinition.new(
164
165
  owner: self,
165
166
  field: field,
166
- type: create_type(field)
167
+ type: Avromatic::Model::Types::TypeFactory.create(schema: field.type, nested_models: nested_models)
167
168
  )
168
169
  attribute_definitions[symbolized_field_name] = attribute_definition
169
170
 
170
- define_method(field.name) { _attributes[symbolized_field_name] }
171
- define_method("#{field.name}?") { !!_attributes[symbolized_field_name] } if boolean?(field)
171
+ # Add all generated methods to a module so they can be overridden
172
+ generated_methods_module.send(:define_method, field.name) { _attributes[symbolized_field_name] }
173
+ generated_methods_module.send(:define_method, "#{field.name}?") { !!_attributes[symbolized_field_name] } if FieldHelper.boolean?(field)
172
174
 
173
- define_method("#{field.name}=") do |value|
175
+ generated_methods_module.send(:define_method, "#{field.name}=") do |value|
174
176
  _attributes[symbolized_field_name] = attribute_definitions[symbolized_field_name].coerce(value)
175
177
  end
176
178
 
177
179
  unless config.mutable # rubocop:disable Style/Next
178
- private("#{field.name}=")
179
- define_method(:clone) { self }
180
- define_method(:dup) { self }
180
+ generated_methods_module.send(:private, "#{field.name}=")
181
+ generated_methods_module.send(:define_method, :clone) { self }
182
+ generated_methods_module.send(:define_method, :dup) { self }
181
183
  end
182
184
  end
183
185
  end
184
-
185
- def boolean?(field)
186
- field.type.type_sym == :boolean ||
187
- (FieldHelper.optional?(field) && field.type.schemas.last.type_sym == :boolean)
188
- end
189
-
190
- def create_type(field)
191
- Avromatic::Model::Types::TypeFactory.create(schema: field.type, nested_models: nested_models)
192
- end
193
186
  end
194
187
 
195
188
  end
@@ -22,7 +22,7 @@ module Avromatic
22
22
  attr_reader :mod, :config
23
23
 
24
24
  # For options see Avromatic::Model.build
25
- def self.model(**options)
25
+ def self.model(**options, &block)
26
26
  Class.new do
27
27
  include Avromatic::Model::Builder.new(**options).mod
28
28
 
@@ -30,6 +30,8 @@ module Avromatic
30
30
  def self.name
31
31
  super || (@name ||= config.avro_schema.name.classify)
32
32
  end
33
+
34
+ class_eval(&block) if block
33
35
  end
34
36
  end
35
37
 
@@ -55,18 +57,14 @@ module Avromatic
55
57
  private
56
58
 
57
59
  def define_included_method
58
- with_builder do |builder|
59
- mod.define_singleton_method(:included) do |model_class|
60
- model_class.include(*builder.inclusions)
61
- model_class.config = builder.config
62
- model_class.add_avro_fields
63
- end
60
+ local_mod = mod
61
+ local_builder = self
62
+ mod.define_singleton_method(:included) do |model_class|
63
+ model_class.include(*local_builder.inclusions)
64
+ model_class.config = local_builder.config
65
+ model_class.add_avro_fields(local_mod)
64
66
  end
65
67
  end
66
-
67
- def with_builder
68
- yield(self)
69
- end
70
68
  end
71
69
  end
72
70
  end
@@ -15,6 +15,11 @@ module Avromatic
15
15
  def required?(field)
16
16
  !optional?(field)
17
17
  end
18
+
19
+ def boolean?(field)
20
+ field.type.type_sym == :boolean ||
21
+ (FieldHelper.optional?(field) && field.type.schemas.last.type_sym == :boolean)
22
+ end
18
23
  end
19
24
  end
20
25
  end
@@ -16,7 +16,7 @@ module Avromatic
16
16
  private
17
17
 
18
18
  def truncated?(value)
19
- value.nsec % 1000 == 0
19
+ value.nsec % 1_000 == 0
20
20
  end
21
21
 
22
22
  def coerce_time(input)
@@ -16,7 +16,7 @@ module Avromatic
16
16
  private
17
17
 
18
18
  def truncated?(value)
19
- value.usec % 1000 == 0
19
+ value.nsec % 1_000_000 == 0
20
20
  end
21
21
 
22
22
  def coerce_time(input)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Avromatic
4
- VERSION = '2.0.0'
4
+ VERSION = '2.0.1'
5
5
  end
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.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Salsify Engineering
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-22 00:00:00.000000000 Z
11
+ date: 2018-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel