nats_wave 1.1.12 → 1.1.14

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.
@@ -1,822 +1,3 @@
1
- # # # frozen_string_literal: true
2
- # #
3
- # # module NatsWave
4
- # # module Concerns
5
- # # module Mappable
6
- # # extend ActiveSupport::Concern
7
- # #
8
- # # included do
9
- # # class_attribute :nats_wave_subscription_config, :nats_wave_publishing_config
10
- # # self.nats_wave_subscription_config = {}
11
- # # self.nats_wave_publishing_config = {}
12
- # # end
13
- # #
14
- # # class_methods do
15
- # # # Configure subscriptions with optional custom handler
16
- # # def nats_wave_subscribes_to(*subjects, **options, &block)
17
- # # Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
18
- # #
19
- # # handler = options[:handler] || block
20
- # #
21
- # # subscription_config = {
22
- # # subjects: subjects.flatten,
23
- # # field_mappings: options[:field_mappings] || {},
24
- # # transformations: options[:transformations] || {},
25
- # # skip_fields: options[:skip_fields] || [],
26
- # # unique_fields: options[:unique_fields] || [:id],
27
- # # sync_strategy: options[:sync_strategy] || :upsert,
28
- # # handler: handler,
29
- # # queue_group: options[:queue_group],
30
- # # auto_sync: options[:auto_sync] != false # Default to true, can be disabled
31
- # # }
32
- # #
33
- # # # Store the config
34
- # # config_key = subjects.join(',')
35
- # # self.nats_wave_subscription_config[config_key] = subscription_config
36
- # #
37
- # # # Create the subscription handler
38
- # # processed_handler = create_subscription_handler(subscription_config)
39
- # #
40
- # # # Register the subscription
41
- # # NatsWave::ModelRegistry.register_subscription(
42
- # # subjects: subjects.flatten,
43
- # # model: self.name,
44
- # # handler: processed_handler,
45
- # # queue_group: subscription_config[:queue_group]
46
- # # )
47
- # #
48
- # # Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
49
- # # end
50
- # #
51
- # # # Configure publishing with optional custom handler
52
- # # def nats_wave_publishes_to(*subjects, **options, &block)
53
- # # Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
54
- # #
55
- # # handler = options[:handler] || block
56
- # #
57
- # # publishing_config = {
58
- # # subjects: subjects.flatten,
59
- # # field_mappings: options[:field_mappings] || {},
60
- # # transformations: options[:transformations] || {},
61
- # # skip_fields: options[:skip_fields] || [],
62
- # # conditions: options[:conditions] || {},
63
- # # actions: options[:actions] || [:create, :update, :destroy],
64
- # # handler: handler,
65
- # # async: options[:async] != false, # Default to true
66
- # # enabled: options[:enabled] != false # Default to true
67
- # # }
68
- # #
69
- # # # Store the config
70
- # # config_key = subjects.join(',')
71
- # # self.nats_wave_publishing_config[config_key] = publishing_config
72
- # #
73
- # # Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
74
- # # end
75
- # #
76
- # # # Get all subscription configurations
77
- # # def nats_wave_subscription_configs
78
- # # nats_wave_subscription_config
79
- # # end
80
- # #
81
- # # # Get all publishing configurations
82
- # # def nats_wave_publishing_configs
83
- # # nats_wave_publishing_config
84
- # # end
85
- # #
86
- # # # Get all subjects this model subscribes to
87
- # # def nats_wave_subscribed_subjects
88
- # # nats_wave_subscription_config.values.flat_map { |config| config[:subjects] }.uniq
89
- # # end
90
- # #
91
- # # # Get all subjects this model publishes to
92
- # # def nats_wave_published_subjects
93
- # # nats_wave_publishing_config.values.flat_map { |config| config[:subjects] }.uniq
94
- # # end
95
- # #
96
- # # private
97
- # #
98
- # # # Create a subscription handler that processes data and calls custom handler or auto-sync
99
- # # def create_subscription_handler(config)
100
- # # model_class = self
101
- # #
102
- # # lambda do |message|
103
- # # begin
104
- # # Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
105
- # #
106
- # # # Extract the raw data
107
- # # raw_data = message['data'] || {}
108
- # # model_name = message['model']
109
- # # action = message['action']
110
- # #
111
- # # # Process the data through mappings and transformations
112
- # # processed_data = model_class.process_data(raw_data, config)
113
- # #
114
- # # # If custom handler is provided, call it with model_name, action, processed_data
115
- # # if config[:handler]
116
- # # Rails.logger.debug "📨 Calling custom subscription handler" if defined?(Rails)
117
- # # config[:handler].call(model_name, action, processed_data, message)
118
- # # elsif config[:auto_sync]
119
- # # Rails.logger.debug "📨 Performing auto-sync" if defined?(Rails)
120
- # # # Default auto-sync behavior
121
- # # model_class.perform_auto_sync(model_name, action, processed_data, config)
122
- # # else
123
- # # Rails.logger.debug "📨 No handler provided and auto_sync disabled" if defined?(Rails)
124
- # # end
125
- # #
126
- # # rescue => e
127
- # # Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
128
- # # Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
129
- # # raise
130
- # # end
131
- # # end
132
- # # end
133
- # #
134
- # # # Process data through field mappings and transformations (used by both subscription and publishing)
135
- # # def process_data(raw_data, config)
136
- # # processed_data = {}
137
- # # field_mappings = config[:field_mappings]
138
- # # transformations = config[:transformations]
139
- # # skip_fields = config[:skip_fields]
140
- # #
141
- # # raw_data.each do |field, value|
142
- # # field_str = field.to_s
143
- # # field_sym = field.to_sym
144
- # #
145
- # # # Skip if in skip_fields
146
- # # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
147
- # #
148
- # # # Apply field mapping
149
- # # mapped_field = field_mappings[field_str] ||
150
- # # field_mappings[field_sym] ||
151
- # # field
152
- # #
153
- # # # Apply transformation if any
154
- # # transformed_value = apply_transformation(value, mapped_field, transformations, raw_data)
155
- # #
156
- # # processed_data[mapped_field.to_s] = transformed_value
157
- # # end
158
- # #
159
- # # processed_data
160
- # # end
161
- # #
162
- # # # Apply transformations to field values
163
- # # def apply_transformation(value, field, transformations, full_record)
164
- # # transformation = transformations[field] || transformations[field.to_sym]
165
- # #
166
- # # case transformation
167
- # # when Proc
168
- # # if transformation.arity == 2 || transformation.arity < 0
169
- # # transformation.call(value, full_record)
170
- # # else
171
- # # transformation.call(value)
172
- # # end
173
- # # when Symbol
174
- # # if self.respond_to?(transformation, true)
175
- # # self.send(transformation, value)
176
- # # elsif value.respond_to?(transformation)
177
- # # value.send(transformation)
178
- # # else
179
- # # Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
180
- # # value
181
- # # end
182
- # # else
183
- # # value
184
- # # end
185
- # # end
186
- # #
187
- # # # Default auto-sync behavior
188
- # # def perform_auto_sync(model_name, action, processed_data, config)
189
- # # unique_fields = config[:unique_fields]
190
- # # sync_strategy = config[:sync_strategy]
191
- # #
192
- # # case action.to_s.downcase
193
- # # when 'create', 'created'
194
- # # handle_auto_create(processed_data, unique_fields, sync_strategy)
195
- # # when 'update', 'updated'
196
- # # handle_auto_update(processed_data, unique_fields, sync_strategy)
197
- # # when 'delete', 'deleted', 'destroy', 'destroyed'
198
- # # handle_auto_delete(processed_data, unique_fields)
199
- # # else
200
- # # Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
201
- # # end
202
- # # end
203
- # #
204
- # # def handle_auto_create(data, unique_fields, sync_strategy)
205
- # # case sync_strategy
206
- # # when :upsert
207
- # # existing = find_by_unique_fields(data, unique_fields)
208
- # # if existing
209
- # # existing.update!(data)
210
- # # Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
211
- # # else
212
- # # record = self.create!(data)
213
- # # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
214
- # # end
215
- # # when :create_only
216
- # # record = self.create!(data)
217
- # # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
218
- # # end
219
- # # rescue => e
220
- # # Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
221
- # # raise
222
- # # end
223
- # #
224
- # # def handle_auto_update(data, unique_fields, sync_strategy)
225
- # # existing = find_by_unique_fields(data, unique_fields)
226
- # # if existing
227
- # # existing.update!(data)
228
- # # Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
229
- # # elsif sync_strategy == :upsert
230
- # # record = self.create!(data)
231
- # # Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
232
- # # else
233
- # # Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
234
- # # end
235
- # # rescue => e
236
- # # Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
237
- # # raise
238
- # # end
239
- # #
240
- # # def handle_auto_delete(data, unique_fields)
241
- # # existing = find_by_unique_fields(data, unique_fields)
242
- # # if existing
243
- # # existing.destroy!
244
- # # Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
245
- # # else
246
- # # Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
247
- # # end
248
- # # rescue => e
249
- # # Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
250
- # # raise
251
- # # end
252
- # #
253
- # # def find_by_unique_fields(data, unique_fields)
254
- # # conditions = {}
255
- # # unique_fields.each do |field|
256
- # # field_str = field.to_s
257
- # # if data.key?(field_str)
258
- # # conditions[field] = data[field_str]
259
- # # elsif data.key?(field.to_sym)
260
- # # conditions[field] = data[field.to_sym]
261
- # # end
262
- # # end
263
- # #
264
- # # return nil if conditions.empty?
265
- # # self.find_by(conditions)
266
- # # end
267
- # # end
268
- # #
269
- # # # Instance methods for publishing
270
- # # def nats_wave_publish(action = nil)
271
- # # action ||= determine_action_from_context
272
- # #
273
- # # self.class.nats_wave_publishing_configs.each do |subjects_key, config|
274
- # # next unless config[:enabled]
275
- # # next unless config[:actions].include?(action.to_sym)
276
- # #
277
- # # # Check conditions (only for publishing)
278
- # # if config[:conditions].any? && !evaluate_conditions(config[:conditions])
279
- # # Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
280
- # # next
281
- # # end
282
- # #
283
- # # # Get the raw data (current model attributes)
284
- # # raw_data = get_raw_attributes
285
- # #
286
- # # # Process the data through mappings and transformations (same as subscription)
287
- # # processed_data = self.class.process_data(raw_data, config)
288
- # #
289
- # # # If custom handler is provided, call it
290
- # # if config[:handler]
291
- # # Rails.logger.debug "📤 Calling custom publishing handler" if defined?(Rails)
292
- # # config[:handler].call(self.class.name, action, processed_data, self)
293
- # # else
294
- # # # Default publishing behavior - publish the processed data
295
- # # config[:subjects].each do |subject|
296
- # # NatsWave.client.publish(
297
- # # subject: subject,
298
- # # model: self.class.name,
299
- # # action: action,
300
- # # data: processed_data, # This is the processed data, not raw attributes
301
- # # metadata: build_publishing_metadata
302
- # # )
303
- # #
304
- # # Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
305
- # # end
306
- # # end
307
- # # end
308
- # # rescue StandardError => e
309
- # # Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
310
- # # # Don't re-raise to avoid breaking transactions
311
- # # end
312
- # #
313
- # # private
314
- # #
315
- # # def determine_action_from_context
316
- # # # Try to determine action from ActiveRecord context
317
- # # if defined?(ActiveRecord) && is_a?(ActiveRecord::Base)
318
- # # return 'create' if previously_new_record?
319
- # # return 'update' if saved_changes.any?
320
- # # return 'destroy' if destroyed?
321
- # # end
322
- # #
323
- # # 'update' # Default fallback
324
- # # end
325
- # #
326
- # # def get_raw_attributes
327
- # # # Get attributes (works for both ActiveRecord and other objects)
328
- # # if respond_to?(:attributes)
329
- # # attributes
330
- # # else
331
- # # # For non-ActiveRecord objects, get instance variables
332
- # # instance_variables.map { |v| [v.to_s.delete('@'), instance_variable_get(v)] }.to_h
333
- # # end
334
- # # end
335
- # #
336
- # # def evaluate_conditions(conditions)
337
- # # conditions.all? do |condition, expected_value|
338
- # # case condition
339
- # # when Proc
340
- # # condition.call(self)
341
- # # when Symbol, String
342
- # # if respond_to?(condition, true)
343
- # # result = send(condition)
344
- # # expected_value.nil? ? result : result == expected_value
345
- # # else
346
- # # false
347
- # # end
348
- # # else
349
- # # false
350
- # # end
351
- # # end
352
- # # end
353
- # #
354
- # # def build_publishing_metadata
355
- # # {
356
- # # source_model: self.class.name,
357
- # # source_id: respond_to?(:id) ? id : object_id,
358
- # # published_at: Time.current.iso8601
359
- # # }
360
- # # end
361
- # # end
362
- # # end
363
- # # end
364
- #
365
- # # frozen_string_literal: true
366
- #
367
- # module NatsWave
368
- # module Concerns
369
- # module Mappable
370
- # extend ActiveSupport::Concern
371
- #
372
- # included do
373
- # class_attribute :nats_wave_subscription_config, :nats_wave_publishing_config
374
- # self.nats_wave_subscription_config = {}
375
- # self.nats_wave_publishing_config = {}
376
- # end
377
- #
378
- # class_methods do
379
- # # Configure subscriptions with optional custom handler
380
- # def nats_wave_subscribes_to(*subjects, **options, &block)
381
- # Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
382
- #
383
- # handler = options[:handler] || block
384
- #
385
- # subscription_config = {
386
- # subjects: subjects.flatten,
387
- # field_mappings: options[:field_mappings] || {},
388
- # transformations: options[:transformations] || {},
389
- # skip_fields: options[:skip_fields] || [],
390
- # unique_fields: options[:unique_fields] || [:id],
391
- # sync_strategy: options[:sync_strategy] || :upsert,
392
- # handler: handler,
393
- # queue_group: options[:queue_group],
394
- # auto_sync: options[:auto_sync] != false # Default to true, can be disabled
395
- # }
396
- #
397
- # # Store the config
398
- # config_key = subjects.join(',')
399
- # self.nats_wave_subscription_config[config_key] = subscription_config
400
- #
401
- # # Create the subscription handler
402
- # processed_handler = create_subscription_handler(subscription_config)
403
- #
404
- # # Register the subscription
405
- # NatsWave::ModelRegistry.register_subscription(
406
- # subjects: subjects.flatten,
407
- # model: self.name,
408
- # handler: processed_handler,
409
- # queue_group: subscription_config[:queue_group]
410
- # )
411
- #
412
- # Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
413
- # end
414
- #
415
- # # Configure publishing with optional custom handler AND auto-publishing callbacks
416
- # def nats_wave_publishes_to(*subjects, **options, &block)
417
- # Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
418
- #
419
- # handler = options[:handler] || block
420
- #
421
- # publishing_config = {
422
- # subjects: subjects.flatten,
423
- # field_mappings: options[:field_mappings] || {},
424
- # transformations: options[:transformations] || {},
425
- # skip_fields: options[:skip_fields] || [],
426
- # conditions: options[:conditions] || {},
427
- # actions: options[:actions] || [:create, :update, :destroy],
428
- # handler: handler,
429
- # async: options[:async] != false, # Default to true
430
- # enabled: options[:enabled] != false # Default to true
431
- # }
432
- #
433
- # # Store the config
434
- # config_key = subjects.join(',')
435
- # self.nats_wave_publishing_config[config_key] = publishing_config
436
- #
437
- # # Add ActiveRecord callbacks for auto-publishing
438
- # setup_publishing_callbacks(publishing_config)
439
- #
440
- # Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
441
- # end
442
- #
443
- # # Get all subscription configurations
444
- # def nats_wave_subscription_configs
445
- # nats_wave_subscription_config
446
- # end
447
- #
448
- # # Get all publishing configurations
449
- # def nats_wave_publishing_configs
450
- # nats_wave_publishing_config
451
- # end
452
- #
453
- # # Get all subjects this model subscribes to
454
- # def nats_wave_subscribed_subjects
455
- # nats_wave_subscription_config.values.flat_map { |config| config[:subjects] }.uniq
456
- # end
457
- #
458
- # # Get all subjects this model publishes to
459
- # def nats_wave_published_subjects
460
- # nats_wave_publishing_config.values.flat_map { |config| config[:subjects] }.uniq
461
- # end
462
- #
463
- # private
464
- #
465
- # # Setup ActiveRecord callbacks for auto-publishing
466
- # def setup_publishing_callbacks(config)
467
- # # Only add callbacks if we're in ActiveRecord and actions are specified
468
- # return unless defined?(ActiveRecord::Base) && self < ActiveRecord::Base
469
- #
470
- # actions = config[:actions]
471
- #
472
- # if actions.include?(:create)
473
- # after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
474
- # end
475
- #
476
- # if actions.include?(:update)
477
- # after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
478
- # end
479
- #
480
- # if actions.include?(:destroy)
481
- # after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
482
- # end
483
- # end
484
- #
485
- # # Create a subscription handler that processes data and calls custom handler or auto-sync
486
- # def create_subscription_handler(config)
487
- # model_class = self
488
- #
489
- # lambda do |message|
490
- # begin
491
- # Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
492
- #
493
- # # Extract the raw data
494
- # raw_data = message['data'] || {}
495
- # model_name = message['model']
496
- # action = message['action']
497
- #
498
- # # Process the data through mappings and transformations
499
- # processed_data = process_subscription_data(raw_data, config)
500
- #
501
- # # If custom handler is provided, call it with model_name, action, processed_data
502
- # if config[:handler]
503
- # Rails.logger.debug "📨 Calling custom subscription handler" if defined?(Rails)
504
- # config[:handler].call(model_name, action, processed_data, message)
505
- # elsif config[:auto_sync]
506
- # Rails.logger.debug "📨 Performing auto-sync" if defined?(Rails)
507
- # # Default auto-sync behavior
508
- # model_class.perform_auto_sync(model_name, action, processed_data, config)
509
- # else
510
- # Rails.logger.debug "📨 No handler provided and auto_sync disabled" if defined?(Rails)
511
- # end
512
- #
513
- # rescue => e
514
- # Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
515
- # Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
516
- # raise
517
- # end
518
- # end
519
- # end
520
- #
521
- # # Process subscription data through field mappings and transformations (CLASS METHOD)
522
- # def process_subscription_data(raw_data, config)
523
- # processed_data = {}
524
- # field_mappings = config[:field_mappings]
525
- # transformations = config[:transformations]
526
- # skip_fields = config[:skip_fields]
527
- #
528
- # raw_data.each do |field, value|
529
- # field_str = field.to_s
530
- # field_sym = field.to_sym
531
- #
532
- # # Skip if in skip_fields
533
- # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
534
- #
535
- # # Apply field mapping
536
- # mapped_field = field_mappings[field_str] ||
537
- # field_mappings[field_sym] ||
538
- # field
539
- #
540
- # # Apply transformation if any
541
- # transformed_value = apply_transformation(value, mapped_field, transformations, raw_data)
542
- #
543
- # processed_data[mapped_field.to_s] = transformed_value
544
- # end
545
- #
546
- # processed_data
547
- # end
548
- #
549
- # # Apply transformations to field values (CLASS METHOD)
550
- # def apply_transformation(value, field, transformations, full_record)
551
- # transformation = transformations[field] || transformations[field.to_sym]
552
- #
553
- # case transformation
554
- # when Proc
555
- # if transformation.arity == 2 || transformation.arity < 0
556
- # transformation.call(value, full_record)
557
- # else
558
- # transformation.call(value)
559
- # end
560
- # when Symbol
561
- # if self.respond_to?(transformation, true)
562
- # self.send(transformation, value)
563
- # elsif value.respond_to?(transformation)
564
- # value.send(transformation)
565
- # else
566
- # Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
567
- # value
568
- # end
569
- # else
570
- # value
571
- # end
572
- # end
573
- #
574
- # # Default auto-sync behavior (CLASS METHOD)
575
- # def perform_auto_sync(model_name, action, processed_data, config)
576
- # unique_fields = config[:unique_fields]
577
- # sync_strategy = config[:sync_strategy]
578
- #
579
- # case action.to_s.downcase
580
- # when 'create', 'created'
581
- # handle_auto_create(processed_data, unique_fields, sync_strategy)
582
- # when 'update', 'updated'
583
- # handle_auto_update(processed_data, unique_fields, sync_strategy)
584
- # when 'delete', 'deleted', 'destroy', 'destroyed'
585
- # handle_auto_delete(processed_data, unique_fields)
586
- # else
587
- # Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
588
- # end
589
- # end
590
- #
591
- # def handle_auto_create(data, unique_fields, sync_strategy)
592
- # case sync_strategy
593
- # when :upsert
594
- # existing = find_by_unique_fields(data, unique_fields)
595
- # if existing
596
- # existing.update!(data)
597
- # Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
598
- # else
599
- # record = self.create!(data)
600
- # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
601
- # end
602
- # when :create_only
603
- # record = self.create!(data)
604
- # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
605
- # end
606
- # rescue => e
607
- # Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
608
- # raise
609
- # end
610
- #
611
- # def handle_auto_update(data, unique_fields, sync_strategy)
612
- # existing = find_by_unique_fields(data, unique_fields)
613
- # if existing
614
- # existing.update!(data)
615
- # Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
616
- # elsif sync_strategy == :upsert
617
- # record = self.create!(data)
618
- # Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
619
- # else
620
- # Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
621
- # end
622
- # rescue => e
623
- # Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
624
- # raise
625
- # end
626
- #
627
- # def handle_auto_delete(data, unique_fields)
628
- # existing = find_by_unique_fields(data, unique_fields)
629
- # if existing
630
- # existing.destroy!
631
- # Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
632
- # else
633
- # Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
634
- # end
635
- # rescue => e
636
- # Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
637
- # raise
638
- # end
639
- #
640
- # def find_by_unique_fields(data, unique_fields)
641
- # conditions = {}
642
- # unique_fields.each do |field|
643
- # field_str = field.to_s
644
- # if data.key?(field_str)
645
- # conditions[field] = data[field_str]
646
- # elsif data.key?(field.to_sym)
647
- # conditions[field] = data[field.to_sym]
648
- # end
649
- # end
650
- #
651
- # return nil if conditions.empty?
652
- # self.find_by(conditions)
653
- # end
654
- # end
655
- #
656
- # # Instance methods for publishing
657
- # def nats_wave_publish(action = nil)
658
- # action ||= determine_action_from_context
659
- #
660
- # self.class.nats_wave_publishing_configs.each do |subjects_key, config|
661
- # next unless config[:enabled]
662
- # next unless config[:actions].include?(action.to_sym)
663
- #
664
- # # Check conditions (only for publishing)
665
- # if config[:conditions].any? && !evaluate_conditions(config[:conditions])
666
- # Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
667
- # next
668
- # end
669
- #
670
- # # Get the raw data (current model attributes)
671
- # raw_data = get_raw_attributes
672
- #
673
- # # Process the data through mappings and transformations
674
- # processed_data = process_publishing_data(raw_data, config)
675
- #
676
- # # If custom handler is provided, call it
677
- # if config[:handler]
678
- # Rails.logger.debug "📤 Calling custom publishing handler" if defined?(Rails)
679
- # config[:handler].call(self.class.name, action, processed_data, self)
680
- # else
681
- # # Default publishing behavior - publish the processed data
682
- # config[:subjects].each do |subject|
683
- # NatsWave.client.publish(
684
- # subject: subject,
685
- # model: self.class.name,
686
- # action: action,
687
- # data: processed_data, # This is the processed data, not raw attributes
688
- # metadata: build_publishing_metadata
689
- # )
690
- #
691
- # Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
692
- # end
693
- # end
694
- # end
695
- # rescue StandardError => e
696
- # Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
697
- # # Don't re-raise to avoid breaking transactions
698
- # end
699
- #
700
- # # Auto-publishing callback methods
701
- # def trigger_nats_wave_auto_publish_on_create
702
- # Rails.logger.debug "🚀 Auto-publishing on create" if defined?(Rails)
703
- # nats_wave_publish('create')
704
- # end
705
- #
706
- # def trigger_nats_wave_auto_publish_on_update
707
- # Rails.logger.debug "🚀 Auto-publishing on update" if defined?(Rails)
708
- # nats_wave_publish('update')
709
- # end
710
- #
711
- # def trigger_nats_wave_auto_publish_on_destroy
712
- # Rails.logger.debug "🚀 Auto-publishing on destroy" if defined?(Rails)
713
- # nats_wave_publish('destroy')
714
- # end
715
- #
716
- # private
717
- #
718
- # def determine_action_from_context
719
- # # Try to determine action from ActiveRecord context
720
- # if defined?(ActiveRecord) && is_a?(ActiveRecord::Base)
721
- # return 'create' if previously_new_record?
722
- # return 'update' if saved_changes.any?
723
- # return 'destroy' if destroyed?
724
- # end
725
- #
726
- # 'update' # Default fallback
727
- # end
728
- #
729
- # def get_raw_attributes
730
- # # Get attributes (works for both ActiveRecord and other objects)
731
- # if respond_to?(:attributes)
732
- # attributes
733
- # else
734
- # # For non-ActiveRecord objects, get instance variables
735
- # instance_variables.map { |v| [v.to_s.delete('@'), instance_variable_get(v)] }.to_h
736
- # end
737
- # end
738
- #
739
- # # Process publishing data through field mappings and transformations (INSTANCE METHOD)
740
- # def process_publishing_data(raw_data, config)
741
- # processed_data = {}
742
- # field_mappings = config[:field_mappings]
743
- # transformations = config[:transformations]
744
- # skip_fields = config[:skip_fields]
745
- #
746
- # raw_data.each do |field, value|
747
- # field_str = field.to_s
748
- # field_sym = field.to_sym
749
- #
750
- # # Skip if in skip_fields
751
- # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
752
- #
753
- # # Apply field mapping (local -> external)
754
- # mapped_field = field_mappings[field_str] ||
755
- # field_mappings[field_sym] ||
756
- # field
757
- #
758
- # # Apply transformation if any
759
- # transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
760
- #
761
- # processed_data[mapped_field.to_s] = transformed_value
762
- # end
763
- #
764
- # processed_data
765
- # end
766
- #
767
- # def apply_publishing_transformation(value, field, transformations, full_record)
768
- # transformation = transformations[field] || transformations[field.to_sym]
769
- #
770
- # case transformation
771
- # when Proc
772
- # if transformation.arity == 2 || transformation.arity < 0
773
- # transformation.call(value, full_record)
774
- # else
775
- # transformation.call(value)
776
- # end
777
- # when Symbol
778
- # if self.respond_to?(transformation, true)
779
- # self.send(transformation, value)
780
- # elsif value.respond_to?(transformation)
781
- # value.send(transformation)
782
- # else
783
- # Rails.logger.warn "Publishing transformation method #{transformation} not found" if defined?(Rails)
784
- # value
785
- # end
786
- # else
787
- # value
788
- # end
789
- # end
790
- #
791
- # def evaluate_conditions(conditions)
792
- # conditions.all? do |condition, expected_value|
793
- # case condition
794
- # when Proc
795
- # condition.call(self)
796
- # when Symbol, String
797
- # if respond_to?(condition, true)
798
- # result = send(condition)
799
- # expected_value.nil? ? result : result == expected_value
800
- # else
801
- # false
802
- # end
803
- # else
804
- # false
805
- # end
806
- # end
807
- # end
808
- #
809
- # def build_publishing_metadata
810
- # {
811
- # source_model: self.class.name,
812
- # source_id: respond_to?(:id) ? id : object_id,
813
- # published_at: Time.current.iso8601
814
- # }
815
- # end
816
- # end
817
- # end
818
- # end
819
-
820
1
  # frozen_string_literal: true
