dry-system 0.19.2 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +472 -1
  3. data/LICENSE +1 -1
  4. data/README.md +4 -3
  5. data/dry-system.gemspec +16 -15
  6. data/lib/dry/system/auto_registrar.rb +1 -13
  7. data/lib/dry/system/component.rb +104 -47
  8. data/lib/dry/system/component_dir.rb +88 -47
  9. data/lib/dry/system/components.rb +8 -4
  10. data/lib/dry/system/config/component_dir.rb +141 -53
  11. data/lib/dry/system/config/component_dirs.rb +176 -70
  12. data/lib/dry/system/config/namespace.rb +76 -0
  13. data/lib/dry/system/config/namespaces.rb +208 -0
  14. data/lib/dry/system/constants.rb +2 -2
  15. data/lib/dry/system/container.rb +279 -201
  16. data/lib/dry/system/errors.rb +72 -61
  17. data/lib/dry/system/identifier.rb +99 -79
  18. data/lib/dry/system/importer.rb +83 -12
  19. data/lib/dry/system/indirect_component.rb +65 -0
  20. data/lib/dry/system/loader.rb +8 -4
  21. data/lib/dry/system/{manual_registrar.rb → manifest_registrar.rb} +12 -13
  22. data/lib/dry/system/plugins/bootsnap.rb +3 -2
  23. data/lib/dry/system/plugins/dependency_graph/strategies.rb +37 -1
  24. data/lib/dry/system/plugins/dependency_graph.rb +26 -20
  25. data/lib/dry/system/plugins/env.rb +3 -2
  26. data/lib/dry/system/plugins/logging.rb +9 -5
  27. data/lib/dry/system/plugins/monitoring.rb +1 -1
  28. data/lib/dry/system/plugins/notifications.rb +1 -1
  29. data/lib/dry/system/plugins/zeitwerk/compat_inflector.rb +22 -0
  30. data/lib/dry/system/plugins/zeitwerk.rb +109 -0
  31. data/lib/dry/system/plugins.rb +8 -7
  32. data/lib/dry/system/provider/source.rb +324 -0
  33. data/lib/dry/system/provider/source_dsl.rb +94 -0
  34. data/lib/dry/system/provider.rb +264 -24
  35. data/lib/dry/system/provider_registrar.rb +276 -0
  36. data/lib/dry/system/provider_source_registry.rb +70 -0
  37. data/lib/dry/system/provider_sources/settings/config.rb +86 -0
  38. data/lib/dry/system/provider_sources/settings/loader.rb +53 -0
  39. data/lib/dry/system/provider_sources/settings.rb +40 -0
  40. data/lib/dry/system/provider_sources.rb +5 -0
  41. data/lib/dry/system/stubs.rb +1 -1
  42. data/lib/dry/system/version.rb +1 -1
  43. data/lib/dry/system.rb +45 -13
  44. metadata +25 -22
  45. data/lib/dry/system/booter/component_registry.rb +0 -35
  46. data/lib/dry/system/booter.rb +0 -200
  47. data/lib/dry/system/components/bootable.rb +0 -289
  48. data/lib/dry/system/components/config.rb +0 -35
  49. data/lib/dry/system/lifecycle.rb +0 -135
  50. data/lib/dry/system/provider_registry.rb +0 -27
  51. data/lib/dry/system/settings/file_loader.rb +0 -30
  52. data/lib/dry/system/settings/file_parser.rb +0 -51
  53. data/lib/dry/system/settings.rb +0 -67
  54. data/lib/dry/system/system_components/settings.rb +0 -11
@@ -1,9 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "dry/configurable"
4
+ require "dry/core/deprecations"
5
+ require "dry/system/constants"
2
6
  require "dry/system/loader"
7
+ require_relative "namespaces"
3
8
 
4
9
  module Dry
5
10
  module System
6
11
  module Config
12
+ # @api public
7
13
  class ComponentDir
8
14
  include Dry::Configurable
9
15
 
@@ -14,7 +20,7 @@ module Dry
14
20
  # Sets the auto-registration policy for the component dir.
15
21
  #
16
22
  # This may be a simple boolean to enable or disable auto-registration for all
17
- # components, or a proc accepting a `Dry::Sytem::Component` and returning a
23
+ # components, or a proc accepting a {Dry::System::Component} and returning a
18
24
  # boolean to configure auto-registration on a per-component basis
