dry-system 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/lib/dry/system.rb +24 -0
  4. data/lib/dry/system/booter.rb +75 -43
  5. data/lib/dry/system/booter/component_registry.rb +37 -0
  6. data/lib/dry/system/component.rb +9 -4
  7. data/lib/dry/system/components.rb +6 -0
  8. data/lib/dry/system/components/bootable.rb +307 -0
  9. data/lib/dry/system/components/config.rb +33 -0
  10. data/lib/dry/system/constants.rb +2 -0
  11. data/lib/dry/system/container.rb +69 -22
  12. data/lib/dry/system/errors.rb +2 -2
  13. data/lib/dry/system/lifecycle.rb +40 -7
  14. data/lib/dry/system/provider.rb +46 -0
  15. data/lib/dry/system/provider_registry.rb +25 -0
  16. data/lib/dry/system/settings.rb +59 -0
  17. data/lib/dry/system/settings/file_loader.rb +28 -0
  18. data/lib/dry/system/settings/file_parser.rb +49 -0
  19. data/lib/dry/system/system_components/settings.rb +9 -0
  20. data/lib/dry/system/version.rb +1 -1
  21. metadata +27 -144
  22. data/.gitignore +0 -39
  23. data/.rspec +0 -3
  24. data/.travis.yml +0 -22
  25. data/.yardopts +0 -5
  26. data/CONTRIBUTING.md +0 -29
  27. data/Gemfile +0 -9
  28. data/Rakefile +0 -12
  29. data/dry-system.gemspec +0 -31
  30. data/examples/custom_configuration_auto_register/Gemfile +0 -5
  31. data/examples/custom_configuration_auto_register/lib/entities/user.rb +0 -7
  32. data/examples/custom_configuration_auto_register/lib/user_repo.rb +0 -5
  33. data/examples/custom_configuration_auto_register/run.rb +0 -8
  34. data/examples/custom_configuration_auto_register/system/boot/persistence.rb +0 -13
  35. data/examples/custom_configuration_auto_register/system/container.rb +0 -16
  36. data/examples/custom_configuration_auto_register/system/import.rb +0 -3
  37. data/examples/standalone/Gemfile +0 -5
  38. data/examples/standalone/lib/user_repo.rb +0 -5
  39. data/examples/standalone/run.rb +0 -8
  40. data/examples/standalone/system/boot/persistence.rb +0 -13
  41. data/examples/standalone/system/container.rb +0 -9
  42. data/examples/standalone/system/import.rb +0 -3
  43. data/spec/fixtures/components/bar.rb +0 -5
  44. data/spec/fixtures/components/bar/baz.rb +0 -4
  45. data/spec/fixtures/components/foo.rb +0 -2
  46. data/spec/fixtures/components/no_register.rb +0 -4
  47. data/spec/fixtures/import_test/config/application.yml +0 -2
  48. data/spec/fixtures/import_test/lib/test/bar.rb +0 -4
  49. data/spec/fixtures/import_test/lib/test/foo.rb +0 -5
  50. data/spec/fixtures/import_test/system/boot/bar.rb +0 -11
  51. data/spec/fixtures/lazytest/config/application.yml +0 -2
  52. data/spec/fixtures/lazytest/lib/test/dep.rb +0 -4
  53. data/spec/fixtures/lazytest/lib/test/foo.rb +0 -5
  54. data/spec/fixtures/lazytest/lib/test/models.rb +0 -4
  55. data/spec/fixtures/lazytest/lib/test/models/book.rb +0 -6
  56. data/spec/fixtures/lazytest/lib/test/models/user.rb +0 -6
  57. data/spec/fixtures/lazytest/system/boot/bar.rb +0 -15
  58. data/spec/fixtures/magic_comments/comments.rb +0 -17
  59. data/spec/fixtures/manual_registration/container/foo.rb +0 -6
  60. data/spec/fixtures/manual_registration/lib/test/foo.rb +0 -9
  61. data/spec/fixtures/multiple_namespaced_components/multiple/level/baz.rb +0 -7
  62. data/spec/fixtures/multiple_namespaced_components/multiple/level/foz.rb +0 -6
  63. data/spec/fixtures/namespaced_components/namespaced/bar.rb +0 -5
  64. data/spec/fixtures/namespaced_components/namespaced/foo.rb +0 -4
  65. data/spec/fixtures/other/config/boot/bar.rb +0 -11
  66. data/spec/fixtures/other/config/boot/hell.rb +0 -3
  67. data/spec/fixtures/other/lib/test/dep.rb +0 -4
  68. data/spec/fixtures/other/lib/test/foo.rb +0 -5
  69. data/spec/fixtures/other/lib/test/models.rb +0 -4
  70. data/spec/fixtures/other/lib/test/models/book.rb +0 -6
  71. data/spec/fixtures/other/lib/test/models/user.rb +0 -6
  72. data/spec/fixtures/stubbing/lib/test/car.rb +0 -7
  73. data/spec/fixtures/stubbing/system/boot/db.rb +0 -8
  74. data/spec/fixtures/test/config/application.yml +0 -2
  75. data/spec/fixtures/test/config/subapp.yml +0 -2
  76. data/spec/fixtures/test/lib/test/dep.rb +0 -4
  77. data/spec/fixtures/test/lib/test/foo.rb +0 -5
  78. data/spec/fixtures/test/lib/test/models.rb +0 -4
  79. data/spec/fixtures/test/lib/test/models/book.rb +0 -6
  80. data/spec/fixtures/test/lib/test/models/user.rb +0 -6
  81. data/spec/fixtures/test/lib/test/singleton_dep.rb +0 -7
  82. data/spec/fixtures/test/log/.gitkeep +0 -0
  83. data/spec/fixtures/test/system/boot/bar.rb +0 -11
  84. data/spec/fixtures/test/system/boot/client.rb +0 -7
  85. data/spec/fixtures/test/system/boot/db.rb +0 -1
  86. data/spec/fixtures/test/system/boot/hell.rb +0 -3
  87. data/spec/fixtures/test/system/boot/logger.rb +0 -5
  88. data/spec/fixtures/umbrella/system/boot/db.rb +0 -10
  89. data/spec/integration/boot_spec.rb +0 -18
  90. data/spec/integration/container/lazy_loading/manual_registration_spec.rb +0 -18
  91. data/spec/integration/import_spec.rb +0 -81
  92. data/spec/spec_helper.rb +0 -48
  93. data/spec/unit/auto_registrar/configuration_spec.rb +0 -26
  94. data/spec/unit/component_spec.rb +0 -121
  95. data/spec/unit/container/auto_register_spec.rb +0 -113
  96. data/spec/unit/container/config_spec.rb +0 -38
  97. data/spec/unit/container/finalize_spec.rb +0 -97
  98. data/spec/unit/container/import_spec.rb +0 -53
  99. data/spec/unit/container/injector_spec.rb +0 -29
  100. data/spec/unit/container_spec.rb +0 -244
  101. data/spec/unit/loader_spec.rb +0 -64
  102. data/spec/unit/magic_comments_parser_spec.rb +0 -41