821
2
 
822
3
  module NatsWave
@@ -833,7 +14,7 @@ module NatsWave
833
14
  class_methods do
834
15
  # Configure subscriptions with optional custom handler
835
16
  def nats_wave_subscribes_to(*subjects, **options, &block)
836
- Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
17
+ NatsWave.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}"
837
18
 
838
19
  # Custom handler is now optional and runs AFTER default behavior
839
20
  custom_handler = options[:handler] || block
@@ -865,12 +46,12 @@ module NatsWave
865
46
  queue_group: subscription_config[:queue_group]
866
47
  )
867
48
 
868
- Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
49
+ NatsWave.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}"
869
50
  end
870
51
 
871
52
  # Configure publishing with optional custom handler AND auto-publishing callbacks
872
53
  def nats_wave_publishes_to(*subjects, **options, &block)
873
- Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
54
+ NatsWave.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}"
874
55
 
875
56
  # Custom handler is now optional and runs AFTER default behavior
876
57
  custom_handler = options[:handler] || block
@@ -885,7 +66,7 @@ module NatsWave
885
66
  custom_handler: custom_handler, # Renamed to be clear it's optional
886
67
  async: options[:async] != false, # Default to true
887
68
  enabled: options[:enabled] != false, # Default to true
888
- only_mapped_fields: options[:only_mapped_fields] != false # Default to true - only send mapped fields
69
+ only_mapped_fields: options[:only_mapped_fields] != false, # Default to true
889
70
  }
