avromatic 0.9.0.rc6 → 0.9.0.rc7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba5443f9bd3883ce2b78d8a27782069b8b6f9387
4
- data.tar.gz: 010950770be1bea00cc8aa4143e8124667d00379
3
+ metadata.gz: 4b3788ff5afb0346f35c6835573445dcd27a1f73
4
+ data.tar.gz: 8a85631271bb0e8203d5b0bf848525e59360c435
5
5
  SHA512:
6
- metadata.gz: 353f84a00f41772c41d4b9889f3610750b66364151d051ab315429f3f5b77a353376f70cd2101c896e043b486a4df22f20e7467158ef29eb5c47d72d9109444b
7
- data.tar.gz: f86f38a32fad99f98f8c697119cc0b4c4b2a8f4e76264b6e8755d8a148b2ee3a3076d19b51c16ca5fefaeb07ff450c3e1b1376dbd3836719648bd353699689dd
6
+ metadata.gz: 67b0159ac2b5c54e4e462b00e022e6a7482dd9b84f412184fec923bd6aadd772b7711320296836653f033ad22de298f894ad066819bff1ed6ce0216bb4335c7d
7
+ data.tar.gz: 81051a75c091280a29d4f70cfa3d7e28a5bfed9743effee953d4f2c11510f7fcce615a02cb4d5c10a1e96e80d3c4a085f613e34a4f40cae9f2be98157649ecea
data/CHANGELOG.md CHANGED
@@ -7,8 +7,9 @@
7
7
  - Add support for recursive models.
8
8
  - Allow required array and map fields to be empty. Only nil values for required
9
9
  array and map fields are now considered invalid.
10
- - Validate nested models. This does not apply to nested models embedded
11
- within other complex types (array, map, and union).
10
+ - Validate nested models. This includes models embedded within other complex
11
+ types (array, map, and union).
12
+ - Truncate values for timestamps to the precision supported by the logical type.
12
13
 
13
14
  ## v0.8.0
14
15
  - Add support for logical types. Currently this requires using the
data/avromatic.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency 'rspec', '~> 3.0'
31
31
  spec.add_development_dependency 'simplecov'
32
32
  spec.add_development_dependency 'webmock'
33
- spec.add_development_dependency 'avro-builder', '>= 0.11.0'
33
+ spec.add_development_dependency 'avro-builder', '>= 0.12.0'
34
34
  # For FakeSchemaRegistryServer
35
35
  spec.add_development_dependency 'sinatra'
36
36
  spec.add_development_dependency 'salsify_rubocop', '~> 0.42.0'
@@ -0,0 +1,26 @@
1
+ module Avromatic
2
+ module Model
3
+ module Attribute
4
+
5
+ # This subclass of Virtus::Attribute is used to truncate timestamp values
6
+ # to the supported precision.
7
+ class AbstractTimestamp < Virtus::Attribute
8
+ def coerce(value)
9
+ return value if value.nil? || value_coerced?(value)
10
+
11
+ value.is_a?(Time) ? coerce_time(value) : value
12
+ end
13
+
14
+ def value_coerced?(_value)
15
+ raise 'subclass must implement `value_coerced?`'
16
+ end
17
+
18
+ private
19
+
20
+ def coerce_time(_value)
21
+ raise 'subclass must implement `coerce_time`'
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ require 'avromatic/model/attribute/abstract_timestamp'
2
+
3
+ module Avromatic
4
+ module Model
5
+ module Attribute
6
+
7
+ # This subclass is used to truncate timestamp values to microseconds.
8
+ class TimestampMicros < AbstractTimestamp
9
+
10
+ def value_coerced?(value)
11
+ value.is_a?(Time) && value.nsec % 1000 == 0
12
+ end
13
+
14
+ private
15
+
16
+ def coerce_time(value)
17
+ Time.at(value.to_i, value.usec)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'avromatic/model/attribute/abstract_timestamp'
2
+
3
+ module Avromatic
4
+ module Model
5
+ module Attribute
6
+
7
+ # This subclass is used to truncate timestamp values to milliseconds.
8
+ class TimestampMillis <AbstractTimestamp
9
+
10
+ def value_coerced?(value)
11
+ value.is_a?(Time) && value.usec % 1000 == 0
12
+ end
13
+
14
+ private
15
+
16
+ def coerce_time(value)
17
+ Time.at(value.to_i, value.usec / 1000 * 1000)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -77,24 +77,13 @@ module Avromatic
77
77
  inclusion: { in: Set.new(field.type.symbols.map(&:freeze)).freeze })
78
78
  when :fixed
79
79
  validates(field.name, length: { is: field.type.size })
80
- when :record
81
- validate_record(field.name)
80
+ when :record, :array, :map, :union
81
+ validate_complex(field.name)
82
82
  end
83
83
 
84
84
  add_required_validation(field)
85
85
  end
86
86
 