19
25
  #
20
26
  # Defaults to `true`.
@@ -27,11 +33,12 @@ module Dry
27
33
  #
28
34
  # @example
29
35
  # dir.auto_register = proc do |component|
30
- # !component.start_with?("entities")
36
+ # !component.identifier.start_with?("entities")
31
37
  # end
32
38
  #
33
39
  # @see auto_register
34
40
  # @see Component
41
+ # @api public
35
42
  #
36
43
  # @!method auto_register
37
44
  #
@@ -40,68 +47,61 @@ module Dry
40
47
  # @return [Boolean, Proc] the configured policy
41
48
  #
42
49
  # @see auto_register=
43
- setting :auto_register, true
50
+ # @api public
51
+ setting :auto_register, default: true
44
52
 
45
- # @!method add_to_load_path=(policy)
46
- #
47
- # Sets whether the dir should be added to the `$LOAD_PATH` after the container
48
- # is configured.
49
- #
50
- # Defaults to `true`. This may need to be set to `false` when using a class
51
- # autoloading system.
53
+ # @!method instance=(instance_proc)
52
54
  #
53
- # @param policy [Boolean]
54
- # @return [Boolean]
55
+ # Sets a proc used to return the instance of any component within the component
56
+ # dir.
55
57
  #
56
- # @see add_to_load_path
57
- # @see Container.configure
58
+ # This proc should accept a {Dry::System::Component} and return the object to
59
+ # serve as the component's instance.
58
60
  #
59
- # @!method add_to_load_path
60
- #
61
- # Returns the configured value.
62
- #
63
- # @return [Boolean]
64
- #
65
- # @see add_to_load_path=
66
- setting :add_to_load_path, true
67
-
68
- # @!method default_namespace=(leading_namespace)
69
- #
70
- # Sets the leading namespace segments to be stripped when registering components
71
- # from the dir in the container.
72
- #
73
- # This is useful to configure when the dir contains components in a module
74
- # namespace that you don't want repeated in their identifiers.
61
+ # When you provide an instance proc, it will be used in preference to the
62
+ # {loader} (either the default loader or an explicitly configured one). Provide
63
+ # an instance proc when you want a simple way to customize the instance for
64
+ # certain components. For complete control, provide a replacement loader via
65
+ # {loader=}.
75
66
  #
76
67
  # Defaults to `nil`.
77
68
  #
78
- # @param leading_namespace [String, nil]
79
- # @return [String, nil]
69
+ # @param instance_proc [Proc, nil]
70
+ # @return [Proc]
80
71
  #
81
72
  # @example
82
- # dir.default_namespace = "my_app"
83
- #
84
- # @example
85
- # dir.default_namespace = "my_app.admin"
73
+ # dir.instance = proc do |component|
74
+ # if component.key.match?(/workers\./)
75
+ # # Register classes for jobs
76
+ # component.loader.constant(component)
77
+ # else
78
+ # # Otherwise register regular instances per default loader
79
+ # component.loader.call(component)
80
+ # end
81
+ # end
86
82
  #
87
- # @see default_namespace
83
+ # @see Component, Loader
84
+ # @api public
88
85
  #
89
- # @!method default_namespace
86
+ # @!method instance
90
87
  #
91
- # Returns the configured value.
88
+ # Returns the configured instance proc.
92
89
  #
93
- # @return [String, nil]
90
+ # @return [Proc, nil]
94
91
  #
95
- # @see default_namespace=
96
- setting :default_namespace
92
+ # @see instance=
93
+ # @api public
94
+ setting :instance
97
95
 
98
96
  # @!method loader=(loader)
99
97
  #
100
- # Sets the loader to use when registering coponents from the dir in the container.
98
+ # Sets the loader to use when registering components from the dir in the
99
+ # container.
101
100
  #
102
101
  # Defaults to `Dry::System::Loader`.
103
102
  #
104
- # When using a class autoloader, consider using `Dry::System::Loader::Autoloading`
103
+ # When using an autoloader like Zeitwerk, consider using
104
+ # `Dry::System::Loader::Autoloading`
105
105
  #
106
106
  # @param loader [#call] the loader
107
107
  # @return [#call] the configured loader
@@ -109,6 +109,7 @@ module Dry
109
109
  # @see loader
110
110
  # @see Loader