890
71
 
891
72
  # Store the config
@@ -895,7 +76,7 @@ module NatsWave
895
76
  # Add ActiveRecord callbacks for auto-publishing (only once per model)
896
77
  setup_publishing_callbacks_once
897
78
 
898
- Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
79
+ NatsWave.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}"
899
80
  end
900
81
 
901
82
  # Get all subscription configurations
@@ -921,7 +102,7 @@ module NatsWave
921
102
  after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
922
103
 
923
104
  @nats_wave_callbacks_added = true
924
- Rails.logger.debug "📤 #{self.name}: Added publishing callbacks" if defined?(Rails)
105
+ NatsWave.logger.debug "📤 #{self.name}: Added publishing callbacks"
925
106
  end
926
107
 
927
108
  # Create a subscription handler that processes data and calls custom handler AFTER auto-sync
@@ -930,7 +111,7 @@ module NatsWave
930
111
 
931
112
  lambda do |message|
932
113
  begin
933
- Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
114
+ NatsWave.logger.debug "📨 Processing subscription message for #{model_class.name}"
934
115
 
935
116
  # Extract the raw data
936
117
  raw_data = message['data'] || {}
@@ -938,29 +119,29 @@ module NatsWave
938
119
  action = message['action']
939
120
 
940
121
  # Process the data through mappings and transformations
