dry-system 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 691aea0bf618106d932309794bcf87afa5d84a3c423871342c2ceb39b45a6ce6
4
- data.tar.gz: 1ac5655641e9ffd965e3f0b37a199367e7157074a14250745a49925bab0ec517
3
+ metadata.gz: 75ae2c71ec73569babb52c596854afc53947908e0d6e4043bd7af02395cd3f33
4
+ data.tar.gz: e60b2a914e0479ec74226a92aa9d6e257c37bc4383d980d838e8ecb18dfe8c3d
5
5
  SHA512:
6
- metadata.gz: 589e77b1739b554528f13633f93bf61c39f4945067318f08afcc5be5bf0afbc53db137f54d0e1b2202aa45a5f2a3df697564cfc7f208cb3fa043d28b0f174706
7
- data.tar.gz: 8271fb82fde50c7bfed6e52da6a58ea90a447ee7097562402cfd38d94823edb29bee835b0e462bc893ddb59ddb76f1d0fe0c9dab99d4cf14062f74082ab0ccdc
6
+ metadata.gz: 11cff300881fb7e00e2575fcc0c1fc3d3d9e9ae0046035287d2c8aa9df47afca1c5f05abce90224899eb503aaa43b47402fa0a25f6d2c1626246aef31c338489
7
+ data.tar.gz: 1f28987740aa6cfc5ab97a20039e62d11cc5394d100dcf1df9c94f663577dfd2fdd363bc8dcb9ff67d162f94fffbb413f304d530563044697b8a638de782a746
@@ -1,3 +1,12 @@
1
+ # 0.11.0 - 2019-03-22
2
+
3
+ ### Changed
4
+
5
+ * [BREAKING] `:decorate` plugin was moved from dry-system to dry-container (available in 0.7.0+). To upgrade remove `use :decorate` and change `decorate` calls from `decorate(key, decorator: something)` to `decorate(key, with: something)` (flash-gordon)
6
+ * [internal] Compatibility with dry-struct 0.7.0 and dry-types 0.15.0
7
+
8
+ [Compare v0.10.1...v0.11.0](https://github.com/dry-rb/dry-system/compare/v0.10.1...v0.11.0)
9
+
1
10
  # 0.10.1 - 2018-07-05
2
11
 
3
12
  ### Added
@@ -35,7 +35,7 @@ module Dry
35
35
  next if !component.auto_register? || registration_config.exclude.(component)
36
36
 
37
37
  container.require_component(component) do
38
- register(component.identifier) { registration_config.instance.(component) }
38
+ register(component.identifier, memoize: registration_config.memoize) { registration_config.instance.(component) }
39
39
  end
40
40
  end
41
41
  end
@@ -16,7 +16,6 @@ module Dry
16
16
  def self.setting(name)
17
17
  define_method(name) do |&block|
18
18
  ivar = "@#{name}"
19
-
20
19
  if block
21
20
  instance_variable_set(ivar, block)
22
21
  else
@@ -28,10 +27,13 @@ module Dry
28
27
  setting :exclude
29
28
  setting :instance
30
29
 
30
+ attr_accessor :memoize
31
+
31
32
  # @api private
32
33
  def initialize
33
34
  @instance = DEFAULT_INSTANCE
34
35
  @exclude = FALSE_PROC
36
+ @memoize = false
35
37
  end
36
38
  end
37
39
  end
@@ -69,6 +69,15 @@ module Dry
69
69
  freeze
70
70
  end
71
71
 
72
+ # @api private
73
+ def shutdown
74
+ components.each do |component|
75
+ next unless booted.include?(component)
76
+
77
+ stop(component)
78
+ end
79
+ end
80
+
72
81
  # @api private
73
82
  def init(name_or_component)
74
83
  with_component(name_or_component) do |component|
@@ -100,7 +109,10 @@ module Dry
100
109
  def stop(name_or_component)
101
110
  call(name_or_component) do |component|
102
111
  raise ComponentNotStartedError.new(name_or_component) unless booted.include?(component)
112
+
103
113
  component.stop
114
+ booted.delete(component)
115
+
104
116
  yield if block_given?
105
117
  end
106
118
  end
@@ -25,7 +25,7 @@ module Dry
25
25
  private
26
26
 
27
27
  def attributes_errors(attributes)
28
- attributes.map { |key, error| "#{key}: #{error}" }
28
+ attributes.map { |key, error| "#{key.name}: #{error}" }
29
29
  end
30
30
  end
31
31
 
@@ -304,6 +304,7 @@ module Dry
304
304
  @__finalized__ = true
305
305
 
306
306
  self.freeze if freeze
307
+ self
307
308
  end
308
309
 
309
310
  # Boots a specific component
@@ -356,6 +357,11 @@ module Dry
356
357
  self
357
358
  end
358
359
 
360
+ def shutdown!
361
+ booter.shutdown
362
+ self
363
+ end
364
+
359
365
  # Sets load paths relative to the container's root dir
360
366
  #
361
367
  # @example
@@ -556,11 +562,22 @@ module Dry
556
562
  raise FileNotFoundError, component
557
563
  end
558
564
 
559
- require component.path
565
+ require_path(component.path)
560
566
 
561
567
  yield
562
568
  end
563
569
 
570
+ # Allows subclasses to use a different strategy for required files.
571
+ #
572
+ # E.g. apps that use `ActiveSupport::Dependencies::Loadable#require_dependency`
573
+ # will override this method to allow container managed dependencies to be reloaded
574
+ # for non-finalized containers.
575
+ #
576
+ # @api private
577
+ def require_path(path)
578
+ require path
579
+ end
580
+
564
581
  # @api private
565
582
  def load_component(key)
566
583
  return self if key?(key)
@@ -27,6 +27,7 @@ module Dry
27
27
  registry.each do |name, container|
28
28
  call(name, container.finalize!)
29
29
  end
30
+ self
30
31
  end
31
32
 
32
33
  # @api private
@@ -111,9 +111,6 @@ module Dry
111
111
  require 'dry/system/plugins/env'
112
112
  register(:env, Plugins::Env)
113
113
 
114
- require 'dry/system/plugins/decorate'
115
- register(:decorate, Plugins::Decorate)
116
-
117
114
  require 'dry/system/plugins/notifications'
118
115
  register(:notifications, Plugins::Notifications)
119
116
 
@@ -10,7 +10,6 @@ module Dry
10
10
  def self.extended(system)
11
11
  super
12
12
 
13
- system.use(:decorate)
14
13
  system.use(:notifications)
15
14
 
16
15
  system.after(:configure) do
@@ -36,7 +35,7 @@ module Dry
36
35
  end
37
36
  end
38
37
 
39
- decorate(key, decorator: proxy.new(target, notifications))
38
+ decorate(key, with: proxy.new(target, notifications))
40
39
  end
41
40
  end
42
41
  end
@@ -42,11 +42,11 @@ module Dry
42
42
  attributes = {}
43
43
  errors = {}
44
44
 
45
- schema.each do |key, type|
46
- value = ENV.fetch(key.to_s.upcase) { env_data[key.to_s.upcase] }
47
- type_check = type.try(value || Undefined)
45
+ schema.each do |key|
46
+ value = ENV.fetch(key.name.to_s.upcase) { env_data[key.name.to_s.upcase] }
47
+ type_check = key.try(value || Undefined)
48
48
 
49
- attributes[key] = value if value
49
+ attributes[key.name] = value if value
50
50
  errors[key] = type_check if type_check.failure?
51
51
  end
52
52
 
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module System
3
- VERSION = '0.10.1'.freeze
3
+ VERSION = '0.11.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-04 00:00:00.000000000 Z
11
+ date: 2019-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -56,36 +56,36 @@ dependencies:
56
56
  name: dry-configurable
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '0.7'
62
59
  - - ">="
63
60
  - !ruby/object:Gem::Version
64
61
  version: 0.7.0
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '0.7'
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - "~>"
70
- - !ruby/object:Gem::Version
71
- version: '0.7'
72
69
  - - ">="
73
70
  - !ruby/object:Gem::Version
74
71
  version: 0.7.0
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.7'
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: dry-container
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '0.6'
81
+ version: '0.7'
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '0.6'
88
+ version: '0.7'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: dry-equalizer
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -126,14 +126,14 @@ dependencies:
126
126
  requirements:
127
127
  - - "~>"
128
128
  - !ruby/object:Gem::Version
129
- version: '0.5'
129
+ version: 0.7.0
130
130
  type: :runtime
131
131
  prerelease: false
132
132
  version_requirements: !ruby/object:Gem::Requirement
133
133
  requirements:
134
134
  - - "~>"
135
135
  - !ruby/object:Gem::Version
136
- version: '0.5'
136
+ version: 0.7.0
137
137
  - !ruby/object:Gem::Dependency
138
138
  name: bundler
139
139
  requirement: !ruby/object:Gem::Requirement
@@ -197,7 +197,6 @@ files:
197
197
  - lib/dry/system/components/bootable.rb
198
198
  - lib/dry/system/components/config.rb
199
199
  - lib/dry/system/constants.rb
200
- - lib/dry/system/container.mod.rb
201
200
  - lib/dry/system/container.rb
202
201
  - lib/dry/system/errors.rb
203
202
  - lib/dry/system/importer.rb
@@ -207,7 +206,6 @@ files:
207
206
  - lib/dry/system/manual_registrar.rb
208
207
  - lib/dry/system/plugins.rb
209
208
  - lib/dry/system/plugins/bootsnap.rb
210
- - lib/dry/system/plugins/decorate.rb
211
209
  - lib/dry/system/plugins/env.rb
212
210
  - lib/dry/system/plugins/logging.rb
213
211
  - lib/dry/system/plugins/monitoring.rb
@@ -233,15 +231,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
231
  requirements:
234
232
  - - ">="
235
233
  - !ruby/object:Gem::Version
236
- version: 2.3.0
234
+ version: 2.4.0
237
235
  required_rubygems_version: !ruby/object:Gem::Requirement
238
236
  requirements:
239
237
  - - ">="
240
238
  - !ruby/object:Gem::Version
241
239
  version: '0'
242
240
  requirements: []
243
- rubyforge_project:
244
- rubygems_version: 2.7.5
241
+ rubygems_version: 3.0.1
245
242
  signing_key:
246
243
  specification_version: 4
247
244
  summary: Organize your code into reusable components
@@ -1,664 +0,0 @@
1
- require 'pathname'
2
-
3
- require 'dry-auto_inject'
4
- require 'dry-configurable'
5
- require 'dry-container'
6
- require 'dry/inflector'
7
-
8
- require 'dry/core/deprecations'
9
-
10
- require 'dry/system'
11
- require 'dry/system/errors'
12
- require 'dry/system/loader'
13
- require 'dry/system/booter'
14
- require 'dry/system/auto_registrar'
15
- require 'dry/system/manual_registrar'
16
- require 'dry/system/importer'
17
- require 'dry/system/component'
18
- require 'dry/system/constants'
19
- require 'dry/system/plugins'
20
-
21
- module Dry
22
- module System
23
- # Abstract container class to inherit from
24
- #
25
- # Container class is treated as a global registry with all system components.
26
- # Container can also import dependencies from other containers, which is
27
- # useful in complex systems that are split into sub-systems.
28
- #
29
- # Container can be finalized, which triggers loading of all the defined
30
- # components within a system, after finalization it becomes frozen. This
31
- # typically happens in cases like booting a web application.
32
- #
33
- # Before finalization, Container can lazy-load components on demand. A
34
- # component can be a simple class defined in a single file, or a complex
35
- # component which has init/start/stop lifecycle, and it's defined in a boot
36
- # file. Components which specify their dependencies using Import module can
37
- # be safely required in complete isolation, and Container will resolve and
38
- # load these dependencies automatically.
39
- #
40
- # Furthermore, Container supports auto-registering components based on
41
- # dir/file naming conventions. This reduces a lot of boilerplate code as all
42
- # you have to do is to put your classes under configured directories and
43
- # their instances will be automatically registered within a container.
44
- #
45
- # Every container needs to be configured with following settings:
46
- #
47
- # * `:name` - a unique container identifier
48
- # * `:root` - a system root directory (defaults to `pwd`)
49
- # * `:system_dir` - directory name relative to root, where bootable components
50
- # can be defined in `boot` dir this defaults to `system`
51
- #
52
- # @example
53
- # class MyApp < Dry::System::Container
54
- # configure do |config|
55
- # config.name = :my_app
56
- #
57
- # # this will auto-register classes from 'lib/components'. ie if you add
58
- # # `lib/components/repo.rb` which defines `Repo` class, then it's
59
- # # instance will be automatically available as `MyApp['repo']`
60
- # config.auto_register = %w(lib/components)
61
- # end
62
- #
63
- # # this will configure $LOAD_PATH to include your `lib` dir
64
- # load_paths!('lib')
65
- # end
66
- #
67
- # @api public
68
- class Container
69
- extend Dry::Configurable
70
- extend Dry::Container::Mixin
71
- extend Dry::System::Plugins
72
-
73
- setting :name
74
- setting :default_namespace
75
- setting(:root, Pathname.pwd.freeze) { |path| Pathname(path) }
76
- setting :system_dir, 'system'.freeze
77
- setting :registrations_dir, 'container'.freeze
78
- setting :auto_register, []
79
- setting :inflector, Dry::Inflector.new
80
- setting :loader, Dry::System::Loader
81
- setting :booter, Dry::System::Booter
82
- setting :auto_registrar, Dry::System::AutoRegistrar
83
- setting :manual_registrar, Dry::System::ManualRegistrar
84
- setting :importer, Dry::System::Importer
85
- setting(:components, {}, reader: true) { |v| v.dup }
86
-
87
- class << self
88
- extend Dry::Core::Deprecations['Dry::System::Container']
89
-
90
- # Configures the container
91
- #
92
- # @example
93
- # class MyApp < Dry::System::Container
94
- # configure do |config|
95
- # config.root = Pathname("/path/to/app")
96
- # config.name = :my_app
97
- # config.auto_register = %w(lib/apis lib/core)
98
- # end
99
- # end
100
- #
101
- # @return [self]
102
- #
103
- # @api public
104
- def configure(&block)
105
- super(&block)
106
- load_paths!(config.system_dir)
107
- hooks[:configure].each { |hook| instance_eval(&hook) }
108
- self
109
- end
110
-
111
- # Registers another container for import
112
- #
113
- # @example
114
- # # system/container.rb
115
- # class Core < Dry::System::Container
116
- # configure do |config|
117
- # config.root = Pathname("/path/to/app")
118
- # config.auto_register = %w(lib/apis lib/core)
119
- # end
120
- # end
121
- #
122
- # # apps/my_app/system/container.rb
123
- # require 'system/container'
124
- #
125
- # class MyApp < Dry::System::Container
126
- # configure do |config|
127
- # config.root = Pathname("/path/to/app")
128
- # config.auto_register = %w(lib/apis lib/core)
129
- # end
130
- #
131
- # import core: Core
132
- # end
133
- #
134
- # @param other [Hash, Dry::Container::Namespace]
135
- #
136
- # @api public
137
- def import(other)
138
- case other
139
- when Hash then importer.register(other)
140
- when Dry::Container::Namespace then super
141
- else
142
- raise ArgumentError, "+other+ must be a hash of names and systems, or a Dry::Container namespace"
143
- end
144
- end
145
-
146
- # Registers finalization function for a bootable component
147
- #
148
- # By convention, boot files for components should be placed in
149
- # `%{system_dir}/boot` and they will be loaded on demand when components
150
- # are loaded in isolation, or during finalization process.
151
- #
152
- # @example
153
- # # system/container.rb
154
- # class MyApp < Dry::System::Container
155
- # configure do |config|
156
- # config.root = Pathname("/path/to/app")
157
- # config.name = :core
158
- # config.auto_register = %w(lib/apis lib/core)
159
- # end
160
- #
161
- # # system/boot/db.rb
162
- # #
163
- # # Simple component registration
164
- # MyApp.boot(:db) do |container|
165
- # require 'db'
166
- #
167
- # container.register(:db, DB.new)
168
- # end
169
- #
170
- # # system/boot/db.rb
171
- # #
172
- # # Component registration with lifecycle triggers
173
- # MyApp.boot(:db) do |container|
174
- # init do
175
- # require 'db'
176
- # DB.configure(ENV['DB_URL'])
177
- # container.register(:db, DB.new)
178
- # end
179
- #
180
- # start do
181
- # db.establish_connection
182
- # end
183
- #
184
- # stop do
185
- # db.close_connection
186
- # end
187
- # end
188
- #
189
- # # system/boot/db.rb
190
- # #
191
- # # Component registration which uses another bootable component
192
- # MyApp.boot(:db) do |container|
193
- # use :logger
194
- #
195
- # start do
196
- # require 'db'
197
- # DB.configure(ENV['DB_URL'], logger: logger)
198
- # container.register(:db, DB.new)
199
- # end
200
- # end
201
- #
202
- # # system/boot/db.rb
203
- # #
204
- # # Component registration under a namespace. This will register the
205
- # # db object under `persistence.db` key
206
- # MyApp.namespace(:persistence) do |persistence|
207
- # require 'db'
208
- # DB.configure(ENV['DB_URL'], logger: logger)
209
- # persistence.register(:db, DB.new)
210
- # end
211
- #
212
- # @param name [Symbol] a unique identifier for a bootable component
213
- #
214
- # @see Lifecycle
215
- #
216
- # @return [self]
217
- #
218
- # @api public
219
- def boot(name, opts = {}, &block)
220
- if components.key?(name)
221
- raise DuplicatedComponentKeyError, "Bootable component #{name.inspect} was already registered"
222
- end
223
-
224
- component =
225
- if opts[:from]
226
- boot_external(name, opts, &block)
227
- else
228
- boot_local(name, opts, &block)
229
- end
230
- self
231
-
232
- components[name] = component
233
- end
234
- deprecate :finalize, :boot
235
-
236
- # @api private
237
- def boot_external(identifier, from:, key: nil, namespace: nil, &block)
238
- component = System.providers[from].component(
239
- identifier, key: key, namespace: namespace, finalize: block, container: self
240
- )
241
-
242
- booter.register_component(component)
243
-
244
- component
245
- end
246
-
247
- # @api private
248
- def boot_local(identifier, namespace: nil, &block)
249
- component = Components::Bootable.new(identifier, container: self, namespace: namespace, &block)
250
-
251
- booter.register_component(component)
252
-
253
- component
254
- end
255
-
256
- # Return if a container was finalized
257
- #
258
- # @return [TrueClass, FalseClass]
259
- #
260
- # @api public
261
- def finalized?
262
- @__finalized__.equal?(true)
263
- end
264
-
265
- # Finalizes the container
266
- #
267
- # This triggers importing components from other containers, booting
268
- # registered components and auto-registering components. It should be
269
- # called only in places where you want to finalize your system as a
270
- # whole, ie when booting a web application
271
- #
272
- # @example
273
- # # system/container.rb
274
- # class MyApp < Dry::System::Container
275
- # configure do |config|
276
- # config.root = Pathname("/path/to/app")
277
- # config.name = :my_app
278
- # config.auto_register = %w(lib/apis lib/core)
279
- # end
280
- # end
281
- #
282
- # # You can put finalization file anywhere you want, ie system/boot.rb
283
- # MyApp.finalize!
284
- #
285
- # # If you need last-moment adjustments just before the finalization
286
- # # you can pass a block and do it there
287
- # MyApp.finalize! do |container|
288
- # # stuff that only needs to happen for finalization
289
- # end
290
- #
291
- # @return [self] frozen container
292
- #
293
- # @api public
294
- def finalize!(freeze: true, &block)
295
- return self if finalized?
296
-
297
- yield(self) if block
298
-
299
- importer.finalize!
300
- booter.finalize!
301
- manual_registrar.finalize!
302
- auto_registrar.finalize!
303
-
304
- @__finalized__ = true
305
-
306
- self.freeze if freeze
307
- end
308
-
309
- # Boots a specific component
310
- #
311
- # As a result, `init` and `start` lifecycle triggers are called
312
- #
313
- # @example
314
- # MyApp.start(:persistence)
315
- #
316
- # @param name [Symbol] the name of a registered bootable component
317
- #
318
- # @return [self]
319
- #
320
- # @api public
321
- def start(name)
322
- booter.start(name)
323
- self
324
- end
325
-
326
- # Boots a specific component but calls only `init` lifecycle trigger
327
- #
328
- # This way of booting is useful in places where a heavy dependency is
329
- # needed but its started environment is not required
330
- #
331
- # @example
332
- # MyApp.init(:persistence)
333
- #
334
- # @param [Symbol] name The name of a registered bootable component
335
- #
336
- # @return [self]
337
- #
338
- # @api public
339
- def init(name)
340
- booter.init(name)
341
- self
342
- end
343
-
344
- # Stop a specific component but calls only `stop` lifecycle trigger
345
- #
346
- # @example
347
- # MyApp.stop(:persistence)
348
- #
349
- # @param [Symbol] name The name of a registered bootable component
350
- #
351
- # @return [self]
352
- #
353
- # @api public
354
- def stop(name)
355
- booter.stop(name)
356
- self
357
- end
358
-
359
- # Sets load paths relative to the container's root dir
360
- #
361
- # @example
362
- # class MyApp < Dry::System::Container
363
- # configure do |config|
364
- # # ...
365
- # end
366
- #
367
- # load_paths!('lib')
368
- # end
369
- #
370
- # @param [Array<String>] dirs
371
- #
372
- # @return [self]
373
- #
374
- # @api public
375
- def load_paths!(*dirs)
376
- dirs.map(&root.method(:join)).each do |path|
377
- next if load_paths.include?(path)
378
- load_paths << path
379
- $LOAD_PATH.unshift(path.to_s)
380
- end
381
- self
382
- end
383
-
384
- # @api public
385
- def load_registrations!(name)
386
- manual_registrar.(name)
387
- self
388
- end
389
-
390
- # Auto-registers components from the provided directory
391
- #
392
- # Typically you want to configure auto_register directories, and it will
393
- # work automatically. Use this method in cases where you want to have an
394
- # explicit way where some components are auto-registered, or if you want
395
- # to exclude some components from being auto-registered
396
- #
397
- # @example
398
- # class MyApp < Dry::System::Container
399
- # configure do |config|
400
- # # ...
401
- # end
402
- #
403
- # # with a dir
404
- # auto_register!('lib/core')
405
- #
406
- # # with a dir and a custom registration block
407
- # auto_register!('lib/core') do |config|
408
- # config.instance do |component|
409
- # # custom way of initializing a component
410
- # end
411
- #
412
- # config.exclude do |component|
413
- # # return true to exclude component from auto-registration
414
- # end
415
- # end
416
- # end
417
- #
418
- # @param [String] dir The dir name relative to the root dir
419
- #
420
- # @yield AutoRegistrar::Configuration
421
- # @see AutoRegistrar::Configuration
422
- #
423
- # @return [self]
424
- #
425
- # @api public
426
- def auto_register!(dir, &block)
427
- auto_registrar.(dir, &block)
428
- self
429
- end
430
-
431
- # Builds injector for this container
432
- #
433
- # An injector is a useful mixin which injects dependencies into
434
- # automatically defined constructor.
435
- #
436
- # @example
437
- # # Define an injection mixin
438
- # #
439
- # # system/import.rb
440
- # Import = MyApp.injector
441
- #
442
- # # Use it in your auto-registered classes
443
- # #
444
- # # lib/user_repo.rb
445
- # require 'import'
446
- #
447
- # class UserRepo
448
- # include Import['persistence.db']
449
- # end
450
- #
451
- # MyApp['user_repo].db # instance under 'persistence.db' key
452
- #
453
- # @param options [Hash] injector options
454
- #
455
- # @api public
456
- def injector(options = {})
457
- Dry::AutoInject(self, options)
458
- end
459
-
460
- # Requires one or more files relative to the container's root
461
- #
462
- # @example
463
- # # single file
464
- # MyApp.require_from_root('lib/core')
465
- #
466
- # # glob
467
- # MyApp.require_from_root('lib/**/*')
468
- #
469
- # @param paths [Array<String>] one or more paths, supports globs too
470
- #
471
- # @api public
472
- def require_from_root(*paths)
473
- paths.flat_map { |path|
474
- path.to_s.include?('*') ? Dir[root.join(path)] : root.join(path)
475
- }.each { |path|
476
- require path.to_s
477
- }
478
- end
479
-
480
- # Returns container's root path
481
- #
482
- # @example
483
- # class MyApp < Dry::System::Container
484
- # configure do |config|
485
- # config.root = Pathname('/my/app')
486
- # end
487
- # end
488
- #
489
- # MyApp.root # returns '/my/app' pathname
490
- #
491
- # @return [Pathname]
492
- #
493
- # @api public
494
- def root
495
- config.root
496
- end
497
-
498
- # @api public
499
- def resolve(key)
500
- load_component(key) unless finalized?
501
-
502
- super
503
- end
504
-
505
- # @api private
506
- def load_paths
507
- @load_paths ||= []
508
- end
509
-
510
- # @api private
511
- def booter
512
- @booter ||= config.booter.new(boot_path)
513
- end
514
-
515
- # @api private
516
- def boot_path
517
- root.join("#{config.system_dir}/boot")
518
- end
519
-
520
- # @api private
521
- def auto_registrar
522
- @auto_registrar ||= config.auto_registrar.new(self)
523
- end
524
-
525
- # @api private
526
- def manual_registrar
527
- @manual_registrar ||= config.manual_registrar.new(self)
528
- end
529
-
530
- # @api private
531
- def importer
532
- @importer ||= config.importer.new(self)
533
- end
534
-
535
- # @api private
536
- def component(identifier, **options)
537
- if (component = booter.components.detect { |c| c.identifier == identifier })
538
- component
539
- else
540
- Component.new(
541
- identifier,
542
- loader: config.loader,
543
- namespace: config.default_namespace,
544
- separator: config.namespace_separator,
545
- inflector: config.inflector,
546
- **options,
547
- )
548
- end
549
- end
550
-
551
- # @api private
552
- def require_component(component)
553
- return if key?(component.identifier)
554
-
555
- unless component.file_exists?(load_paths)
556
- raise FileNotFoundError, component
557
- end
558
-
559
- require component.path
560
-
561
- yield
562
- end
563
-
564
- # @api private
565
- def load_component(key)
566
- puts "load_component #{key}"
567
- return self if key?(key)
568
-
569
- component(key).tap do |component|
570
- if component.boot?
571
- booter.start(component)
572
- else
573
- root_key = component.root_key
574
-
575
- puts "root key:"
576
- p root_key
577
-
578
- # byebug
579
-
580
-
581
- # if (bootable_dep = component(root_key)).boot?
582
- # booter.start(bootable_dep)
583
-
584
- if importer.key?(root_key)
585
- load_imported_component(component.namespaced(root_key))
586
- else
587
- # Feels like we don't even need this if load_local_component gets involved with booting?
588
- booter.start(root_key) if booter.bootable?(root_key)
589
-
590
-
591
- load_local_component(component)
592
- end
593
-
594
-
595
-
596
- # if booter.bootable?(root_key)
597
- # booter.start(root_key)
598
- # elsif importer.key?(root_key)
599
- # load_imported_component(component.namespaced(root_key))
600
- # else
601
- # load_local_component(component)
602
- # end
603
- end
604
- end
605
-
606
- self
607
- end
608
-
609
- # @api private
610
- def after(event, &block)
611
- hooks[event] << block
612
- end
613
-
614
- # @api private
615
- def hooks
616
- @__hooks__ ||= Hash.new { |h, k| h[k] = [] }
617
- end
618
-
619
- # @api private
620
- def inherited(klass)
621
- new_hooks = Container.hooks.dup
622
-
623
- hooks.each do |event, blocks|
624
- new_hooks[event].concat(blocks)
625
- new_hooks[event].concat(klass.hooks[event])
626
- end
627
-
628
- klass.instance_variable_set(:@__hooks__, new_hooks)
629
- super
630
- end
631
-
632
- private
633
-
634
- # @api private
635
- def load_local_component(component, default_namespace_fallback = false)
636
- # byebug
637
-
638
- # if booter.bootable?(component)
639
- # booter.boot_dependency(component) unless finalized?
640
- # end
641
-
642
- if component.file_exists?(load_paths)
643
- require_component(component) do
644
- register(component.identifier) { component.instance }
645
- end
646
- elsif !default_namespace_fallback
647
- load_local_component(component.prepend(config.default_namespace), true)
648
- elsif manual_registrar.file_exists?(component)
649
- manual_registrar.(component)
650
- else
651
- raise ComponentLoadError, component
652
- end
653
- end
654
-
655
- # @api private
656
- def load_imported_component(component)
657
- container = importer[component.namespace]
658
- container.load_component(component.identifier)
659
- importer.(component.namespace, container)
660
- end
661
- end
662
- end
663
- end
664
- end
@@ -1,22 +0,0 @@
1
- module Dry
2
- module System
3
- module Plugins
4
- # @api public
5
- module Decorate
6
- # @api public
7
- def decorate(key, decorator:)
8
- original = _container.delete(key.to_s)
9
-
10
- if original.is_a?(Dry::Container::Item) && original.options[:call] && decorator.is_a?(Class)
11
- register(key) do
12
- decorator.new(original.call)
13
- end
14
- else
15
- decorated = decorator.is_a?(Class) ? decorator.new(original) : decorator
16
- register(key, decorated)
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end