111
111
  # @see Loader::Autoloading
112
+ # @api public
112
113
  #
113
114
  # @!method loader
114
115
  #
@@ -117,7 +118,8 @@ module Dry
117
118
  # @return [#call]
118
119
  #
119
120
  # @see loader=
120
- setting :loader, Dry::System::Loader
121
+ # @api public
122
+ setting :loader, default: Dry::System::Loader
121
123
 
122
124
  # @!method memoize=(policy)
123
125
  #
@@ -138,11 +140,12 @@ module Dry
138
140
  #
139
141
  # @example
140
142
  # dir.memoize = proc do |component|
141
- # !component.start_with?("providers")
143
+ # !component.identifier.start_with?("providers")
142
144
  # end
143
145
  #
144
146
  # @see memoize
145
147
  # @see Component
148
+ # @api public
146
149
  #
147
150
  # @!method memoize
148
151
  #
@@ -151,7 +154,79 @@ module Dry
151
154
  # @return [Boolean, Proc] the configured memoization policy
152
155
  #
153
156
  # @see memoize=
154
- setting :memoize, false
157
+ # @api public
158
+ setting :memoize, default: false
159
+
160
+ # @!method namespaces
161
+ #
162
+ # Returns the configured namespaces for the component dir.
163
+ #
164
+ # Allows namespaces to added on the returned object via {Namespaces#add}.
165
+ #
166
+ # @return [Namespaces] the namespaces
167
+ #
168
+ # @see Namespaces#add
169
+ # @api public
170
+ setting :namespaces, default: Namespaces.new, cloneable: true
171
+
172
+ # @!method add_to_load_path=(policy)
173
+ #
174
+ # Sets whether the dir should be added to the `$LOAD_PATH` after the container
175
+ # is configured.
176
+ #
177
+ # Defaults to `true`. This may need to be set to `false` when using a class
178
+ # autoloading system.
179
+ #
180
+ # @param policy [Boolean]
181
+ # @return [Boolean]
182
+ #
183
+ # @see add_to_load_path
184
+ # @see Container.configure
185
+ # @api public
186
+ #
187
+ # @!method add_to_load_path
188
+ #
189
+ # Returns the configured value.
190
+ #
191
+ # @return [Boolean]
192
+ #
193
+ # @see add_to_load_path=
194
+ # @api public
195
+ setting :add_to_load_path, default: true
196
+
197
+ # @api public
198
+ def default_namespace=(namespace)
199
+ Dry::Core::Deprecations.announce(
200
+ "Dry::System::Config::ComponentDir#default_namespace=",
201
+ "Add a namespace instead: `dir.namespaces.add #{namespace.to_s.inspect}, key: nil`",
202
+ tag: "dry-system",
203
+ uplevel: 1
204
+ )
205
+
206
+ # We don't have the configured separator here, so the best we can do is guess
207
+ # that it's a dot
208
+ namespace_path = namespace.gsub(".", PATH_SEPARATOR)
209
+
210
+ return if namespaces.namespaces[namespace_path]
211
+
212
+ namespaces.add namespace_path, key: nil
213
+ end
214
+
215
+ # @api public
216
+ def default_namespace
217
+ Dry::Core::Deprecations.announce(
218
+ "Dry::System::Config::ComponentDir#default_namespace",
219
+ "Use namespaces instead, e.g. `dir.namespaces`",
220
+ tag: "dry-system",
221
+ uplevel: 1
222
+ )
223
+
224
+ ns_path = namespaces.to_a.reject(&:root?).first&.path
225
+
226
+ # We don't have the configured separator here, so the best we can do is guess
227
+ # that it's a dot
228
+ ns_path&.gsub(PATH_SEPARATOR, ".")
229
+ end
155
230
 
156
231
  # @!endgroup
157
232
 
@@ -160,7 +235,7 @@ module Dry
160
235
  # @return [String] the path
161
236
  attr_reader :path
162
237
 
163
- # @api private
238
+ # @api public
164
239
  def initialize(path)
165
240
  super()
166
241
  @path = path
@@ -172,15 +247,28 @@ module Dry
172
247
  !!config.auto_register
173
248
  end
174
249
 
175
- # Returns true if a setting has been explicitly configured and is not returning
176
- # just a default value.
250
+ # Returns true if the given setting has been explicitly configured by the user
177
251
  #