941
- processed_data = process_subscription_data(raw_data, config)
122
+ processed_data = model_class.process_subscription_data(raw_data, config)
942
123
 
943
124
  # Always perform auto-sync first (if enabled)
944
125
  if config[:auto_sync]
945
- Rails.logger.debug "📨 Performing auto-sync first" if defined?(Rails)
126
+ NatsWave.logger.debug "📨 Performing auto-sync first"
946
127
  model_class.perform_auto_sync(model_name, action, processed_data, config)
947
128
  end
948
129
 
949
130
  # Then call custom handler if provided (optional)
950
131
  if config[:custom_handler]
951
- Rails.logger.debug "📨 Calling custom subscription handler after auto-sync" if defined?(Rails)
132
+ NatsWave.logger.debug "📨 Calling custom subscription handler after auto-sync"
952
133
  config[:custom_handler].call(model_name, action, processed_data, message)
953
134
  end
954
135
 
955
136
  rescue => e
956
- Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
957
- Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
137
+ NatsWave.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}"
138
+ NatsWave.logger.error e.backtrace.join("\n")
958
139
  raise
959
140
  end
960
141
  end
961
142
  end
962
143
 
963
- # Process subscription data through field mappings and transformations (CLASS METHOD)
144
+ # Process subscription data through field mappings and transformations (PUBLIC CLASS METHOD)
964
145
  def process_subscription_data(raw_data, config)