87
- def validate_record(field_name)
88
- validate do |instance|
89
- record = instance.send(field_name)
90
- if record && record.invalid?
91
- record.errors.each do |key, message|
92
- errors.add(field_name.to_sym, "invalid: #{key} #{message}")
93
- end
94
- end
95
- end
96
- end
97
-
98
87
  def add_required_validation(field)
99
88
  if required?(field) && field.default == :no_default
100
89
  case field.type.type_sym
@@ -5,6 +5,7 @@ require 'avromatic/model/configuration'
5
5
  require 'avromatic/model/value_object'
6
6
  require 'avromatic/model/configurable'
7
7
  require 'avromatic/model/nested_models'
8
+ require 'avromatic/model/validation'
8
9
  require 'avromatic/model/attribute/union'
9
10
  require 'avromatic/model/attributes'
10
11
  require 'avromatic/model/attribute/record'
@@ -44,6 +45,7 @@ module Avromatic
44
45
  Virtus.value_object,
45
46
  Avromatic::Model::Configurable,
46
47
  Avromatic::Model::NestedModels,
48
+ Avromatic::Model::Validation,
47
49
  Avromatic::Model::Attributes,
48
50
  Avromatic::Model::ValueObject,
49
51
  Avromatic::Model::RawSerialization,
@@ -1,11 +1,14 @@
1
+ require 'avromatic/model/attribute/timestamp_micros'
2
+ require 'avromatic/model/attribute/timestamp_millis'
3
+
1
4
  module Avromatic
2
5
  module Model
3
6
  module LogicalTypes
4
7
 
5
8
  LOGICAL_TYPE_MAP = {
6
9
  'date' => Date,
7
- 'timestamp-micros' => Time,
8
- 'timestamp-millis' => Time
10
+ 'timestamp-micros' => Avromatic::Model::Attribute::TimestampMicros,
11
+ 'timestamp-millis' => Avromatic::Model::Attribute::TimestampMillis
9
12
  }.freeze
10
13
 
11
14
  def self.value_class(logical_type)
@@ -0,0 +1,54 @@
1
+ module Avromatic
2
+ module Model
3
+ module Validation
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+
8
+ # Returns an array of messages
9
+ def validate_nested_value(value)
10
+ case value
11
+ when Avromatic::Model::Attributes
12
+ validate_record_value(value)
13
+ when Array
14
+ value.flat_map.with_index do |element, index|
15
+ validate_nested_value(element).map do |message|
16
+ "[#{index}]#{message}"
17
+ end
18
+ end
19
+ when Hash
20
+ value.flat_map do |key, map_value|
21
+ # keys for the Avro map type are always strings and do not require
22
+ # validation
23
+ validate_nested_value(map_value).map do |message|
24
+ "['#{key}']#{message}"
25
+ end
26
+ end
27
+ else
28
+ []
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def validate_complex(field_name)
35
+ validate do |instance|
36
+ value = instance.send(field_name)
37
+ messages = self.class.validate_nested_value(value)
38
+ messages.each { |message| instance.errors.add(field_name.to_sym, message) }
39
+ end
40
+ end
41
+
42
+ def validate_record_value(record)
43
+ if record && record.invalid?
44
+ record.errors.map do |key, message|
45
+ ".#{key} #{message}".gsub(' .', '.')
46
+ end
47
+ else
48
+ []
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Avromatic
2
- VERSION = '0.9.0.rc6'.freeze
2
+ VERSION = '0.9.0.rc7'.freeze
3
3
  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: 0.9.0.rc6
4
+ version: 0.9.0.rc7
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-26 00:00:00.000000000 Z
11
+ date: 2016-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avro
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - ">="
158
158
  - !ruby/object:Gem::Version
159
- version: 0.11.0
159
+ version: 0.12.0
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
- version: 0.11.0
166
+ version: 0.12.0
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: sinatra
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -246,7 +246,10 @@ files:
246
246
  - gemfiles/rails4_2.gemfile
247
247
  - lib/avromatic.rb
248
248
  - lib/avromatic/model.rb
249
+ - lib/avromatic/model/attribute/abstract_timestamp.rb
249
250
  - lib/avromatic/model/attribute/record.rb
251
+ - lib/avromatic/model/attribute/timestamp_micros.rb
252
+ - lib/avromatic/model/attribute/timestamp_millis.rb
250
253
  - lib/avromatic/model/attribute/union.rb
251
254
  - lib/avromatic/model/attribute_type/union.rb
252
255
  - lib/avromatic/model/attributes.rb
@@ -262,6 +265,7 @@ files:
262
265
  - lib/avromatic/model/passthrough_serializer.rb
263
266
  - lib/avromatic/model/raw_serialization.rb
264
267
  - lib/avromatic/model/type_registry.rb
268
+ - lib/avromatic/model/validation.rb
265
269
  - lib/avromatic/model/value_object.rb
266
270
  - lib/avromatic/model_registry.rb
267
271
  - lib/avromatic/railtie.rb