178
- # This is used to determine which settings from `ComponentDirs` should be applied
179
- # as additional defaults.
252
+ # This is used when determining whether to apply system-wide default values to a
253
+ # component dir (explicitly configured settings will not be overridden by
254
+ # defaults)
180
255
  #
256
+ # @param key [Symbol] the setting name
257
+ #
258
+ # @return [Boolean]
259
+ #
260
+ # @see Dry::System::Config::ComponentDirs#apply_defaults_to_dir
181
261
  # @api private
182
262
  def configured?(key)
183
- config._settings[key].input_defined?
263
+ case key
264
+ when :namespaces
265
+ # Because we mutate the default value for the `namespaces` setting, rather
266
+ # than assign a new one, to check if it's configured we must see whether any
267
+ # namespaces have been added
268
+ !config.namespaces.empty?
269
+ else
270
+ config._settings[key].input_defined?
271
+ end
184
272
  end
185
273
 
186
274
  private
@@ -1,5 +1,5 @@
1
- require "concurrent/map"
2
- require "dry/configurable"
1
+ # frozen_string_literal: true
2
+
3
3
  require "dry/system/constants"
4
4
  require "dry/system/errors"
5
5
  require_relative "component_dir"
@@ -7,21 +7,17 @@ require_relative "component_dir"
7
7
  module Dry
8
8
  module System
9
9
  module Config
10
+ # The configured component dirs for a container
11
+ #
12
+ # @api public
10
13
  class ComponentDirs
11
- include Dry::Configurable
12
-
13
- # Settings from ComponentDir are configured here as defaults for all added dirs
14
- ComponentDir._settings.each do |setting|
15
- _settings << setting.dup
16
- end
17
-
18
14
  # @!group Settings
19
15
 
20
16
  # @!method auto_register=(value)
21
17
  #
22
18
  # Sets a default `auto_register` for all added component dirs
23
19
  #
24
- # @see ComponentDir.auto_register
20
+ # @see ComponentDir.auto_register=
25
21
  # @see auto_register
26
22
  #
27
23
  # @!method auto_register
@@ -30,37 +26,24 @@ module Dry
30
26
  #
31
27
  # @see auto_register=
32
28
 
33
- # @!method add_to_load_path=(value)
34
- #
35
- # Sets a default `add_to_load_path` value for all added component dirs
36
- #
37
- # @see ComponentDir.add_to_load_path
38
- # @see add_to_load_path
39
- #
40
- # @!method add_to_load_path
41
- #
42
- # Returns the configured default `add_to_load_path`
43
- #
44
- # @see add_to_load_path=
45
-
46
- # @!method default_namespace=(value)
29
+ # @!method instance=(value)
47
30
  #
48
- # Sets a default `default_namespace` value for all added component dirs
31
+ # Sets a default `instance` for all added component dirs
49
32
  #
50
- # @see ComponentDir.default_namespace
51
- # @see default_namespace
33
+ # @see ComponentDir.instance=
34
+ # @see auto_register
52
35
  #
53
- # @!method default_namespace
36
+ # @!method auto_register
54
37
  #
55
- # Returns the configured default `default_namespace`
38
+ # Returns the configured default `instance`
56
39
  #
57
- # @see default_namespace=
40
+ # @see instance=
58
41
 
59
42
  # @!method loader=(value)
60
43
  #
61
44
  # Sets a default `loader` value for all added component dirs
62
45
  #
63
- # @see ComponentDir.loader
46
+ # @see ComponentDir.loader=
64
47
  # @see loader
65
48
  #
66
49
  # @!method loader
@@ -73,7 +56,7 @@ module Dry
73
56
  #
74
57
  # Sets a default `memoize` value for all added component dirs
75
58
  #
76
- # @see ComponentDir.memoize
59
+ # @see ComponentDir.memoize=
77
60
  # @see memoize
78
61
  #
79
62
  # @!method memoize
@@ -82,54 +65,154 @@ module Dry
82
65
  #
83
66
  # @see memoize=
84
67
 