965
146
  processed_data = {}
966
147
  field_mappings = config[:field_mappings]
@@ -974,7 +155,7 @@ module NatsWave
974
155
  # Skip if in skip_fields
975
156
  next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
976
157
 
977
- # Apply field mapping
158
+ # Apply field mapping (external -> local)
978
159
  mapped_field = field_mappings[field_str] ||
979
160
  field_mappings[field_sym] ||
980
161
  field
@@ -988,7 +169,7 @@ module NatsWave
988
169
  processed_data
989
170
  end
990
171
 
991
- # Apply transformations to field values (CLASS METHOD)
172
+ # Apply transformations to field values (PUBLIC CLASS METHOD)
992
173
  def apply_transformation(value, field, transformations, full_record)
993
174
  transformation = transformations[field] || transformations[field.to_sym]
994
175
 
@@ -1005,7 +186,7 @@ module NatsWave
1005
186
  elsif value.respond_to?(transformation)
1006
187
  value.send(transformation)
1007
188
  else
1008
- Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
189
+ NatsWave.logger.warn "Transformation method #{transformation} not found"
1009
190
  value
1010
191
  end
1011
192
  else
@@ -1013,7 +194,7 @@ module NatsWave
1013
194
  end
1014
195
  end
1015
196
 
1016
- # Default auto-sync behavior (CLASS METHOD)
197
+ # Default auto-sync behavior (PUBLIC CLASS METHOD)
1017
198
  def perform_auto_sync(model_name, action, processed_data, config)
