deimos-ruby 2.5.3 → 2.6.0.pre.beta1
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 +2 -0
- data/README.md +20 -9
- data/deimos-ruby.gemspec +1 -0
- data/docs/CONFIGURATION.md +11 -4
- data/lib/deimos/active_record_consume/batch_consumption.rb +1 -1
- data/lib/deimos/active_record_consume/message_consumption.rb +2 -2
- data/lib/deimos/active_record_consumer.rb +1 -1
- data/lib/deimos/active_record_producer.rb +1 -1
- data/lib/deimos/config/configuration.rb +34 -11
- data/lib/deimos/ext/producer_middleware.rb +2 -2
- data/lib/deimos/logging.rb +9 -0
- data/lib/deimos/producer.rb +5 -5
- data/lib/deimos/schema_backends/avro_base.rb +7 -36
- data/lib/deimos/schema_class.rb +72 -0
- data/lib/deimos/transcoder.rb +6 -6
- data/lib/deimos/utils/schema_class.rb +14 -47
- data/lib/deimos/version.rb +1 -1
- data/lib/deimos.rb +3 -3
- data/lib/tasks/deimos.rake +16 -4
- data/regenerate_test_schema_classes.rb +12 -3
- data/spec/active_record_batch_consumer_association_spec.rb +1 -1
- data/spec/active_record_batch_consumer_spec.rb +1 -1
- data/spec/active_record_consume/batch_consumption_spec.rb +1 -1
- data/spec/active_record_consumer_spec.rb +3 -3
- data/spec/active_record_producer_spec.rb +1 -1
- data/spec/batch_consumer_spec.rb +2 -2
- data/spec/consumer_spec.rb +9 -9
- data/spec/schema_class_spec.rb +65 -0
- data/spec/schemas/my_namespace/generated.rb +4 -4
- data/spec/schemas/my_namespace/my_long_namespace_schema.rb +2 -2
- data/spec/schemas/my_namespace/my_nested_schema.rb +3 -3
- data/spec/schemas/my_namespace/my_schema.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_compound_key.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_id_key.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_key.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_with_boolean.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_with_circular_reference.rb +3 -3
- data/spec/schemas/my_namespace/my_schema_with_complex_type.rb +6 -6
- data/spec/schemas/my_namespace/my_schema_with_date_time.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_with_id.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_with_title.rb +2 -2
- data/spec/schemas/my_namespace/my_schema_with_union_type.rb +6 -6
- data/spec/schemas/my_namespace/my_schema_with_unique_id.rb +2 -2
- data/spec/schemas/my_namespace/my_updated_schema.rb +1 -1
- data/spec/schemas/my_namespace/request/create_topic.rb +2 -2
- data/spec/schemas/my_namespace/request/index.rb +2 -2
- data/spec/schemas/my_namespace/request/update_request.rb +2 -2
- data/spec/schemas/my_namespace/response/create_topic.rb +2 -2
- data/spec/schemas/my_namespace/response/index.rb +2 -2
- data/spec/schemas/my_namespace/response/update_response.rb +2 -2
- data/spec/schemas/my_namespace/wibble.rb +2 -2
- data/spec/schemas/my_namespace/widget.rb +2 -2
- data/spec/schemas/my_namespace/widget_the_second.rb +2 -2
- data/spec/schemas/my_namespace/widget_the_third.rb +2 -2
- data/spec/spec_helper.rb +2 -2
- data/spec/utils/db_poller_spec.rb +1 -1
- metadata +18 -27
- data/lib/deimos/schema_class/base.rb +0 -62
- data/lib/deimos/schema_class/enum.rb +0 -49
- data/lib/deimos/schema_class/record.rb +0 -100
- data/lib/generators/deimos/schema_class/templates/schema_class.rb.tt +0 -8
- data/lib/generators/deimos/schema_class/templates/schema_enum.rb.tt +0 -13
- data/lib/generators/deimos/schema_class/templates/schema_record.rb.tt +0 -102
- data/lib/generators/deimos/schema_class_generator.rb +0 -369
- data/spec/generators/schema_class/my_schema_spec.rb +0 -16
- data/spec/generators/schema_class/my_schema_with_circular_reference_spec.rb +0 -98
- data/spec/generators/schema_class/my_schema_with_complex_types_spec.rb +0 -237
- data/spec/generators/schema_class_generator_spec.rb +0 -283
- data/spec/snapshots/consumers-no-nest.snap +0 -1740
- data/spec/snapshots/consumers.snap +0 -1720
- data/spec/snapshots/consumers_and_producers-no-nest.snap +0 -1740
- data/spec/snapshots/consumers_and_producers.snap +0 -1720
- data/spec/snapshots/consumers_circular-no-nest.snap +0 -1740
- data/spec/snapshots/consumers_circular.snap +0 -1720
- data/spec/snapshots/consumers_complex_types-no-nest.snap +0 -1740
- data/spec/snapshots/consumers_complex_types.snap +0 -1720
- data/spec/snapshots/consumers_nested-no-nest.snap +0 -1740
- data/spec/snapshots/consumers_nested.snap +0 -1720
- data/spec/snapshots/namespace_folders.snap +0 -1800
- data/spec/snapshots/namespace_map.snap +0 -1800
- data/spec/snapshots/producers_with_key-no-nest.snap +0 -1740
- data/spec/snapshots/producers_with_key.snap +0 -1720
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rails/generators'
|
|
4
|
-
require 'deimos'
|
|
5
|
-
require 'deimos/schema_backends/avro_base'
|
|
6
|
-
|
|
7
|
-
# Generates new schema classes.
|
|
8
|
-
module Deimos
|
|
9
|
-
module Generators
|
|
10
|
-
# Generator for Schema Classes used for the IDE and consumer/producer interfaces
|
|
11
|
-
class SchemaClassGenerator < Rails::Generators::Base
|
|
12
|
-
|
|
13
|
-
# @return [Array<Symbol>]
|
|
14
|
-
SPECIAL_TYPES = %i(record enum).freeze
|
|
15
|
-
# @return [String]
|
|
16
|
-
INITIALIZE_WHITESPACE = "\n#{' ' * 19}".freeze
|
|
17
|
-
# @return [Array<String>]
|
|
18
|
-
IGNORE_DEFAULTS = %w(message_id timestamp).freeze
|
|
19
|
-
# @return [String]
|
|
20
|
-
SCHEMA_CLASS_FILE = 'schema_class.rb'
|
|
21
|
-
# @return [String]
|
|
22
|
-
SCHEMA_RECORD_PATH = File.expand_path('schema_class/templates/schema_record.rb.tt', __dir__).freeze
|
|
23
|
-
# @return [String]
|
|
24
|
-
SCHEMA_ENUM_PATH = File.expand_path('schema_class/templates/schema_enum.rb.tt', __dir__).freeze
|
|
25
|
-
|
|
26
|
-
source_root File.expand_path('schema_class/templates', __dir__)
|
|
27
|
-
|
|
28
|
-
no_commands do
|
|
29
|
-
# Retrieve the fields from this Avro Schema
|
|
30
|
-
# @param schema [Avro::Schema::NamedSchema]
|
|
31
|
-
# @return [Array<SchemaField>]
|
|
32
|
-
def fields(schema)
|
|
33
|
-
schema.fields.map do |field|
|
|
34
|
-
Deimos::SchemaField.new(field.name, field.type, [], field.default)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Converts Deimos::SchemaField's to String form for generated YARD docs
|
|
39
|
-
# @param schema_field [Deimos::SchemaField]
|
|
40
|
-
# @return [String] A string representation of the Type of this SchemaField
|
|
41
|
-
def deimos_field_type(schema_field)
|
|
42
|
-
_field_type(schema_field.type)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Generate a Schema Model Class and all of its Nested Records from a
|
|
46
|
-
# Deimos Consumer or Producer Configuration object
|
|
47
|
-
# @param schema_name [String]
|
|
48
|
-
# @param namespace [String]
|
|
49
|
-
# @param key_config [Hash,nil]
|
|
50
|
-
# @return [void]
|
|
51
|
-
def generate_classes(schema_name, namespace, key_config, backend: nil)
|
|
52
|
-
schema_base = Deimos.schema_backend(schema: schema_name,
|
|
53
|
-
namespace: namespace,
|
|
54
|
-
backend: backend)
|
|
55
|
-
return unless schema_base.supports_class_generation?
|
|
56
|
-
|
|
57
|
-
schema_base.load_schema
|
|
58
|
-
if key_config&.dig(:schema)
|
|
59
|
-
key_schema_base = Deimos.schema_backend(schema: key_config[:schema],
|
|
60
|
-
namespace: namespace,
|
|
61
|
-
backend: backend)
|
|
62
|
-
key_schema_base.load_schema
|
|
63
|
-
generate_class_from_schema_base(key_schema_base, key_config: nil)
|
|
64
|
-
end
|
|
65
|
-
generate_class_from_schema_base(schema_base, key_config: key_config)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# @param schema [Avro::Schema::NamedSchema]
|
|
69
|
-
# @return [Array<Avro::Schema::NamedSchema]
|
|
70
|
-
def child_schemas(schema)
|
|
71
|
-
if schema.respond_to?(:fields)
|
|
72
|
-
schema.fields.map(&:type)
|
|
73
|
-
elsif schema.respond_to?(:values)
|
|
74
|
-
[schema.values]
|
|
75
|
-
elsif schema.respond_to?(:items)
|
|
76
|
-
[schema.items]
|
|
77
|
-
elsif schema.respond_to?(:schemas)
|
|
78
|
-
schema.schemas.reject { |s| s.instance_of?(Avro::Schema::PrimitiveSchema) }
|
|
79
|
-
else
|
|
80
|
-
[]
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# @param schemas [Array<Avro::Schema::NamedSchema>]
|
|
85
|
-
# @return [Array<Avro::Schema::NamedSchema>]
|
|
86
|
-
def collect_all_schemas(schemas)
|
|
87
|
-
schemas.dup.each do |schema|
|
|
88
|
-
next if @discovered_schemas.include?(schema)
|
|
89
|
-
|
|
90
|
-
@discovered_schemas << schema
|
|
91
|
-
schemas.concat(collect_all_schemas(child_schemas(schema)))
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
schemas.select { |s| s.respond_to?(:name) }.uniq
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# @param schema_base [Deimos::SchemaBackends::Base]
|
|
98
|
-
# @param key_config [Hash,nil]
|
|
99
|
-
# @return [void]
|
|
100
|
-
def generate_class_from_schema_base(schema_base, key_config: nil)
|
|
101
|
-
@discovered_schemas = Set.new
|
|
102
|
-
@sub_schema_templates = []
|
|
103
|
-
schemas = collect_all_schemas(schema_base.schema_store.schemas.values)
|
|
104
|
-
|
|
105
|
-
main_schema = schemas.find { |s| s.name == schema_base.schema }
|
|
106
|
-
sub_schemas = schemas.reject { |s| s.name == schema_base.schema }.sort_by(&:name)
|
|
107
|
-
if Deimos.config.schema.nest_child_schemas
|
|
108
|
-
@sub_schema_templates = sub_schemas.map do |schema|
|
|
109
|
-
_generate_class_template_from_schema(schema, nil)
|
|
110
|
-
end
|
|
111
|
-
write_file(main_schema, key_config)
|
|
112
|
-
else
|
|
113
|
-
write_file(main_schema, key_config)
|
|
114
|
-
sub_schemas.each do |schema|
|
|
115
|
-
write_file(schema, nil)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# @param schema [Avro::Schema::NamedSchema]
|
|
121
|
-
# @param key_config [Hash,nil]
|
|
122
|
-
# @return [void]
|
|
123
|
-
def write_file(schema, key_config)
|
|
124
|
-
class_template = _generate_class_template_from_schema(schema, key_config)
|
|
125
|
-
@modules = Utils::SchemaClass.modules_for(schema.namespace)
|
|
126
|
-
@main_class_definition = class_template
|
|
127
|
-
|
|
128
|
-
file_prefix = schema.name.underscore.singularize
|
|
129
|
-
if Deimos.config.schema.use_full_namespace
|
|
130
|
-
# Use entire namespace for folders
|
|
131
|
-
# but don't add directories that are already in the path
|
|
132
|
-
directories = @modules.map(&:underscore).select do |m|
|
|
133
|
-
Deimos.config.schema.generated_class_path.exclude?(m)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
file_prefix = "#{directories.join('/')}/#{file_prefix}"
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
filename = "#{Deimos.config.schema.generated_class_path}/#{file_prefix}.rb"
|
|
140
|
-
template(SCHEMA_CLASS_FILE, filename, force: true)
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# Format a given field into its appropriate to_h representation.
|
|
144
|
-
# @param field[Deimos::SchemaField]
|
|
145
|
-
# @return [String]
|
|
146
|
-
def field_as_json(field)
|
|
147
|
-
res = "'#{field.name}' => @#{field.name}"
|
|
148
|
-
field_base_type = _schema_base_class(field.type).type_sym
|
|
149
|
-
|
|
150
|
-
if %i(record enum).include?(field_base_type)
|
|
151
|
-
res += case field.type.type_sym
|
|
152
|
-
when :array
|
|
153
|
-
'.map { |v| v&.as_json }'
|
|
154
|
-
when :map
|
|
155
|
-
'.transform_values { |v| v&.as_json }'
|
|
156
|
-
else
|
|
157
|
-
'&.as_json'
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
res + (field.name == @fields.last.name ? '' : ',')
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
desc 'Generate a class based on configured consumer and producers.'
|
|
167
|
-
# @return [void]
|
|
168
|
-
def generate
|
|
169
|
-
_validate
|
|
170
|
-
Rails.logger.info("Generating schemas from Deimos.config to #{Deimos.config.schema.generated_class_path}")
|
|
171
|
-
found_schemas = {}
|
|
172
|
-
Deimos.karafka_configs.each do |config|
|
|
173
|
-
schema_name = config.schema
|
|
174
|
-
next if schema_name.nil?
|
|
175
|
-
|
|
176
|
-
namespace = config.namespace || Deimos.config.producers.schema_namespace
|
|
177
|
-
key_schema_name = config.key_config[:schema]
|
|
178
|
-
|
|
179
|
-
# don't regenerate if the schema was already found and had a payload key
|
|
180
|
-
next if found_schemas["#{namespace}.#{schema_name}"].present?
|
|
181
|
-
|
|
182
|
-
found_schemas["#{namespace}.#{schema_name}"] = key_schema_name
|
|
183
|
-
found_schemas["#{namespace}.#{key_schema_name}"] = nil
|
|
184
|
-
generate_classes(schema_name, namespace, config.key_config, backend: config.schema_backend)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
generate_from_schema_files(found_schemas.keys)
|
|
188
|
-
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
private
|
|
192
|
-
|
|
193
|
-
def generate_from_schema_files(found_schemas)
|
|
194
|
-
path = Deimos.config.schema.path || Deimos.config.schema.paths[:avro].first
|
|
195
|
-
schema_store = SchemaRegistry::AvroSchemaStore.new(path: path)
|
|
196
|
-
schema_store.load_schemas!
|
|
197
|
-
schema_store.schemas.values.sort_by { |s| "#{s.namespace}#{s.name}" }.each do |schema|
|
|
198
|
-
name = "#{schema.namespace}.#{schema.name}"
|
|
199
|
-
next if found_schemas.include?(name)
|
|
200
|
-
|
|
201
|
-
generate_classes(schema.name, schema.namespace, nil)
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
# Determines if Schema Class Generation can be run.
|
|
206
|
-
# @raise if Schema Backend is not of a Avro-based class
|
|
207
|
-
def _validate
|
|
208
|
-
backend = Deimos.config.schema.backend.to_s
|
|
209
|
-
raise 'Schema Class Generation requires an Avro-based Schema Backend' if backend !~ /^avro/
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
# @param schema[Avro::Schema::NamedSchema]
|
|
213
|
-
# @param key_config[Hash,nil]
|
|
214
|
-
# @return [String]
|
|
215
|
-
def _generate_class_template_from_schema(schema, key_config)
|
|
216
|
-
_set_instance_variables(schema, key_config)
|
|
217
|
-
|
|
218
|
-
temp = schema.is_a?(Avro::Schema::RecordSchema) ? _record_class_template : _enum_class_template
|
|
219
|
-
res = ERB.new(temp, trim_mode: '-')
|
|
220
|
-
res.result(binding)
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
# @param schema[Avro::Schema::NamedSchema]
|
|
224
|
-
# @param key_config [Hash,nil]
|
|
225
|
-
def _set_instance_variables(schema, key_config)
|
|
226
|
-
schema_is_record = schema.is_a?(Avro::Schema::RecordSchema)
|
|
227
|
-
@current_schema = schema
|
|
228
|
-
return unless schema_is_record
|
|
229
|
-
|
|
230
|
-
@fields = fields(schema)
|
|
231
|
-
key_schema = nil
|
|
232
|
-
if key_config&.dig(:schema)
|
|
233
|
-
key_schema_base = Deimos.schema_backend(schema: key_config[:schema], namespace: schema.namespace)
|
|
234
|
-
key_schema_base.load_schema
|
|
235
|
-
key_schema = key_schema_base.schema_store.schemas.values.first
|
|
236
|
-
@fields << Deimos::SchemaField.new('payload_key', key_schema, [], nil)
|
|
237
|
-
end
|
|
238
|
-
@initialization_definition = _initialization_definition
|
|
239
|
-
@field_assignments = _field_assignments
|
|
240
|
-
@tombstone_assignment = _tombstone_assignment(key_config, key_schema)
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
def _tombstone_assignment(key_config, key_schema)
|
|
244
|
-
return nil unless key_config
|
|
245
|
-
|
|
246
|
-
if key_config[:plain]
|
|
247
|
-
"record.tombstone_key = key"
|
|
248
|
-
elsif key_config[:field]
|
|
249
|
-
"record.tombstone_key = key\n record.#{key_config[:field]} = key"
|
|
250
|
-
elsif key_schema
|
|
251
|
-
field_base_type = _field_type(key_schema)
|
|
252
|
-
"record.tombstone_key = #{field_base_type}.initialize_from_value(key)\n record.payload_key = key"
|
|
253
|
-
else
|
|
254
|
-
''
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
# Defines the initialization method for Schema Records with one keyword argument per line
|
|
259
|
-
# @return [String] A string which defines the method signature for the initialize method
|
|
260
|
-
def _initialization_definition
|
|
261
|
-
arguments = @fields.map do |schema_field|
|
|
262
|
-
arg = "#{schema_field.name}:"
|
|
263
|
-
arg += _field_default(schema_field)
|
|
264
|
-
arg.strip
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
result = "def initialize(_from_message: false, #{arguments.first}"
|
|
268
|
-
arguments[1..].each_with_index do |arg, _i|
|
|
269
|
-
result += ",#{INITIALIZE_WHITESPACE}#{arg}"
|
|
270
|
-
end
|
|
271
|
-
"#{result})"
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# @param field [SchemaField]
|
|
275
|
-
# @return [String]
|
|
276
|
-
def _field_default(field)
|
|
277
|
-
default = field.default
|
|
278
|
-
return ' nil' if default == :no_default || default.nil? || IGNORE_DEFAULTS.include?(field.name)
|
|
279
|
-
|
|
280
|
-
type_sym = field.type.type_sym
|
|
281
|
-
if type_sym == :union
|
|
282
|
-
type_sym = field.type.schemas.find { |s| s.type_sym != :null }&.type_sym
|
|
283
|
-
end
|
|
284
|
-
case type_sym
|
|
285
|
-
when :string, :enum
|
|
286
|
-
" \"#{default}\""
|
|
287
|
-
when :record
|
|
288
|
-
schema_name = Deimos::SchemaBackends::AvroBase.schema_classname(field.type)
|
|
289
|
-
class_instance = Utils::SchemaClass.instance(field.default, schema_name)
|
|
290
|
-
" #{class_instance.to_h}"
|
|
291
|
-
else
|
|
292
|
-
" #{default}"
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
# Overrides default attr accessor methods
|
|
297
|
-
# @return [Array<String>]
|
|
298
|
-
def _field_assignments
|
|
299
|
-
result = []
|
|
300
|
-
@fields.each do |field|
|
|
301
|
-
field_type = field.type.type_sym # Record, Union, Enum, Array or Map
|
|
302
|
-
schema_base_type = _schema_base_class(field.type)
|
|
303
|
-
field_base_type = _field_type(schema_base_type)
|
|
304
|
-
method_argument = %i(array map).include?(field_type) ? 'values' : 'value'
|
|
305
|
-
is_schema_class = %i(record enum).include?(schema_base_type.type_sym)
|
|
306
|
-
|
|
307
|
-
field_initialization = method_argument
|
|
308
|
-
|
|
309
|
-
if _is_complex_union?(field)
|
|
310
|
-
field_initialization = "initialize_#{field.name}_type(value, from_message: self._from_message)"
|
|
311
|
-
elsif is_schema_class
|
|
312
|
-
field_initialization = "#{field_base_type}.initialize_from_value(value, from_message: self._from_message)"
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
result << {
|
|
316
|
-
field: field,
|
|
317
|
-
field_type: field_type,
|
|
318
|
-
is_schema_class: is_schema_class,
|
|
319
|
-
method_argument: method_argument,
|
|
320
|
-
deimos_type: deimos_field_type(field),
|
|
321
|
-
field_initialization: field_initialization,
|
|
322
|
-
is_complex_union: _is_complex_union?(field)
|
|
323
|
-
}
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
result
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
# Helper method to detect if a field is a complex union type with multiple record schemas
|
|
330
|
-
# @param field [Deimos::SchemaField]
|
|
331
|
-
# @return [Boolean]
|
|
332
|
-
def _is_complex_union?(field)
|
|
333
|
-
return false unless field.type.type_sym == :union
|
|
334
|
-
|
|
335
|
-
non_null_schemas = field.type.schemas.reject { |s| s.type_sym == :null }
|
|
336
|
-
|
|
337
|
-
record_schemas = non_null_schemas.select { |s| s.type_sym == :record }
|
|
338
|
-
record_schemas.length > 1
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
# Converts Avro::Schema::NamedSchema's to String form for generated YARD docs.
|
|
342
|
-
# Recursively handles the typing for Arrays, Maps and Unions.
|
|
343
|
-
# @param avro_schema [Avro::Schema::NamedSchema]
|
|
344
|
-
# @return [String] A string representation of the Type of this SchemaField
|
|
345
|
-
def _field_type(avro_schema)
|
|
346
|
-
Deimos::SchemaBackends::AvroBase.field_type(avro_schema)
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
# Returns the base class for this schema. Decodes Arrays, Maps and Unions
|
|
350
|
-
# @param avro_schema [Avro::Schema::NamedSchema]
|
|
351
|
-
# @return [Avro::Schema::NamedSchema]
|
|
352
|
-
def _schema_base_class(avro_schema)
|
|
353
|
-
Deimos::SchemaBackends::AvroBase.schema_base_class(avro_schema)
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
# An ERB template for schema record classes
|
|
357
|
-
# @return [String]
|
|
358
|
-
def _record_class_template
|
|
359
|
-
File.read(SCHEMA_RECORD_PATH).strip
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
# An ERB template for schema enum classes
|
|
363
|
-
# @return [String]
|
|
364
|
-
def _enum_class_template
|
|
365
|
-
File.read(SCHEMA_ENUM_PATH).strip
|
|
366
|
-
end
|
|
367
|
-
end
|
|
368
|
-
end
|
|
369
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
RSpec.describe Schemas::MyNamespace::MySchema do
|
|
2
|
-
let(:key) { Schemas::MyNamespace::MySchemaKey.new(test_id: 123) }
|
|
3
|
-
|
|
4
|
-
it 'should produce a tombstone with a hash' do
|
|
5
|
-
result = described_class.tombstone({ test_id: 123 })
|
|
6
|
-
expect(result.payload_key).to eq(key)
|
|
7
|
-
expect(result.to_h).to eq({ payload_key: { 'test_id' => 123 } })
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
it 'should work with a record' do
|
|
11
|
-
key = Schemas::MyNamespace::MySchemaKey.new(test_id: 123)
|
|
12
|
-
result = described_class.tombstone(key)
|
|
13
|
-
expect(result.payload_key).to eq(key)
|
|
14
|
-
expect(result.to_h).to eq({ payload_key: { 'test_id' => 123 } })
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# For testing the generated class.
|
|
4
|
-
RSpec.describe Schemas::MyNamespace::MySchemaWithCircularReference do
|
|
5
|
-
let(:payload_hash) do
|
|
6
|
-
{
|
|
7
|
-
properties: {
|
|
8
|
-
a_boolean: {
|
|
9
|
-
'property' => true
|
|
10
|
-
},
|
|
11
|
-
an_integer: {
|
|
12
|
-
'property' => 1
|
|
13
|
-
},
|
|
14
|
-
a_float: {
|
|
15
|
-
'property' => 4.5
|
|
16
|
-
},
|
|
17
|
-
a_string: {
|
|
18
|
-
'property' => 'string'
|
|
19
|
-
},
|
|
20
|
-
an_array: {
|
|
21
|
-
'property' => [1, 2, 3]
|
|
22
|
-
},
|
|
23
|
-
an_hash: {
|
|
24
|
-
'property' => {
|
|
25
|
-
'a_key' => 'a_value'
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
describe 'class initialization' do
|
|
33
|
-
it 'should initialize the class from keyword arguments' do
|
|
34
|
-
klass = described_class.new(properties: payload_hash[:properties])
|
|
35
|
-
expect(klass).to be_instance_of(described_class)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it 'should initialize the class from a hash with symbols as keys' do
|
|
39
|
-
klass = described_class.new(**payload_hash)
|
|
40
|
-
expect(klass).to be_instance_of(described_class)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it 'should initialize the class when missing attributes' do
|
|
44
|
-
payload_hash.delete(:properties)
|
|
45
|
-
klass = described_class.new(**payload_hash)
|
|
46
|
-
expect(klass).to be_instance_of(described_class)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
describe 'base class methods' do
|
|
52
|
-
let(:klass) do
|
|
53
|
-
described_class.new(**payload_hash)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
it 'should return the name of the schema and namespace' do
|
|
57
|
-
expect(klass.schema).to eq('MySchemaWithCircularReference')
|
|
58
|
-
expect(klass.namespace).to eq('com.my-namespace')
|
|
59
|
-
expect(klass.full_schema).to eq('com.my-namespace.MySchemaWithCircularReference')
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it 'should return a json version of the payload' do
|
|
63
|
-
described_class.new(**payload_hash)
|
|
64
|
-
payload_h = {
|
|
65
|
-
'properties' => {
|
|
66
|
-
a_boolean: {
|
|
67
|
-
'property' =>true
|
|
68
|
-
},
|
|
69
|
-
an_integer: {
|
|
70
|
-
'property' =>1
|
|
71
|
-
},
|
|
72
|
-
a_float: {
|
|
73
|
-
'property' =>4.5
|
|
74
|
-
},
|
|
75
|
-
a_string: {
|
|
76
|
-
'property' =>'string'
|
|
77
|
-
},
|
|
78
|
-
an_array: {
|
|
79
|
-
'property' =>[1, 2, 3]
|
|
80
|
-
},
|
|
81
|
-
an_hash: {
|
|
82
|
-
'property' =>{
|
|
83
|
-
'a_key' => 'a_value'
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
expect(klass.as_json).to eq(payload_h)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
it 'should return a JSON string of the payload' do
|
|
93
|
-
s = '{"properties":{"a_boolean":{"property":true},"an_integer":{"property":1},"a_float":{"property":4.5},"a_str' \
|
|
94
|
-
'ing":{"property":"string"},"an_array":{"property":[1,2,3]},"an_hash":{"property":{"a_key":"a_value"}}}}'
|
|
95
|
-
expect(klass.to_json).to eq(s)
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|