68
+ # rubocop:disable Layout/LineLength
69
+
70
+ # @!method namespaces
71
+ #
72
+ # Returns the default configured namespaces for all added component dirs
73
+ #
74
+ # Allows namespaces to added on the returned object via {Dry::System::Config::Namespaces#add}.
75
+ #
76
+ # @see Dry::System::Config::Namespaces#add
77
+ #
78
+ # @return [Namespaces] the namespaces
79
+
80
+ # @!method add_to_load_path=(value)
81
+ #
82
+ # Sets a default `add_to_load_path` value for all added component dirs
83
+ #
84
+ # @see ComponentDir.add_to_load_path=
85
+ # @see add_to_load_path
86
+ #
87
+ # @!method add_to_load_path
88
+ #
89
+ # Returns the configured default `add_to_load_path`
90
+ #
91
+ # @see add_to_load_path=
92
+
93
+ # rubocop:enable Layout/LineLength
94
+
85
95
  # @!endgroup
86
96
 
97
+ # A ComponentDir for configuring the default values to apply to all added
98
+ # component dirs
99
+ #
100
+ # @see #method_missing
101
+ # @api private
102
+ attr_reader :defaults
103
+
104
+ # Creates a new component dirs
105
+ #
87
106
  # @api private
88
107
  def initialize
89
- @dirs = Concurrent::Map.new
108
+ @dirs = {}
109
+ @defaults = ComponentDir.new(nil)
90
110
  end
91
111
 
92
112
  # @api private
93
113
  def initialize_copy(source)
94
- super
95
- @dirs = source.dirs.dup
114
+ @dirs = source.dirs.map { |path, dir| [path, dir.dup] }.to_h
115
+ @defaults = source.defaults.dup
116
+ end
117
+
118
+ # Returns and optionally yields a previously added component dir
119
+ #
120
+ # @param path [String] the path for the component dir
121
+ # @yieldparam dir [ComponentDir] the component dir
122
+ #
123
+ # @return [ComponentDir] the component dir
124
+ #
125
+ # @api public
126
+ def dir(path)
127
+ dirs[path].tap do |dir|
128
+ # Defaults can be (re-)applied first, since the dir has already been added
129
+ apply_defaults_to_dir(dir) if dir
130
+ yield dir if block_given?
131
+ end
96
132
  end
133
+ alias_method :[], :dir
97
134
 
98
- # Adds and configures a component dir
135
+ # @overload add(path)
136
+ # Adds and configures a component dir for the given path
137
+ #
138
+ # @param path [String] the path for the component dir, relative to the configured
139
+ # container root
140
+ # @yieldparam dir [ComponentDir] the component dir to configure
99
141
  #
100
- # @param path [String] the path for the component dir, relative to the configured
101
- # container root
142
+ # @return [ComponentDir] the added component dir
102
143
  #
103
- # @yieldparam dir [ComponentDir] the component dir to configure
144
+ # @example
145
+ # component_dirs.add "lib" do |dir|
146
+ # dir.default_namespace = "my_app"
147
+ # end
104
148
  #
105
- # @return [ComponentDir] the added component dir
149
+ # @see ComponentDir
150
+ # @api public
106
151
  #
107
- # @example
108
- # component_dirs.add "lib" do |dir|
109
- # dir.default_namespace = "my_app"
110
- # end
152
+ # @overload add(dir)
153
+ # Adds a configured component dir
111
154
  #
112
- # @see ComponentDir
113
- def add(path)
155
+ # @param dir [ComponentDir] the configured component dir
156
+ #
157
+ # @return [ComponentDir] the added component dir
158
+ #
159
+ # @example
160
+ # dir = Dry::System::ComponentDir.new("lib")
161
+ # component_dirs.add dir
162
+ #
163
+ # @see ComponentDir
164
+ # @api public
165
+ def add(path_or_dir)
166
+ path, dir_to_add = path_and_dir(path_or_dir)
167
+
114
168
  raise ComponentDirAlreadyAddedError, path if dirs.key?(path)
115
169
 
116
- dirs[path] = ComponentDir.new(path).tap do |dir|
170
+ dirs[path] = dir_to_add.tap do |dir|
171
+ # Defaults must be applied after yielding, since the dir is being newly added,
172
+ # and must have its configuration fully in place before we can know which
173
+ # defaults to apply
174
+ yield dir if path_or_dir == path && block_given?
117
175
  apply_defaults_to_dir(dir)
118
- yield dir if block_given?
119
176
  end
120
177
  end
121
178
 