1018
199
  unique_fields = config[:unique_fields]
1019
200
  sync_strategy = config[:sync_strategy]
@@ -1026,7 +207,7 @@ module NatsWave
1026
207
  when 'delete', 'deleted', 'destroy', 'destroyed'
1027
208
  handle_auto_delete(processed_data, unique_fields)
1028
209
  else
1029
- Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
210
+ NatsWave.logger.warn "Unknown action for auto-sync: #{action}"
1030
211
  end
1031
212
  end
1032
213
 
@@ -1036,17 +217,17 @@ module NatsWave
1036
217
  existing = find_by_unique_fields(data, unique_fields)
1037
218
  if existing
1038
219
  existing.update!(data)
1039
- Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
220
+ NatsWave.logger.info "✅ Updated existing #{self.name}: #{existing.id}"
1040
221
  else
1041
222
  record = self.create!(data)
1042
- Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
223
+ NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
1043
224
  end
1044
225
  when :create_only
1045
226
  record = self.create!(data)
1046
- Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
227
+ NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
1047
228
  end
1048
229
  rescue => e
1049
- Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
230
+ NatsWave.logger.error "❌ Failed to create #{self.name}: #{e.message}"
1050
231
  raise
1051
232
  end
1052
233
 
@@ -1054,15 +235,15 @@ module NatsWave
1054
235
  existing = find_by_unique_fields(data, unique_fields)
