deimos-ruby 2.1.6 → 2.1.8

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: 83e7562bf4350bb2a223a8aaa6c4ad710c2c20741b39a8349132f4bac131100c
4
- data.tar.gz: 5238a10a42512e0588c3295c2aea72888a203012906967f1c9aec71059123db9
3
+ metadata.gz: db2890edc1a3d0148f1d2d17d488956140403691807b782b14fb59ab85e5eb70
4
+ data.tar.gz: 559be5246d5793112335575066f02ec07ed4310baf86bdb630a076d448770714
5
5
  SHA512:
6
- metadata.gz: 73bd43e24c3d2ff030ee3e09c572e68f18fb41da135df627d13e8298de2a888c3a69e7a4e7f51d15f6a687c01c26a5858724118dc4ea156033c5ec4fba01be8a
7
- data.tar.gz: cd177bc3f323848882a1a31c9d1bdb526c8e75f21ce10f78361927cd6d9bce3eeb0bc3b30646f3e9f6112bd3dc256d279c91d6519f756c088a2d46e081140fbc
6
+ metadata.gz: 75f32bba6112ba1cabb233c9333bb0f6e56029d30a85d24ccca5057302f103b76482e364fb183f3f8fa545f3dbb75f4f03404f4b12392ec4e8c4bea199a8ccf7
7
+ data.tar.gz: a8a745e864fd29d442fd4a4f474f58428f3ffe7fee1ea41e50ebebff8121da0aba8c91c5605ac6c991b91fe7ccb6ff03fbabf203dc296beb43e60e13f3b9c991
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
+ # 2.1.8 - 2025-08-11
11
+
12
+ - Feature: Producers can now customize the deletion payload, so different producers using the same model can send different delete messages.
13
+
14
+ # 2.1.7 - 2025-07-23
15
+
16
+ - Feature: Skip batch_record_list fill_primary_keys! if the primary key has already been filled during consumption
17
+
10
18
  # 2.1.6 - 2025-07-23
11
19
 
12
20
  - Fix: Allows rails to handle querying bulk_import_id when replacing associations for non-string bulk_import_ids
@@ -316,7 +324,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
316
324
  # 1.12.2 - 2021-12-10
317
325
 
318
326
  ### Features :star:
319
-
320
327
  - Added `Deimos.encode` and `Deimos.decode` for non-topic-related encoding and decoding.
321
328
 
322
329
  # 1.12.1 - 2021-11-02
@@ -327,7 +334,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
327
334
  # 1.12.0 - 2021-11-01
328
335
 
329
336
  ### Features :star:
330
-
331
337
  - Generate Schema classes from Avro Schemas
332
338
  - Use Schema Classes in your consumer and producer
333
339
 
@@ -361,7 +367,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
361
367
  - Added a `save_record` method to ActiveRecordConsumer in case calling code wants to work with the record before saving.
362
368
 
363
369
  - ### Fixes :wrench:
364
-
365
370
  - Fixed a regression where the default values for consumer / Phobos listener configs were not correct (they were all nil). This is technically a breaking change, but it puts the configs back the way they were at version 1.4 and matches the documentation.
366
371
 
367
372
  ## 1.9.2 - 2021-01-29
@@ -378,7 +383,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
378
383
  - Bumped the version of ruby-kafka to latest
379
384
 
380
385
  - ### Fixes :wrench:
381
-
382
386
  - Prevents DB Poller from reconnecting to DB if there is an open transaction
383
387
  - Replaces `before` by `prepend_before` for more consistent test setups.