@@ -1,38 +0,0 @@
1
- require 'dry/system/container'
2
-
3
- RSpec.describe Dry::System::Container, '.config' do
4
- subject(:config) { Test::Container.config }
5
- let(:configuration) { proc { } }
6
-
7
- before do
8
- class Test::Container < Dry::System::Container
9
- end
10
- Test::Container.configure(&configuration)
11
- end
12
-
13
- describe '#root' do
14
- subject(:root) { config.root }
15
-
16
- context 'no value' do
17
- it 'defaults to pwd' do
18
- expect(root).to eq Pathname.pwd
19
- end
20
- end
21
-
22
- context 'string provided' do
23
- let(:configuration) { proc { |config| config.root = '/tmp' } }
24
-
25
- it 'coerces string paths to pathname' do
26
- expect(root).to eq Pathname('/tmp')
27
- end
28
- end
29
-
30
- context 'pathname provided' do
31
- let(:configuration) { proc { |config| config.root = Pathname('/tmp') } }
32
-
33
- it 'accepts the pathname' do
34
- expect(root).to eq Pathname('/tmp')
35
- end
36
- end
37
- end
38
- end
@@ -1,97 +0,0 @@
1
- RSpec.describe Dry::System::Container, '.finalize' do
2
- subject(:system) { Test::App }
3
-
4
- let(:db) { spy(:db) }
5
-
6
- before do
7
- Test.const_set(:DB, db)
8
-
9
- module Test
10
- class App < Dry::System::Container
11
- configure do |config|
12
- config.root = SPEC_ROOT.join('fixtures/test')
13
- end
14
-
15
- finalize(:db) do
16
- register(:db, Test::DB)
17
-
18
- init do
19
- db.establish_connection
20
- end
21
-
22
- start do
23
- db.load
24
- end
25
-
26
- stop do
27
- db.close_connection
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- describe '#init' do
35
- it 'calls init function' do
36
- system.booter.(:db).init
37
- expect(db).to have_received(:establish_connection)
38
- end
39
- end
40
-
41
- describe '#start' do
42
- it 'calls start function' do
43
- system.booter.(:db).start
44
- expect(db).to have_received(:load)
45
- end
46
- end
47
-
48
- describe '#stop' do
49
- it 'calls stop function' do
50
- system.booter.(:db).stop
51
- expect(db).to have_received(:close_connection)
52
- end
53
- end
54
-
55
- specify 'boot triggers init' do
56
- system.booter.init(:db)
57
-
58
- expect(db).to have_received(:establish_connection)
59
- expect(db).to_not have_received(:load)
60
- end
61
-
62
- specify 'start triggers init + start' do
63
- system.booter.start(:db)
64
-
65
- expect(db).to have_received(:establish_connection)
66
- expect(db).to have_received(:load)
67
- end
68
-
69
- specify 'start raises error on undefined method or variable' do
70
- expect {
71
- system.finalize(:db) { oops('arg') }
72
- system.booter.start(:db)
73
- }.to raise_error(NoMethodError, /oops/)
74
-
75
- expect {
76
- system.finalize(:db) { oops }
77
- system.booter.start(:db)
78
- }.to raise_error(NameError, /oops/)
79
- end
80
-
81
- specify 'booter returns cached lifecycle objects' do
82
- expect(system.booter.(:db)).to be(system.booter.(:db))
83
- end
84
-
85
- specify 'lifecycle triggers are called only once' do
86
- system.booter.start(:db)
87
- system.booter.start(:db)
88
-
89
- system.booter.init(:db)
90
- system.booter.init(:db)
91
-
92
- expect(db).to have_received(:establish_connection).exactly(1)
93
- expect(db).to have_received(:load).exactly(1)
94
-
95
- expect(system.booter.(:db).statuses).to eql(%i[init start])
96
- end
97
- end
@@ -1,53 +0,0 @@
1
- require 'dry/system/container'
2
-
3
- RSpec.describe Dry::System::Container, '.import' do
4
- subject(:app) { Class.new(Dry::System::Container) }
5
-
6
- let(:db) do
7
- Class.new(Dry::System::Container) do
8
- register(:users, %w(jane joe))
9
- end
10
- end
11
-
12
- it 'imports one container into another' do
13
- app.import(persistence: db)
14
-
15
- expect(app.key?('persistence.users')).to be(false)
16
-
17
- app.finalize!
18
-
19
- expect(app['persistence.users']).to eql(%w(jane joe))
20
- end
21
-
22
- describe 'import module' do
23
- it 'loads system when it was not loaded in the imported container yet' do
24
- class Test::Other < Dry::System::Container
25
- configure do |config|
26
- config.root = SPEC_ROOT.join('fixtures/import_test').realpath
27
- end
28
-
29
- load_paths!('lib')
30
- end
31
-
32
- class Test::Container < Dry::System::Container
33
- configure do |config|
34
- config.root = SPEC_ROOT.join('fixtures/test').realpath
35
- end
36
-
37
- load_paths!('lib')
38
-
39
- import other: Test::Other
40
- end
41
-
42
- module Test
43
- Import = Container.injector
44
- end
45
-
46
- class Test::Foo
47
- include Test::Import['other.test.bar']
48
- end
49
-
50
- expect(Test::Foo.new.bar).to be_instance_of(Test::Bar)
51
- end
52
- end
53
- end
@@ -1,29 +0,0 @@
1
- require "dry/system/container"
2
-
3
- RSpec.describe Dry::System::Container, ".injector" do
4
- context "injector_options provided" do
5
- it "builds an injector with the provided options" do
6
- Test::Foo = Class.new
7
-
8
- Test::Container = Class.new(Dry::System::Container) do
9
- register "foo", Test::Foo.new
10
- end
11
-
12
- Test::Inject = Test::Container.injector(strategies: {
13
- default: Dry::AutoInject::Strategies::Args,
14
- australian: Dry::AutoInject::Strategies::Args
15
- })
16
-
17
- injected_class = Class.new do
18
- include Test::Inject.australian["foo"]
19
- end
20
-
21
- obj = injected_class.new
22
- expect(obj.foo).to be_a Test::Foo
23
-
24
- another = Object.new
25
- obj = injected_class.new(another)
26
- expect(obj.foo).to eq another
27
- end
28
- end
29
- end
@@ -1,244 +0,0 @@
1
- require 'dry/system/container'
2
- require 'dry/system/stubs'
3
-
4
- RSpec.describe Dry::System::Container do
5
- subject(:container) { Test::Container }
6
-
7
- context 'with default core dir' do
8
- before do
9
- class Test::Container < Dry::System::Container
10
- configure do |config|
11
- config.root = SPEC_ROOT.join('fixtures/test').realpath
12
- end
13
-
14
- load_paths!('lib')
15
- end
16
-
17
- module Test
18
- Import = Container.injector
19
- end
20
- end
21
-
22
- describe '.require' do
23
- it 'requires a single file' do
24
- container.require(Pathname('lib/test/models'))
25
-
26
- expect(Test.const_defined?(:Models)).to be(true)
27
- end
28
-
29
- it 'requires many files when glob pattern is passed' do
30
- container.require(Pathname('lib/test/models/*.rb'))
31
-
32
- expect(Test::Models.const_defined?(:User)).to be(true)
33
- expect(Test::Models.const_defined?(:Book)).to be(true)
34
- end
35
- end
36
-
37
- describe '.require_component' do
38
-
39
- shared_examples_for 'requireable' do
40
- it 'requires component file' do
41
- component = container.component('test/foo')
42
- required = false
43
- container.require_component(component) do
44
- required = true
45
- end
46
- expect(required).to be(true)
47
- end
48
- end
49
-
50
- it_behaves_like 'requireable'
51
-
52
- context 'when already required' do
53
- before do
54
- Kernel.require('test/foo')
55
- end
56
-
57
- it_behaves_like 'requireable'
58
- end
59
-
60
- it 'raises when file does not exist' do
61
- component = container.component('test/missing')
62
- expect { container.require_component(component) }.to raise_error(
63
- Dry::System::FileNotFoundError, /test\.missing/
64
- )
65
- end
66
-
67
- it 'returns for already registered components' do
68
- component = container.component('test/foo')
69
-
70
- registrar = -> {
71
- container.register(component.identifier) { component.instance }
72
- }
73
-
74
- container.require_component(component, &registrar)
75
-
76
- required = false
77
- registrar = -> { required = true }
78
- container.require_component(component, &registrar)
79
- expect(required).to be(false)
80
- end
81
- end
82
-
83
- describe '.load_component' do
84
- it 'loads and registers systems from configured load paths' do
85
- container.load_component('test.foo')
86
-
87
- expect(Test::Foo.new.dep).to be_instance_of(Test::Dep)
88
- end
89
-
90
- it "raises an error if a system's file can't be found" do
91
- expect { container.load_component('test.missing') }.to raise_error(
92
- Dry::System::ComponentLoadError, /test\.missing/
93
- )
94
- end
95
-
96
- it "is a no op if a matching system is already registered" do
97
- container.register "test.no_matching_file", Object.new
98
-
99
- expect { container.load_component("test.no_matching_file") }.not_to raise_error
100
- end
101
- end
102
- end
103
-
104
- describe '.init' do
105
- before do
106
- class Test::Container < Dry::System::Container
107
- configure do |config|
108
- config.root = SPEC_ROOT.join('fixtures/lazytest').realpath
109
- end
110
-
111
- load_paths!('lib')
112
- end
113
- end
114
-
115
- it 'lazy-boot a given system' do
116
- container.init(:bar)
117
-
118
- expect(Test.const_defined?(:Bar)).to be(true)
119
- expect(container.key?('test.bar')).to be(false)
120
- end
121
- end
122
-
123
- describe '.start' do
124
- shared_examples_for 'a booted system' do
125
- it 'boots a given system and finalizes it' do
126
- container.start(:bar)
127
-
128
- expect(Test.const_defined?(:Bar)).to be(true)
129
- expect(container['test.bar']).to eql('I was finalized')
130
- end
131
-
132
- it 'expects a symbol identifier matching file name' do
133
- expect {
134
- container.start('bar')
135
- }.to raise_error(ArgumentError, 'component identifier "bar" must be a symbol')
136
- end
137
-
138
- it 'expects identifier to point to an existing boot file' do
139
- expect {
140
- container.start(:foo)
141
- }.to raise_error(
142
- ArgumentError,
143
- 'component identifier +foo+ is invalid or boot file is missing'
144
- )
145
- end
146
-
147
- describe "missmatch betwenn finalize name and registered component" do
148
- it "raises a meaningful error" do
149
- expect{
150
- container.start(:hell)
151
- }.to raise_error(Dry::System::ComponentFileMismatchError)
152
- end
153
- end
154
- end
155
-
156
- context 'with the default core dir' do
157
- it_behaves_like 'a booted system' do
158
- before do
159
- class Test::Container < Dry::System::Container
160
- configure do |config|
161
- config.root = SPEC_ROOT.join('fixtures/test').realpath
162
- end
163
-
164
- load_paths!('lib')
165
- end
166
- end
167
- end
168
- end
169
-
170
- context 'with a custom core dir' do
171
- it_behaves_like 'a booted system' do
172
- before do
173
- class Test::Container < Dry::System::Container
174
- configure do |config|
175
- config.root = SPEC_ROOT.join('fixtures/other').realpath
176
- config.system_dir = 'config'
177
- end
178
-
179
- load_paths!('lib')
180
- end
181
- end
182
- end
183
- end
184
-
185
- it 'passes container to the finalizer block' do
186
- class Test::Container < Dry::System::Container
187
- configure { |c| c.name = :awesome }
188
-
189
- finalize(:foo) do |container|
190
- register(:w00t, container.config.name)
191
- end
192
- end
193
-
194
- Test::Container.booter.(:foo)
195
-
196
- expect(Test::Container[:w00t]).to be(:awesome)
197
- end
198
- end
199
-
200
- describe '.stub' do
201
- let(:stubbed_car) do
202
- instance_double(Test::Car, wheels_count: 5)
203
- end
204
-
205
- before do
206
- class Test::Container < Dry::System::Container
207
- configure do |config|
208
- config.root = SPEC_ROOT.join('fixtures/stubbing').realpath
209
- end
210
-
211
- load_paths!('lib')
212
- auto_register!('lib')
213
- end
214
- end
215
-
216
- describe 'with stubs disabled' do
217
- it 'raises error when trying to stub frozen container' do
218
- expect { container.stub('test.car', stubbed_car) }.to raise_error(NoMethodError, /stub/)
219
- end
220
- end
221
-
222
- describe 'with stubs enabled' do
223
- before do
224
- container.enable_stubs!
225
- end
226
-
227
- it 'lazy-loads a component' do
228
- expect(container[:db]).to be_instance_of(Test::DB)
229
- container.finalize!
230
- expect(container[:db]).to be_instance_of(Test::DB)
231
- end
232
-
233
- it 'allows to stub components' do
234
- container.finalize!
235
-
236
- expect(container['test.car'].wheels_count).to be(4)
237
-
238
- container.stub('test.car', stubbed_car)
239
-
240
- expect(container['test.car'].wheels_count).to be(5)
241
- end
242
- end
243
- end
244
- end