deimos-ruby 1.8.6 → 1.10.0
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 +35 -0
- data/Gemfile.lock +106 -103
- data/deimos-ruby.gemspec +4 -3
- data/docs/ARCHITECTURE.md +1 -5
- data/docs/CONFIGURATION.md +1 -0
- data/lib/deimos.rb +2 -1
- data/lib/deimos/active_record_consume/message_consumption.rb +5 -0
- data/lib/deimos/config/configuration.rb +13 -13
- data/lib/deimos/kafka_source.rb +8 -12
- data/lib/deimos/test_helpers.rb +1 -1
- data/lib/deimos/utils/db_poller.rb +1 -1
- data/lib/deimos/version.rb +1 -1
- data/spec/config/configuration_spec.rb +17 -17
- data/spec/kafka_source_spec.rb +69 -0
- metadata +30 -14
- data/lib/deimos/config/configurable.rb +0 -278
- data/lib/deimos/monkey_patches/ruby_kafka_heartbeat.rb +0 -85
- data/spec/config/configurable_spec.rb +0 -136
@@ -58,6 +58,11 @@ module Deimos
|
|
58
58
|
attrs.each do |k, v|
|
59
59
|
record.send("#{k}=", v)
|
60
60
|
end
|
61
|
+
save_record(record)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param record [ActiveRecord::Base]
|
65
|
+
def save_record(record)
|
61
66
|
record.created_at ||= Time.zone.now if record.respond_to?(:created_at)
|
62
67
|
record.updated_at = Time.zone.now if record.respond_to?(:updated_at)
|
63
68
|
record.save!
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'fig_tree'
|
3
4
|
require_relative 'phobos_config'
|
4
|
-
require_relative 'configurable'
|
5
5
|
require_relative '../metrics/mock'
|
6
6
|
require_relative '../tracing/mock'
|
7
7
|
require 'active_support/core_ext/numeric'
|
8
8
|
|
9
9
|
# :nodoc:
|
10
10
|
module Deimos
|
11
|
-
include
|
11
|
+
include FigTree
|
12
12
|
|
13
13
|
# :nodoc:
|
14
|
-
class
|
14
|
+
class FigTree::ConfigStruct
|
15
15
|
include Deimos::PhobosConfig
|
16
16
|
end
|
17
17
|
|
@@ -60,7 +60,7 @@ module Deimos
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
# @param kafka_config [
|
63
|
+
# @param kafka_config [FigTree::ConfigStruct]
|
64
64
|
def self.configure_producer_or_consumer(kafka_config)
|
65
65
|
klass = kafka_config.class_name.constantize
|
66
66
|
klass.class_eval do
|
@@ -327,19 +327,19 @@ module Deimos
|
|
327
327
|
# These are the phobos "listener" configs. See CONFIGURATION.md for more
|
328
328
|
# info.
|
329
329
|
setting :group_id
|
330
|
-
setting :max_concurrency
|
331
|
-
setting :start_from_beginning
|
330
|
+
setting :max_concurrency, 1
|
331
|
+
setting :start_from_beginning, true
|
332
332
|
setting :max_bytes_per_partition, 500.kilobytes
|
333
|
-
setting :min_bytes
|
334
|
-
setting :max_wait_time
|
333
|
+
setting :min_bytes, 1
|
334
|
+
setting :max_wait_time, 5
|
335
335
|
setting :force_encoding
|
336
|
-
setting :delivery
|
336
|
+
setting :delivery, :batch
|
337
337
|
setting :backoff
|
338
|
-
setting :session_timeout
|
339
|
-
setting :offset_commit_interval
|
340
|
-
setting :offset_commit_threshold
|
338
|
+
setting :session_timeout, 300
|
339
|
+
setting :offset_commit_interval, 10
|
340
|
+
setting :offset_commit_threshold, 0
|
341
341
|
setting :offset_retention_time
|
342
|
-
setting :heartbeat_interval
|
342
|
+
setting :heartbeat_interval, 10
|
343
343
|
end
|
344
344
|
|
345
345
|
setting_object :db_poller do
|
data/lib/deimos/kafka_source.rb
CHANGED
@@ -6,6 +6,9 @@ module Deimos
|
|
6
6
|
module KafkaSource
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
+
DEPRECATION_WARNING = 'The kafka_producer interface will be deprecated ' \
|
10
|
+
'in future releases. Please use kafka_producers instead.'
|
11
|
+
|
9
12
|
included do
|
10
13
|
after_create(:send_kafka_event_on_create)
|
11
14
|
after_update(:send_kafka_event_on_update)
|
@@ -64,19 +67,12 @@ module Deimos
|
|
64
67
|
|
65
68
|
# @return [Array<Deimos::ActiveRecordProducer>] the producers to run.
|
66
69
|
def kafka_producers
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
# Deprecated - use #kafka_producers instead.
|
74
|
-
# @return [Deimos::ActiveRecordProducer] the producer to use.
|
75
|
-
def kafka_producer
|
76
|
-
raise NotImplementedError if self.method(:kafka_producers).
|
77
|
-
owner == Deimos::KafkaSource
|
70
|
+
if self.respond_to?(:kafka_producer)
|
71
|
+
Deimos.config.logger.warn(message: DEPRECATION_WARNING)
|
72
|
+
return [self.kafka_producer]
|
73
|
+
end
|
78
74
|
|
79
|
-
|
75
|
+
raise NotImplementedError
|
80
76
|
end
|
81
77
|
|
82
78
|
# This is an internal method, part of the activerecord_import gem. It's
|
data/lib/deimos/test_helpers.rb
CHANGED
@@ -68,7 +68,7 @@ module Deimos
|
|
68
68
|
|
69
69
|
# Grab the PollInfo or create if it doesn't exist.
|
70
70
|
def retrieve_poll_info
|
71
|
-
ActiveRecord::Base.connection.reconnect!
|
71
|
+
ActiveRecord::Base.connection.reconnect! unless ActiveRecord::Base.connection.open_transactions.positive?
|
72
72
|
new_time = @config.start_from_beginning ? Time.new(0) : Time.zone.now
|
73
73
|
@info = Deimos::PollInfo.find_by_producer(@config.producer_class) ||
|
74
74
|
Deimos::PollInfo.create!(producer: @config.producer_class,
|
data/lib/deimos/version.rb
CHANGED
@@ -74,34 +74,34 @@ describe Deimos, 'configuration' do
|
|
74
74
|
{
|
75
75
|
topic: 'my_consume_topic',
|
76
76
|
group_id: 'my_group_id',
|
77
|
-
max_concurrency:
|
78
|
-
start_from_beginning:
|
77
|
+
max_concurrency: 1,
|
78
|
+
start_from_beginning: true,
|
79
79
|
max_bytes_per_partition: 524_288,
|
80
|
-
min_bytes:
|
81
|
-
max_wait_time:
|
80
|
+
min_bytes: 1,
|
81
|
+
max_wait_time: 5,
|
82
82
|
force_encoding: nil,
|
83
|
-
delivery:
|
84
|
-
session_timeout:
|
85
|
-
offset_commit_interval:
|
86
|
-
offset_commit_threshold:
|
83
|
+
delivery: 'batch',
|
84
|
+
session_timeout: 300,
|
85
|
+
offset_commit_interval: 10,
|
86
|
+
offset_commit_threshold: 0,
|
87
87
|
offset_retention_time: nil,
|
88
|
-
heartbeat_interval:
|
88
|
+
heartbeat_interval: 10,
|
89
89
|
handler: 'ConsumerTest::MyConsumer'
|
90
90
|
}, {
|
91
91
|
topic: 'my_batch_consume_topic',
|
92
92
|
group_id: 'my_batch_group_id',
|
93
|
-
max_concurrency:
|
94
|
-
start_from_beginning:
|
93
|
+
max_concurrency: 1,
|
94
|
+
start_from_beginning: true,
|
95
95
|
max_bytes_per_partition: 500.kilobytes,
|
96
|
-
min_bytes:
|
97
|
-
max_wait_time:
|
96
|
+
min_bytes: 1,
|
97
|
+
max_wait_time: 5,
|
98
98
|
force_encoding: nil,
|
99
99
|
delivery: 'inline_batch',
|
100
|
-
session_timeout:
|
101
|
-
offset_commit_interval:
|
102
|
-
offset_commit_threshold:
|
100
|
+
session_timeout: 300,
|
101
|
+
offset_commit_interval: 10,
|
102
|
+
offset_commit_threshold: 0,
|
103
103
|
offset_retention_time: nil,
|
104
|
-
heartbeat_interval:
|
104
|
+
heartbeat_interval: 10,
|
105
105
|
handler: 'ConsumerTest::MyBatchConsumer'
|
106
106
|
}
|
107
107
|
],
|
data/spec/kafka_source_spec.rb
CHANGED
@@ -308,5 +308,74 @@ module KafkaSourceSpec
|
|
308
308
|
}, widgets[1].id)
|
309
309
|
end
|
310
310
|
end
|
311
|
+
|
312
|
+
context 'with AR models that implement the kafka_producer interface' do
|
313
|
+
before(:each) do
|
314
|
+
# Dummy class we can include the mixin in. Has a backing table created
|
315
|
+
# earlier and has the import hook disabled
|
316
|
+
deprecated_class = Class.new(ActiveRecord::Base) do
|
317
|
+
include Deimos::KafkaSource
|
318
|
+
self.table_name = 'widgets'
|
319
|
+
|
320
|
+
# :nodoc:
|
321
|
+
def self.kafka_config
|
322
|
+
{
|
323
|
+
update: true,
|
324
|
+
delete: true,
|
325
|
+
import: false,
|
326
|
+
create: true
|
327
|
+
}
|
328
|
+
end
|
329
|
+
|
330
|
+
# :nodoc:
|
331
|
+
def self.kafka_producer
|
332
|
+
WidgetProducer
|
333
|
+
end
|
334
|
+
end
|
335
|
+
stub_const('WidgetDeprecated', deprecated_class)
|
336
|
+
WidgetDeprecated.reset_column_information
|
337
|
+
end
|
338
|
+
|
339
|
+
it 'logs a warning and sends the message as usual' do
|
340
|
+
expect(Deimos.config.logger).to receive(:warn).with({ message: WidgetDeprecated::DEPRECATION_WARNING })
|
341
|
+
widget = WidgetDeprecated.create(widget_id: 1, name: 'Widget 1')
|
342
|
+
expect('my-topic').to have_sent({
|
343
|
+
widget_id: 1,
|
344
|
+
name: 'Widget 1',
|
345
|
+
id: widget.id,
|
346
|
+
created_at: anything,
|
347
|
+
updated_at: anything
|
348
|
+
}, widget.id)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context 'with AR models that do not implement any producer interface' do
|
353
|
+
before(:each) do
|
354
|
+
# Dummy class we can include the mixin in. Has a backing table created
|
355
|
+
# earlier and has the import hook disabled
|
356
|
+
buggy_class = Class.new(ActiveRecord::Base) do
|
357
|
+
include Deimos::KafkaSource
|
358
|
+
self.table_name = 'widgets'
|
359
|
+
|
360
|
+
# :nodoc:
|
361
|
+
def self.kafka_config
|
362
|
+
{
|
363
|
+
update: true,
|
364
|
+
delete: true,
|
365
|
+
import: false,
|
366
|
+
create: true
|
367
|
+
}
|
368
|
+
end
|
369
|
+
end
|
370
|
+
stub_const('WidgetBuggy', buggy_class)
|
371
|
+
WidgetBuggy.reset_column_information
|
372
|
+
end
|
373
|
+
|
374
|
+
it 'raises a NotImplementedError exception' do
|
375
|
+
expect {
|
376
|
+
WidgetBuggy.create(widget_id: 1, name: 'Widget 1')
|
377
|
+
}.to raise_error(NotImplementedError)
|
378
|
+
end
|
379
|
+
end
|
311
380
|
end
|
312
381
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deimos-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Orner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: avro_turf
|
@@ -28,44 +28,64 @@ dependencies:
|
|
28
28
|
name: phobos
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.9'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3.0'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '1.9'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.0'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: ruby-kafka
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
|
-
- - "
|
51
|
+
- - "<"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
53
|
+
version: '2'
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
|
-
- - "
|
58
|
+
- - "<"
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
60
|
+
version: '2'
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
62
|
name: sigurd
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
|
-
- -
|
65
|
+
- - "~>"
|
60
66
|
- !ruby/object:Gem::Version
|
61
67
|
version: 0.0.1
|
62
68
|
type: :runtime
|
63
69
|
prerelease: false
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
|
-
- -
|
72
|
+
- - "~>"
|
67
73
|
- !ruby/object:Gem::Version
|
68
74
|
version: 0.0.1
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: fig_tree
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.0.2
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.0.2
|
69
89
|
- !ruby/object:Gem::Dependency
|
70
90
|
name: activerecord-import
|
71
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -364,7 +384,6 @@ files:
|
|
364
384
|
- lib/deimos/backends/kafka_async.rb
|
365
385
|
- lib/deimos/backends/test.rb
|
366
386
|
- lib/deimos/batch_consumer.rb
|
367
|
-
- lib/deimos/config/configurable.rb
|
368
387
|
- lib/deimos/config/configuration.rb
|
369
388
|
- lib/deimos/config/phobos_config.rb
|
370
389
|
- lib/deimos/consume/batch_consumption.rb
|
@@ -380,7 +399,6 @@ files:
|
|
380
399
|
- lib/deimos/metrics/provider.rb
|
381
400
|
- lib/deimos/monkey_patches/phobos_cli.rb
|
382
401
|
- lib/deimos/monkey_patches/phobos_producer.rb
|
383
|
-
- lib/deimos/monkey_patches/ruby_kafka_heartbeat.rb
|
384
402
|
- lib/deimos/poll_info.rb
|
385
403
|
- lib/deimos/producer.rb
|
386
404
|
- lib/deimos/railtie.rb
|
@@ -423,7 +441,6 @@ files:
|
|
423
441
|
- spec/backends/kafka_async_spec.rb
|
424
442
|
- spec/backends/kafka_spec.rb
|
425
443
|
- spec/batch_consumer_spec.rb
|
426
|
-
- spec/config/configurable_spec.rb
|
427
444
|
- spec/config/configuration_spec.rb
|
428
445
|
- spec/consumer_spec.rb
|
429
446
|
- spec/deimos_spec.rb
|
@@ -507,7 +524,6 @@ test_files:
|
|
507
524
|
- spec/backends/kafka_async_spec.rb
|
508
525
|
- spec/backends/kafka_spec.rb
|
509
526
|
- spec/batch_consumer_spec.rb
|
510
|
-
- spec/config/configurable_spec.rb
|
511
527
|
- spec/config/configuration_spec.rb
|
512
528
|
- spec/consumer_spec.rb
|
513
529
|
- spec/deimos_spec.rb
|
@@ -1,278 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require 'active_support/callbacks'
|
5
|
-
|
6
|
-
module Deimos
|
7
|
-
# Module to allow configuration. Loosely based off of the dry-configuration
|
8
|
-
# gem but with several advantages:
|
9
|
-
# - Works with Ruby 2.3.
|
10
|
-
# - More succinct syntax using method_missing so you do not need to write
|
11
|
-
# "config.whatever" and can just write "whatever".
|
12
|
-
# - Use nested blocks:
|
13
|
-
# Deimos.configure do
|
14
|
-
# config.kafka.ssl do
|
15
|
-
# enabled true
|
16
|
-
# ca_cert_file 'my_file'
|
17
|
-
# end
|
18
|
-
# config.kafka do
|
19
|
-
# ssl do
|
20
|
-
# enabled true
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
# - Allows for arrays of configurations:
|
25
|
-
# Deimos.configure do |config|
|
26
|
-
# config.producer do
|
27
|
-
# class_name 'MyProducer'
|
28
|
-
# topic 'MyTopic'
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
# - Allows to call `configure` multiple times without crashing.
|
32
|
-
# - Allows to lazy-set default values by passing a proc as a default:
|
33
|
-
# Deimos.define_settings do |config|
|
34
|
-
# setting :my_val, default_proc: proc { MyDefault.calculated_value }
|
35
|
-
# end
|
36
|
-
# - Support for setting up and automatically calling deprecated configurations.
|
37
|
-
# - Support for configuration callbacks.
|
38
|
-
module Configurable
|
39
|
-
extend ActiveSupport::Concern
|
40
|
-
|
41
|
-
ConfigValue = Struct.new(:value, :default_value, :default_proc, :deprecation) do
|
42
|
-
|
43
|
-
# Reset value back to default.
|
44
|
-
def reset!
|
45
|
-
if self.value.is_a?(ConfigStruct)
|
46
|
-
self.value.reset!
|
47
|
-
else
|
48
|
-
self.value = self.default_value
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# :nodoc:
|
53
|
-
def clone_and_reset
|
54
|
-
setting = ConfigValue.new(self.value, self.default_value,
|
55
|
-
self.default_proc, self.deprecation)
|
56
|
-
setting.reset!
|
57
|
-
setting
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
# Class that defines and keeps the configuration values.
|
63
|
-
class ConfigStruct
|
64
|
-
include ActiveSupport::Callbacks
|
65
|
-
|
66
|
-
define_callbacks :configure
|
67
|
-
|
68
|
-
# @param name [String]
|
69
|
-
def initialize(name)
|
70
|
-
@name = name
|
71
|
-
@settings = {}
|
72
|
-
@setting_objects = {}
|
73
|
-
@setting_templates = {}
|
74
|
-
end
|
75
|
-
|
76
|
-
# Reset config back to default values.
|
77
|
-
def reset!
|
78
|
-
@setting_objects = @setting_templates.map { |k, _| [k, []] }.to_h
|
79
|
-
@settings.values.each(&:reset!)
|
80
|
-
end
|
81
|
-
|
82
|
-
# Mark a configuration as deprecated and replaced with the new config.
|
83
|
-
# @param old_config [String]
|
84
|
-
# @param new_config [String]
|
85
|
-
def deprecate(old_config, new_config)
|
86
|
-
@settings[old_config.to_sym] ||= ConfigValue.new
|
87
|
-
@settings[old_config.to_sym].deprecation = new_config
|
88
|
-
end
|
89
|
-
|
90
|
-
# :nodoc:
|
91
|
-
def inspect
|
92
|
-
"#{@name}: #{@settings.inspect} #{@setting_objects.inspect}"
|
93
|
-
end
|
94
|
-
|
95
|
-
# @return [Hash]
|
96
|
-
def to_h
|
97
|
-
@settings.map { |k, v| [k, v.value] }.to_h
|
98
|
-
end
|
99
|
-
|
100
|
-
# :nodoc:
|
101
|
-
def clone_and_reset
|
102
|
-
new_config = self.clone
|
103
|
-
new_config.setting_objects = new_config.setting_objects.clone
|
104
|
-
new_config.settings = new_config.settings.map { |k, v| [k, v.clone_and_reset] }.to_h
|
105
|
-
new_config
|
106
|
-
end
|
107
|
-
|
108
|
-
# Define a setting template for an array of objects via a block:
|
109
|
-
# setting_object :producer do
|
110
|
-
# setting :topic
|
111
|
-
# setting :class_name
|
112
|
-
# end
|
113
|
-
# This will create the `producer` method to define these values as well
|
114
|
-
# as the `producer_objects` method to retrieve them.
|
115
|
-
# @param name [Symbol]
|
116
|
-
def setting_object(name, &block)
|
117
|
-
new_config = ConfigStruct.new("#{@name}.#{name}")
|
118
|
-
@setting_objects[name] = []
|
119
|
-
@setting_templates[name] = new_config
|
120
|
-
new_config.instance_eval(&block)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Define a setting with the given name.
|
124
|
-
# @param name [Symbol]
|
125
|
-
# @param default_value [Object]
|
126
|
-
# @param default_proc [Proc]
|
127
|
-
def setting(name, default_value=nil, default_proc: nil, &block)
|
128
|
-
if block_given?
|
129
|
-
# Create a nested setting
|
130
|
-
setting_config = @settings[name]&.value || ConfigStruct.new("#{@name}.#{name}")
|
131
|
-
setting = ConfigValue.new
|
132
|
-
setting.value = setting_config
|
133
|
-
@settings[name] = setting
|
134
|
-
setting_config.instance_eval(&block)
|
135
|
-
else
|
136
|
-
setting = ConfigValue.new
|
137
|
-
setting.default_proc = default_proc
|
138
|
-
setting.default_value = default_value
|
139
|
-
setting.reset!
|
140
|
-
@settings[name] = setting
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# :nodoc:
|
145
|
-
def respond_to_missing?(method, include_all=true)
|
146
|
-
method = method.to_s.sub(/=$/, '')
|
147
|
-
method.ends_with?('objects') ||
|
148
|
-
@setting_templates.key?(method.to_sym) ||
|
149
|
-
@settings.key?(method.to_sym) ||
|
150
|
-
super
|
151
|
-
end
|
152
|
-
|
153
|
-
# :nodoc:
|
154
|
-
def method_missing(method, *args, &block)
|
155
|
-
config_key = method.to_s.sub(/=$/, '').to_sym
|
156
|
-
|
157
|
-
# Return the list of setting objects with the given name
|
158
|
-
if config_key.to_s.end_with?('objects')
|
159
|
-
return _setting_object_method(config_key)
|
160
|
-
end
|
161
|
-
|
162
|
-
# Define a new setting object with the given name
|
163
|
-
if @setting_templates.key?(config_key) && block_given?
|
164
|
-
return _new_setting_object_method(config_key, &block)
|
165
|
-
end
|
166
|
-
|
167
|
-
setting = @settings[config_key]
|
168
|
-
|
169
|
-
if setting&.deprecation
|
170
|
-
return _deprecated_config_method(method, *args)
|
171
|
-
end
|
172
|
-
|
173
|
-
return super unless setting
|
174
|
-
|
175
|
-
if block_given?
|
176
|
-
return _block_config_method(config_key, &block)
|
177
|
-
end
|
178
|
-
|
179
|
-
_default_config_method(config_key, *args)
|
180
|
-
end
|
181
|
-
|
182
|
-
protected
|
183
|
-
|
184
|
-
# Only for the clone method
|
185
|
-
attr_accessor :settings, :setting_objects
|
186
|
-
|
187
|
-
private
|
188
|
-
|
189
|
-
def _deprecated_config_method(method, *args)
|
190
|
-
config_key = method.to_s.sub(/=$/, '').to_sym
|
191
|
-
new_config = @settings[config_key].deprecation
|
192
|
-
equals = method.to_s.end_with?('=') ? '=' : ''
|
193
|
-
ActiveSupport::Deprecation.warn("config.#{config_key}#{equals} is deprecated - use config.#{new_config}#{equals}")
|
194
|
-
obj = self
|
195
|
-
messages = new_config.split('.')
|
196
|
-
messages[0..-2].each do |message|
|
197
|
-
obj = obj.send(message)
|
198
|
-
end
|
199
|
-
if args.length.positive?
|
200
|
-
obj.send(messages[-1], args[0])
|
201
|
-
else
|
202
|
-
obj.send(messages[-1])
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
# Get or set a value.
|
207
|
-
def _default_config_method(config_key, *args)
|
208
|
-
if args.length.positive?
|
209
|
-
# Set the value
|
210
|
-
@settings[config_key].value = args[0]
|
211
|
-
else
|
212
|
-
# Get the value
|
213
|
-
setting = @settings[config_key]
|
214
|
-
if setting.default_proc && setting.value.nil?
|
215
|
-
setting.value = setting.default_proc.call
|
216
|
-
end
|
217
|
-
setting.value
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
# Define a new setting object and use the passed block to define values.
|
222
|
-
def _new_setting_object_method(config_key, &block)
|
223
|
-
new_config = @setting_templates[config_key].clone_and_reset
|
224
|
-
new_config.instance_eval(&block)
|
225
|
-
@setting_objects[config_key] << new_config
|
226
|
-
end
|
227
|
-
|
228
|
-
# Return a setting object.
|
229
|
-
def _setting_object_method(config_key)
|
230
|
-
key = config_key.to_s.sub(/_objects$/, '').to_sym
|
231
|
-
@setting_objects[key]
|
232
|
-
end
|
233
|
-
|
234
|
-
# Define new values inside a block.
|
235
|
-
def _block_config_method(config_key, &block)
|
236
|
-
unless @settings[config_key].value.is_a?(ConfigStruct)
|
237
|
-
raise "Block called for #{config_key} but it is not a nested config!"
|
238
|
-
end
|
239
|
-
|
240
|
-
@settings[config_key].value.instance_eval(&block)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
# :nodoc:
|
245
|
-
module ClassMethods
|
246
|
-
# Define and redefine settings.
|
247
|
-
def define_settings(&block)
|
248
|
-
config.instance_eval(&block)
|
249
|
-
end
|
250
|
-
|
251
|
-
# Configure the settings with values.
|
252
|
-
def configure(&block)
|
253
|
-
if defined?(Rake) && defined?(Rake.application)
|
254
|
-
tasks = Rake.application.top_level_tasks
|
255
|
-
if tasks.any? { |t| %w(assets webpacker yarn).include?(t.split(':').first) }
|
256
|
-
puts 'Skipping Deimos configuration since we are in JS/CSS compilation'
|
257
|
-
return
|
258
|
-
end
|
259
|
-
end
|
260
|
-
config.run_callbacks(:configure) do
|
261
|
-
config.instance_eval(&block)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
# @return [ConfigStruct]
|
266
|
-
def config
|
267
|
-
@config ||= ConfigStruct.new('config')
|
268
|
-
end
|
269
|
-
|
270
|
-
# Pass a block to run after configuration is done.
|
271
|
-
def after_configure(&block)
|
272
|
-
mod = self
|
273
|
-
config.class.set_callback(:configure, :after,
|
274
|
-
proc { mod.instance_eval(&block) })
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|