122
- # Returns the added component dirs, with default settings applied
179
+ # Deletes and returns a previously added component dir
180
+ #
181
+ # @param path [String] the path for the component dir
182
+ #
183
+ # @return [ComponentDir] the removed component dir
184
+ #
185
+ # @api public
186
+ def delete(path)
187
+ dirs.delete(path)
188
+ end
189
+
190
+ # Returns the paths of the component dirs
191
+ #
192
+ # @return [Array<String>] the component dir paths
193
+ #
194
+ # @api public
195
+ def paths
196
+ dirs.keys
197
+ end
198
+
199
+ # Returns the count of component dirs
200
+ #
201
+ # @return [Integer]
123
202
  #
124
- # @return [Hash<String, ComponentDir>] the component dirs as a hash, keyed by path
125
- def dirs
126
- @dirs.each { |_, dir| apply_defaults_to_dir(dir) }
203
+ # @api public
204
+ def length
205
+ dirs.length
127
206
  end
207
+ alias_method :size, :length
128
208
 
129
209
  # Returns the added component dirs, with default settings applied
130
210
  #
131
211
  # @return [Array<ComponentDir>]
212
+ #
213
+ # @api public
132
214
  def to_a
215
+ dirs.each { |_, dir| apply_defaults_to_dir(dir) }
133
216
  dirs.values
134
217
  end
135
218
 
@@ -137,46 +220,69 @@ module Dry
137
220
  # argument.
138
221
  #
139
222
  # @yieldparam dir [ComponentDir] the yielded component dir
223
+ #
224
+ # @api public
140
225
  def each(&block)
141
226
  to_a.each(&block)
142
227
  end
143
228
 
229
+ protected
230
+
231
+ # Returns the hash of component dirs, keyed by their paths
232
+ #
233
+ # Recently changed default configuration may not be applied to these dirs. Use
234
+ # #to_a or #each to access dirs with default configuration fully applied.
235
+ #
236
+ # This method exists to encapsulate the instance variable and to serve the needs
237
+ # of #initialize_copy
238
+ #
239
+ # @return [Hash{String => ComponentDir}]
240
+ #
241
+ # @api private
242
+ attr_reader :dirs
243
+
144
244
  private
145
245
 
146
- # Apply default settings to a component dir. This is run every time the dirs are
246
+ # Converts a path string or pre-built component dir into a path and dir tuple
247
+ #
248
+ # @param path_or_dir [String,ComponentDir]
249
+ #
250
+ # @return [Array<(String, ComponentDir)>]
251
+ #
252
+ # @see #add
253
+ def path_and_dir(path_or_dir)
254
+ if path_or_dir.is_a?(ComponentDir)
255
+ dir = path_or_dir
256
+ [dir.path, dir]
257
+ else
258
+ path = path_or_dir
259
+ [path, ComponentDir.new(path)]
260
+ end
261
+ end
262
+
263
+ # Applies default settings to a component dir. This is run every time the dirs are
147
264
  # accessed to ensure defaults are applied regardless of when new component dirs
148
265
  # are added. This method must be idempotent.
149
266
  #
150
267
  # @return [void]
151
268
  def apply_defaults_to_dir(dir)
152
- dir.config.values.each do |key, _value|
153
- if configured?(key) && !dir.configured?(key)
154
- dir.public_send(:"#{key}=", public_send(key))
269
+ defaults.config.values.each do |key, _|
270
+ if defaults.configured?(key) && !dir.configured?(key)
271
+ dir.public_send(:"#{key}=", defaults.public_send(key).dup)
155
272
  end
156
273
  end
157
274
  end
158
275
 
159
- # Returns true if a setting has been explicitly configured and is not returning
160
- # just a default value.
161
- #
162
- # This is used to determine which settings should be applied to added component
163
- # dirs as additional defaults.
164
- #
165
- # @api private
166
- def configured?(key)
167
- config._settings[key].input_defined?
168
- end
169
-
170
276
  def method_missing(name, *args, &block)
171
- if config.respond_to?(name)
172
- config.public_send(name, *args, &block)
277
+ if defaults.respond_to?(name)
278
+ defaults.public_send(name, *args, &block)
173
279
  else
174
280
  super
175
281
  end
176
282
  end
177
283
 
178
284
  def respond_to_missing?(name, include_all = false)
179
- config.respond_to?(name) || super
285
+ defaults.respond_to?(name) || super
180
286
  end
181
287
  end
182
288
  end