384
388
  - Adds validation in the `kafka_producers` method (fixes [#90](https://github.com/flipp-oss/deimos/issues/90))
@@ -120,16 +120,16 @@ The following are additional settings that can be added to the `topic` block in
120
120
 
121
121
  ### Consumer Settings
122
122
 
123
- | Config name | Default | Description |
124
- |--------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
125
- | each_message | false | If true, use `consume_message` for each message rather than `consume_batch` for the full batch. |
126
- | reraise_errors | false | Default behavior is to swallow uncaught exceptions and log to the metrics provider. Set this to true to instead raise all errors. Note that raising an error will ensure that the message cannot be processed - if there is a bad message which will always raise that error, your consumer will not be able to proceed past it and will be stuck forever until you fix your code. See also the fatal_error configuration. |
127
- | fatal_error | `proc { false }` | Block taking an exception, payload and metadata and returning true if this should be considered a fatal error and false otherwise. E.g. you can use this to always fail if the database is available. Not needed if reraise_errors is set to true. |
128
- | max_db_batch_size | nil | Maximum limit for batching database calls to reduce the load on the db. |
129
- | bulk_import_id_column | `:bulk_import_id` | Name of the column to use for multi-table imports. |
130
- | replace_associations | true | If false, append to associations in multi-table imports rather than replacing them. |
131
- | bulk_import_id_generator | nil | Block to determine the bulk_import_id generated during bulk consumption. If no block is specified the provided/default block from the consumers configuration will be used. |
132
- | save_associations_first |false|Whether to save associated records of primary class prior to upserting primary records. Foreign key of associated records are assigned to the record class prior to saving the record class
123
+ | Config name | Default | Description |
124
+ |--------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
125
+ | each_message | false | If true, use `consume_message` for each message rather than `consume_batch` for the full batch. |
126
+ | reraise_errors | false | Default behavior is to swallow uncaught exceptions and log to the metrics provider. Set this to true to instead raise all errors. Note that raising an error will ensure that the message cannot be processed - if there is a bad message which will always raise that error, your consumer will not be able to proceed past it and will be stuck forever until you fix your code. See also the fatal_error configuration. |
127
+ | fatal_error | `proc { false }` | Block taking an exception, payload and metadata and returning true if this should be considered a fatal error and false otherwise. E.g. you can use this to always fail if the database is available. Not needed if reraise_errors is set to true. |
128
+ | max_db_batch_size | nil | Maximum limit for batching database calls to reduce the load on the db. |
129
+ | bulk_import_id_column | `:bulk_import_id` | Name of the column to use for multi-table imports. |
130
+ | replace_associations | true | If false, append to associations in multi-table imports rather than replacing them. |
131
+ | bulk_import_id_generator | nil | Block to determine the bulk_import_id generated during bulk consumption. If no block is specified the provided/default block from the consumers configuration will be used. |
132
+ | save_associations_first | false | Whether to save associated records of primary class prior to upserting primary records. Foreign key of associated records are assigned to the record class prior to saving the record class |
133
133
 
134
134
  ### Defining Consumers
135
135
 
@@ -52,6 +52,9 @@ module Deimos
52
52
  # records.
53
53
  def fill_primary_keys!
54
54
  primary_col = self.klass.primary_key
55
+
56
+ return if self.batch_records.empty? || self.batch_records.first.send(primary_col).present?
57
+
55
58
  bulk_import_map = self.klass.
56
59
  where(self.bulk_import_column => self.batch_records.map(&:bulk_import_id)).
57
60
  select(primary_col, self.bulk_import_column).
@@ -76,6 +76,15 @@ module Deimos
76
76
  Utils::SchemaClass.instance(payload, encoder.schema, encoder.namespace)
77
77
  end
78
78
 
79
+ # Deletion payload for a record by default, delegate to the
80
+ # model's deletion_payload. Producers may override this method to
81
+ # customize the deletion key/payload per producer.
82
+ # @param record [ActiveRecord::Base]
83
+ # @return [Hash]
84
+ def generate_deletion_payload(record)
85
+ record.deletion_payload
86
+ end
87
+
79
88
  # Query to use when polling the database with the DbPoller. Add
80
89
  # includes, joins, or wheres as necessary, or replace entirely.
81
90
  # @param time_from [Time] the time to start the query from.
@@ -100,7 +109,7 @@ module Deimos
100
109
  end
101
110
 
102
111
  # Post process records after publishing
103
- # @param records [Array<ActiveRecord::Base>]
112
+ # @param _records [Array<ActiveRecord::Base>]
104
113
  def post_process(_records)
105
114
  end
106
115
 
@@ -46,7 +46,9 @@ module Deimos
46
46
  def send_kafka_event_on_destroy
47
47
  return unless self.class.kafka_config[:delete]
48
48
 
49
- self.class.kafka_producers.each { |p| p.publish_list([self.deletion_payload]) }
49
+ self.class.kafka_producers.each do |p|
50
+ p.publish_list([p.generate_deletion_payload(self)])
51
+ end
50
52
  end
51
53
 
52
54
  # Payload to send after we are destroyed.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Deimos
4
- VERSION = '2.1.6'
4
+ VERSION = '2.1.8'
5
5
  end
@@ -251,5 +251,192 @@ RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
251
251
 
252
252
  end
253
253
 
254
+ context 'with recorded primary_keys' do
255
+ before(:all) do
256
+ ActiveRecord::Base.connection.create_table(:fidgets, force: true, id: false) do |t|
257
+ t.string :test_id, primary_key: true
258
+ t.integer(:some_int)
259
+ t.string(:bulk_import_id)
260
+ t.timestamps
261
+ end
262
+
263
+ ActiveRecord::Base.connection.create_table(:fidget_details, force: true) do |t|
264
+ t.string(:title)
265
+ t.string(:bulk_import_id)
266
+ t.belongs_to(:fidget)
267
+
268
+ t.index(%i(title), unique: true)
269
+ end
270
+
271
+ end
272
+
273
+ after(:all) do
274
+ ActiveRecord::Base.connection.drop_table(:fidgets)
275
+ ActiveRecord::Base.connection.drop_table(:fidget_details)
276
+ end
277
+
278
+ let(:fidget_detail_class) do
279
+ Class.new(ActiveRecord::Base) do
280
+ self.table_name = 'fidget_details'
281
+ belongs_to :fidget
282
+ end
283
+ end
284
+
285
+ let(:fidget_class) do
286
+ Class.new(ActiveRecord::Base) do
287
+ self.table_name = 'fidgets'
288
+ has_one :fidget_detail
289
+ end
290
+ end
291
+
292
+ let(:bulk_id_generator) { proc { SecureRandom.uuid } }
293
+
294
+ let(:key_proc) do
295
+ lambda do |klass|
296
+ case klass.to_s
297
+ when 'Fidget'
298
+ %w(test_id)
299
+ when 'FidgetDetail'
300
+ %w(title)
301
+ else
302
+ raise "Key Columns for #{klass} not defined"
303
+ end
304
+
305
+ end
306
+ end
307
+
308
+ before(:each) do
309
+ stub_const('Fidget', fidget_class)
310
+ stub_const('FidgetDetail', fidget_detail_class)
311
+ Fidget.reset_column_information
312
+ end
313
+
314
+
315
+ let(:batch) do
316
+ Deimos::ActiveRecordConsume::BatchRecordList.new(
317
+ [
318
+ Deimos::ActiveRecordConsume::BatchRecord.new(
319
+ klass: Fidget,
320
+ attributes: { test_id: 'id1', some_int: 5, fidget_detail: { title: 'Title 1' } },
321
+ bulk_import_column: 'bulk_import_id',
322
+ bulk_import_id_generator: bulk_id_generator
323
+ ),
324
+ Deimos::ActiveRecordConsume::BatchRecord.new(
325
+ klass: Fidget,
326
+ attributes: { test_id: 'id2', some_int: 10, fidget_detail: { title: 'Title 2' } },
327
+ bulk_import_column: 'bulk_import_id',
328
+ bulk_import_id_generator: bulk_id_generator
329
+ )
330
+ ]
331
+ )
332
+ end
333
+
334
+ it 'should not backfill the primary key when the primary_key exists' do
335
+ allow(Fidget).to receive(:where).and_call_original
336
+ results = described_class.new(Widget,
337
+ bulk_import_id_generator: bulk_id_generator,
338
+ bulk_import_id_column: 'bulk_import_id',
339
+ key_col_proc: key_proc).mass_update(batch)
340
+ expect(results.count).to eq(2)
341
+ expect(Fidget.count).to eq(2)
342
+ expect(Fidget).not_to have_received(:where).with(:bulk_import_id => [instance_of(String), instance_of(String)])
343
+ end
344
+
345
+ end
346
+
347
+ context 'without recorded primary_keys' do
348
+ before(:all) do
349
+ ActiveRecord::Base.connection.create_table(:fidgets, force: true) do |t|
350
+ t.string(:test_id)
351
+ t.integer(:some_int)
352
+ t.string(:bulk_import_id)
353
+ t.timestamps
354
+ end
355
+
356
+ ActiveRecord::Base.connection.create_table(:fidget_details, force: true) do |t|
357
+ t.string(:title)
358
+ t.string(:bulk_import_id)
359
+ t.belongs_to(:fidget)
360
+
361
+ t.index(%i(title), unique: true)
362
+ end
363
+
364
+ end
365
+
366
+ after(:all) do
367
+ ActiveRecord::Base.connection.drop_table(:fidgets)
368
+ ActiveRecord::Base.connection.drop_table(:fidget_details)
369
+ end
370
+
371
+ let(:fidget_detail_class) do
372
+ Class.new(ActiveRecord::Base) do
373
+ self.table_name = 'fidget_details'
374
+ belongs_to :fidget
375
+ end
376
+ end
377
+
378
+ let(:fidget_class) do
379
+ Class.new(ActiveRecord::Base) do
380
+ self.table_name = 'fidgets'
381
+ has_one :fidget_detail
382
+ end
383
+ end
384
+
385
+ let(:bulk_id_generator) { proc { SecureRandom.uuid } }
386
+
387
+ let(:key_proc) do
388
+ lambda do |klass|
389
+ case klass.to_s
390
+ when 'Fidget'
391
+ %w(id)
392
+ when 'FidgetDetail'
393
+ %w(title)
394
+ else
395
+ raise "Key Columns for #{klass} not defined"
396
+ end
397
+
398
+ end
399
+ end
400
+
401
+ before(:each) do
402
+ stub_const('Fidget', fidget_class)
403
+ stub_const('FidgetDetail', fidget_detail_class)
404
+ Fidget.reset_column_information
405
+ end
406
+
407
+
408
+ let(:batch) do
409
+ Deimos::ActiveRecordConsume::BatchRecordList.new(
410
+ [
411
+ Deimos::ActiveRecordConsume::BatchRecord.new(
412
+ klass: Fidget,
413
+ attributes: { test_id: 'id1', some_int: 5, fidget_detail: { title: 'Title 1' } },
414
+ bulk_import_column: 'bulk_import_id',
415
+ bulk_import_id_generator: bulk_id_generator
416
+ ),
417
+ Deimos::ActiveRecordConsume::BatchRecord.new(
418
+ klass: Fidget,
419
+ attributes: { test_id: 'id2', some_int: 10, fidget_detail: { title: 'Title 2' } },
420
+ bulk_import_column: 'bulk_import_id',
421
+ bulk_import_id_generator: bulk_id_generator
422
+ )
423
+ ]
424
+ )
425
+ end
426
+
427
+ it 'should not backfill the primary key when the primary_key exists' do
428
+ allow(Fidget).to receive(:where).and_call_original
429
+ results = described_class.new(Widget,
430
+ bulk_import_id_generator: bulk_id_generator,
431
+ bulk_import_id_column: 'bulk_import_id',
432
+ key_col_proc: key_proc).mass_update(batch)
433
+ expect(results.count).to eq(2)
434
+ expect(Fidget.count).to eq(2)
435
+ expect(Fidget).to have_received(:where).with(:bulk_import_id => [instance_of(String), instance_of(String)])
436
+ expect(batch.records.map(&:id)).to eq([1,2])
437
+ end
438
+
439
+ end
440
+
254
441
  end
255
442
  end
@@ -105,23 +105,96 @@ module KafkaSourceSpec
105
105
  expect('my-topic-the-second').to have_sent(nil, widget.id)
106
106
  end
107
107
 
108
+ context 'multi-producer model using two different key fields' do
109
+ before(:each) do
110
+ class MultiKeyWidget < ActiveRecord::Base
111
+ include Deimos::KafkaSource
112
+ self.table_name = 'widgets'
113
+
114
+ def self.kafka_producers
115
+ [WidgetProducer, WidgetStringKeyProducer]
116
+ end
117
+ end
118
+
119
+ class WidgetStringKeyProducer < Deimos::ActiveRecordProducer
120
+ class << self
121
+
122
+ def generate_payload(attributes, record)
123
+ payload = super(attributes, record)
124
+ payload.merge('id' => record.model_id)
125
+
126
+ end
127
+
128
+ def generate_deletion_payload(record)
129
+ { payload_key: record.model_id }
130
+ end
131
+ end
132
+ end
133
+
134
+ Karafka::App.routes.redraw do
135
+ topic 'my-topic' do
136
+ namespace 'com.my-namespace'
137
+ schema 'Widget'
138
+ key_config field: :id
139
+ producer_class WidgetProducer
140
+ end
141
+
142
+ topic 'my-topic-the-Third' do
143
+ namespace 'com.my-namespace'
144
+ schema 'WidgetTheThird'
145
+ key_config field: :model_id
146
+ producer_class WidgetStringKeyProducer
147
+ end
148
+
149
+ end
150
+ end
151
+
152
+ it 'publishes create/delete with correct keys per producer (primary: id, secondary: model_id)' do
153
+ multi_key_widget = MultiKeyWidget.create!(widget_id: 7, model_id: 'model-id-123', name: 'name-123')
154
+
155
+ expect('my-topic').to have_sent({
156
+ widget_id: 7,
157
+ name: 'name-123',
158
+ id: multi_key_widget.id,
159
+ created_at: anything,
160
+ updated_at: anything
161
+ }, multi_key_widget.id)
162
+
163
+ expect('my-topic-the-Third').to have_sent({
164
+ widget_id: 7,
165
+ model_id: multi_key_widget.model_id,
166
+ id: multi_key_widget.model_id,
167
+ created_at: anything,
168
+ updated_at: anything
169
+ }, multi_key_widget.model_id)
170
+
171
+ expect(WidgetProducer).to receive(:generate_deletion_payload).and_call_original
172
+ expect(WidgetStringKeyProducer).to receive(:generate_deletion_payload).and_call_original
173
+
174
+ multi_key_widget.destroy
175
+
176
+ expect('my-topic').to have_sent(nil, multi_key_widget.id)
177
+ expect('my-topic-the-Third').to have_sent(nil, multi_key_widget.model_id)
178
+ end
179
+ end
180
+
108
181
  context 'with truncation off' do
109
182
  before(:each) do
110
183
  Deimos.config.producers.truncate_columns = false
111
184
  end
112
185
  it 'should not truncate values' do
113
- widget = Widget.create!(widget_id: 1, name: 'a'*500)
186
+ widget = Widget.create!(widget_id: 1, name: 'a' * 500)
114
187
  expect('my-topic').to have_sent({
115
188
  widget_id: 1,
116
- name: 'a'*500,
189
+ name: 'a' * 500,
117
190
  id: widget.id,
118
191
  created_at: anything,
119
192
  updated_at: anything
120
193
  }, 1)
121
- widget.update_attribute(:name, 'b'*500)
194
+ widget.update_attribute(:name, 'b' * 500)
122
195
  expect('my-topic').to have_sent({
123
196
  widget_id: 1,
124
- name: 'b'*500,
197
+ name: 'b' * 500,
125
198
  id: widget.id,
126
199
  created_at: anything,
127
200
  updated_at: anything
@@ -134,18 +207,18 @@ module KafkaSourceSpec
134
207
  Deimos.config.producers.truncate_columns = true
135
208
  end
136
209
  it 'should truncate values' do
137
- widget = Widget.create!(widget_id: 1, name: 'a'*500)
210
+ widget = Widget.create!(widget_id: 1, name: 'a' * 500)
138
211
  expect('my-topic').to have_sent({
139
212
  widget_id: 1,
140
- name: 'a'*100,
213
+ name: 'a' * 100,
141
214
  id: widget.id,
142
215
  created_at: anything,
143
216
  updated_at: anything
144
217
  }, 1)
145
- widget.update_attribute(:name, 'b'*500)
218
+ widget.update_attribute(:name, 'b' * 500)
146
219
  expect('my-topic').to have_sent({
147
220
  widget_id: 1,
148
- name: 'b'*100,
221
+ name: 'b' * 100,
149
222
  id: widget.id,
150
223
  created_at: anything,
151
224
  updated_at: anything
@@ -304,6 +377,7 @@ module KafkaSourceSpec
304
377
  [WidgetProducer]
305
378
  end
306
379
  end
380
+
307
381
  WidgetNoImportHook.reset_column_information
308
382
  end
309
383
 
@@ -0,0 +1,27 @@
1
+ {
2
+ "namespace": "com.my-namespace",
3
+ "name": "WidgetTheThird",
4
+ "type": "record",
5
+ "fields": [
6
+ {
7
+ "name": "id",
8
+ "type": "string"
9
+ },
10
+ {
11
+ "name": "widget_id",
12
+ "type": "long"
13
+ },
14
+ {
15
+ "name": "model_id",
16
+ "type": "string"
17
+ },
18
+ {
19
+ "name": "updated_at",
20
+ "type": "long"
21
+ },
22
+ {
23
+ "name": "created_at",
24
+ "type": "long"
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is autogenerated by Deimos, Do NOT modify
4
+ module Schemas; module MyNamespace
5
+ ### Primary Schema Class ###
6
+ # Autogenerated Schema for Record at com.my-namespace.WidgetTheThird
7
+ class WidgetTheThird < Deimos::SchemaClass::Record
8
+
9
+ ### Attribute Accessors ###
10
+ # @return [String]
11
+ attr_accessor :id
12
+ # @return [Integer]
13
+ attr_accessor :widget_id
14
+ # @return [String]
15
+ attr_accessor :model_id
16
+ # @return [Integer]
17
+ attr_accessor :updated_at
18
+ # @return [Integer]
19
+ attr_accessor :created_at
20
+
21
+ # @override
22
+ def initialize(_from_message: false, id: nil,
23
+ widget_id: nil,
24
+ model_id: nil,
25
+ updated_at: nil,
26
+ created_at: nil)
27
+ @_from_message = _from_message
28
+ super
29
+ self.id = id
30
+ self.widget_id = widget_id
31
+ self.model_id = model_id
32
+ self.updated_at = updated_at
33
+ self.created_at = created_at
34
+ end
35
+
36
+ # @override
37
+ def schema
38
+ 'WidgetTheThird'
39
+ end
40
+
41
+ # @override
42
+ def namespace
43
+ 'com.my-namespace'
44
+ end
45
+
46
+ # @override
47
+ def as_json(_opts={})
48
+ {
49
+ 'id' => @id,
50
+ 'widget_id' => @widget_id,
51
+ 'model_id' => @model_id,
52
+ 'updated_at' => @updated_at,
53
+ 'created_at' => @created_at
54
+ }
55
+ end
56
+ end
57
+ end; end
@@ -1648,6 +1648,66 @@ module Schemas
1648
1648
  end
1649
1649
 
1650
1650
 
1651
+ spec/app/lib/schema_classes/widget_the_third.rb:
1652
+ # frozen_string_literal: true
1653
+
1654
+ # This file is autogenerated by Deimos, Do NOT modify
1655
+ module Schemas
1656
+ ### Primary Schema Class ###
1657
+ # Autogenerated Schema for Record at com.my-namespace.WidgetTheThird
1658
+ class WidgetTheThird < Deimos::SchemaClass::Record
1659
+
1660
+ ### Attribute Accessors ###
1661
+ # @return [String]
1662
+ attr_accessor :id
1663
+ # @return [Integer]
1664
+ attr_accessor :widget_id
1665
+ # @return [String]
1666
+ attr_accessor :model_id
1667
+ # @return [Integer]
1668
+ attr_accessor :updated_at
1669
+ # @return [Integer]
1670
+ attr_accessor :created_at
1671
+
1672
+ # @override
1673
+ def initialize(_from_message: false, id: nil,
1674
+ widget_id: nil,
1675
+ model_id: nil,
1676
+ updated_at: nil,
1677
+ created_at: nil)
1678
+ @_from_message = _from_message
1679
+ super
1680
+ self.id = id
1681
+ self.widget_id = widget_id
1682
+ self.model_id = model_id
1683
+ self.updated_at = updated_at
1684
+ self.created_at = created_at
1685
+ end
1686
+
1687
+ # @override
1688
+ def schema
1689
+ 'WidgetTheThird'
1690
+ end
1691
+
1692
+ # @override
1693
+ def namespace
1694
+ 'com.my-namespace'
1695
+ end
1696
+
1697
+ # @override
1698
+ def as_json(_opts={})
1699
+ {
1700
+ 'id' => @id,
1701
+ 'widget_id' => @widget_id,
1702
+ 'model_id' => @model_id,
1703
+ 'updated_at' => @updated_at,
1704
+ 'created_at' => @created_at
1705
+ }
1706
+ end
1707
+ end
1708
+ end
1709
+
1710
+
1651
1711
  spec/app/lib/schema_classes/yet_another_enum.rb:
1652
1712
  # frozen_string_literal: true
1653
1713