1055
236
  if existing
1056
237
  existing.update!(data)
1057
- Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
238
+ NatsWave.logger.info "✅ Updated #{self.name}: #{existing.id}"
1058
239
  elsif sync_strategy == :upsert
1059
240
  record = self.create!(data)
1060
- Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
241
+ NatsWave.logger.info "✅ Created new #{self.name} during update: #{record.id}"
1061
242
  else
1062
- Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
243
+ NatsWave.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}"
1063
244
  end
1064
245
  rescue => e
1065
- Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
246
+ NatsWave.logger.error "❌ Failed to update #{self.name}: #{e.message}"
1066
247
  raise
1067
248
  end
1068
249
 
@@ -1070,12 +251,12 @@ module NatsWave
1070
251
  existing = find_by_unique_fields(data, unique_fields)
1071
252
  if existing
1072
253
  existing.destroy!
1073
- Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
254
+ NatsWave.logger.info "✅ Deleted #{self.name}: #{existing.id}"
1074
255
  else
1075
- Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
256
+ NatsWave.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}"
1076
257
  end
1077
258
  rescue => e
1078
- Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
259
+ NatsWave.logger.error "❌ Failed to delete #{self.name}: #{e.message}"
1079
260
  raise
1080
261
  end
1081
262
 
@@ -1105,7 +286,7 @@ module NatsWave
1105
286
 
1106
287
  # Check conditions (only for publishing)
1107
288
  if config[:conditions].any? && !evaluate_conditions(config[:conditions])
1108
- Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
289
+ NatsWave.logger.debug "📤 Skipping publish - conditions not met"
1109
290
  next
1110
291
  end
1111
292
 
@@ -1128,17 +309,17 @@ module NatsWave
1128
309
  metadata: build_publishing_metadata
1129
310
  )
1130
311
 
1131
- Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
312
+ NatsWave.logger.info "📤 Published #{self.class.name} to #{subject}"
1132
313
  end
1133
314
 
1134
315
  # Then call custom handler if provided (optional)
1135
316
  if config[:custom_handler]
1136
- Rails.logger.debug "📤 Calling custom publishing handler after publishing" if defined?(Rails)
317
+ NatsWave.logger.debug "📤 Calling custom publishing handler after publishing"
1137
318
  config[:custom_handler].call(self.class.name, action, processed_data, self)
1138
319
  end
1139
320
  end
1140
321
  rescue StandardError => e
1141
- Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
322
+ NatsWave.logger.error("Failed to publish: #{e.message}")
1142
323
  # Don't re-raise to avoid breaking transactions
1143
324
  end
1144
325
 
@@ -1147,7 +328,7 @@ module NatsWave
1147
328
  return if @nats_wave_publishing_in_progress
1148
329
  @nats_wave_publishing_in_progress = true
1149
330
 
1150
- Rails.logger.debug "🚀 Auto-publishing on create" if defined?(Rails)
331
+ NatsWave.logger.debug "🚀 Auto-publishing on create"
1151
332
  nats_wave_publish('create')
1152
333
 
1153
334
  @nats_wave_publishing_in_progress = false
@@ -1157,7 +338,7 @@ module NatsWave
1157
338
  return if @nats_wave_publishing_in_progress
1158
339
  @nats_wave_publishing_in_progress = true
1159
340
 
1160
- Rails.logger.debug "🚀 Auto-publishing on update" if defined?(Rails)
341
+ NatsWave.logger.debug "🚀 Auto-publishing on update"
1161
342
  nats_wave_publish('update')
1162
343
 
1163
344
  @nats_wave_publishing_in_progress = false
@@ -1167,7 +348,7 @@ module NatsWave
1167
348
  return if @nats_wave_publishing_in_progress
1168
349
  @nats_wave_publishing_in_progress = true
1169
350
 
1170
- Rails.logger.debug "🚀 Auto-publishing on destroy" if defined?(Rails)
351
+ NatsWave.logger.debug "🚀 Auto-publishing on destroy"
1171
352
  nats_wave_publish('destroy')
1172
353
 
1173
354
  @nats_wave_publishing_in_progress = false
@@ -1196,45 +377,49 @@ module NatsWave
1196
377
  end
1197
378
  end
1198
379
 
1199
- # Process publishing data through field mappings and transformations (INSTANCE METHOD)
1200
380
  def process_publishing_data(raw_data, config)
1201
381
  processed_data = {}
1202
- field_mappings = config[:field_mappings]
1203
- transformations = config[:transformations]
1204
- skip_fields = config[:skip_fields]
382
+ field_mappings = config[:field_mappings] || {}
383
+ transformations = config[:transformations] || {}
384
+ skip_fields = config[:skip_fields] || []
1205
385
  only_mapped_fields = config[:only_mapped_fields]
1206
386
 
1207
- # If only_mapped_fields is true, only process fields that have mappings or transformations
1208
- fields_to_process = if only_mapped_fields && field_mappings.any?
1209
- # Only process fields that are explicitly mapped or have transformations
1210
- mapped_source_fields = field_mappings.keys.map(&:to_s)
1211
- transformation_fields = transformations.keys.map(&:to_s)
1212
- all_relevant_fields = (mapped_source_fields + transformation_fields).uniq
1213
-
1214
- raw_data.select { |field, _| all_relevant_fields.include?(field.to_s) }
1215
- else
1216
- # Process all fields (existing behavior)
1217
- raw_data
1218
- end
1219
-
1220
- fields_to_process.each do |field, value|
1221
- field_str = field.to_s
1222
- field_sym = field.to_sym
1223
-
1224
- # Skip if in skip_fields
1225
- next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
1226
-
1227
- # Apply field mapping (local -> external)
1228
- mapped_field = field_mappings[field_str] ||
1229
- field_mappings[field_sym] ||
1230
- field
1231
-
1232
- # Apply transformation if any
1233
- transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
1234
-
1235
- processed_data[mapped_field.to_s] = transformed_value
387
+ # If only_mapped_fields is true, only process fields that have explicit mappings
388
+ if only_mapped_fields && field_mappings.any?
389
+ field_mappings.each do |local_field, external_field|
390
+ local_field_str = local_field.to_s
391
+
392
+ # Skip if this field is in skip_fields
393
+ next if skip_fields.include?(local_field_str) || skip_fields.include?(local_field.to_sym)
394
+
395
+ # Get the value from raw_data
396
+ value = raw_data[local_field_str] || raw_data[local_field.to_sym]
397
+
398
+ # Apply transformation if any (use external field name for transformation lookup)
399
+ transformed_value = apply_publishing_transformation(value, external_field, transformations, raw_data)
400
+
401
+ processed_data[external_field.to_s] = transformed_value
402
+ end
403
+ else
404
+ # Original behavior - process all fields
405
+ raw_data.each do |field, value|
406
+ field_str = field.to_s
407
+ field_sym = field.to_sym
408
+
409
+ # Skip if in skip_fields
410
+ next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
411
+
412
+ # Apply field mapping (local -> external) - ONLY if mapping exists
413
+ mapped_field = field_mappings[field_str] ||
414
+ field_mappings[field_sym] ||
415
+ field # Use original field name if no mapping
416
+
417
+ # Apply transformation if any
418
+ transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
419
+
420
+ processed_data[mapped_field.to_s] = transformed_value
421
+ end
1236
422
  end
1237
-
1238
423
  processed_data
1239
424
  end
1240
425
 
@@ -1254,7 +439,7 @@ module NatsWave
1254
439
  elsif value.respond_to?(transformation)
1255
440
  value.send(transformation)
1256
441
  else
1257
- Rails.logger.warn "Publishing transformation method #{transformation} not found" if defined?(Rails)
442
+ NatsWave.logger.warn "Publishing transformation method #{transformation} not found"
1258
443
  value
1259
444
  end
1260
445
  else