jerry 1.0.1 → 2.0.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/.gitignore +1 -2
- data/.reek +2 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +11 -2
- data/.yardopts +8 -1
- data/Gemfile +0 -2
- data/Guardfile +16 -0
- data/README.md +93 -78
- data/Rakefile +20 -1
- data/bin/console +3 -0
- data/bin/guard +3 -0
- data/bin/rake +3 -0
- data/bin/setup +3 -0
- data/doc/multiple-configurations.md +51 -0
- data/jerry.gemspec +8 -3
- data/lib/jerry/class_provider.rb +30 -0
- data/lib/jerry/config.rb +64 -61
- data/lib/jerry/errors.rb +16 -0
- data/lib/jerry/version.rb +1 -1
- data/lib/jerry.rb +27 -39
- data/spec/class_provider_spec.rb +109 -0
- data/spec/config_spec.rb +152 -132
- data/spec/error_spec.rb +23 -0
- data/spec/examples_spec.rb +120 -0
- data/spec/fixtures/db_app.rb +17 -0
- data/spec/fixtures/house.rb +15 -0
- data/spec/fixtures/multi_db_app.rb +31 -0
- data/spec/fixtures/shopping_cart.rb +70 -0
- data/spec/fixtures/shopping_cart_config.rb +27 -0
- data/spec/jerry_spec.rb +45 -110
- data/spec/spec_helper.rb +3 -5
- metadata +117 -9
- data/spec/support/silence_warnings.rb +0 -7
data/lib/jerry.rb
CHANGED
@@ -1,53 +1,41 @@
|
|
1
1
|
require 'jerry/version'
|
2
|
+
require 'jerry/errors'
|
2
3
|
require 'jerry/config'
|
3
4
|
|
4
5
|
# Inversion of Control container.
|
5
6
|
#
|
6
|
-
# This class is in charge of bootstrapping your application. This is done by
|
7
|
+
# This class is in charge of bootstrapping your application. This is done by
|
8
|
+
# defining {Jerry::Config configs}.
|
7
9
|
#
|
8
|
-
# @example
|
9
|
-
# class
|
10
|
-
#
|
10
|
+
# @example Basic usage
|
11
|
+
# class FooConfig < Jerry::Config
|
12
|
+
# # ...
|
11
13
|
# end
|
12
|
-
#
|
13
|
-
#
|
14
|
+
#
|
15
|
+
# class BarConfig < Jerry::Config
|
16
|
+
# # ...
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# jerry = Jerry.new FooConfig.new, BarConfig.new
|
20
|
+
# jerry[SomeClass] #=> #<Someclass:...>
|
14
21
|
class Jerry
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
# @param [Jerry::Config] configs Configs used to rig components. Multiple config can be given. If two configs
|
19
|
-
# define the same component, the later config will have priority.
|
22
|
+
# @param configs [Array<Jerry::Config>] configurations describing how to wire
|
23
|
+
# your application
|
20
24
|
def initialize(*configs)
|
21
|
-
|
22
|
-
|
23
|
-
configs.each { |config| self << config }
|
24
|
-
end
|
25
|
-
|
26
|
-
# Load a config
|
27
|
-
#
|
28
|
-
# @param [Jerry::Config] config Config to be loaded. If the loaded config defines a component already defined
|
29
|
-
# by another config, the component from the new config will take priority.
|
30
|
-
def <<(config)
|
31
|
-
components = config.components
|
32
|
-
components.each { |component| @index[component] = config }
|
33
|
-
config.jerry = self
|
34
|
-
end
|
35
|
-
|
36
|
-
# Rigs a component
|
37
|
-
#
|
38
|
-
# @param [Symbol] component Component to rig.
|
39
|
-
# @return The component requested
|
40
|
-
# @raise [Jerry::RigError] when the requested component does not exist
|
41
|
-
def rig(component)
|
42
|
-
raise RigError, "could not find component #{component}" unless knows? component
|
25
|
+
configs.each { |conf| conf.jerry = self }
|
43
26
|
|
44
|
-
@
|
27
|
+
@configs = configs
|
45
28
|
end
|
46
29
|
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# @
|
50
|
-
def
|
51
|
-
@
|
30
|
+
# @param key what to provide
|
31
|
+
# @return an insance of the sepcified key provided by one of the configs
|
32
|
+
# @raise [Jerry::InstantiationError] if can't instanciate key
|
33
|
+
def [](key)
|
34
|
+
config = @configs.find { |conf| conf.knows? key }
|
35
|
+
if config
|
36
|
+
config[key]
|
37
|
+
else
|
38
|
+
fail Jerry::InstantiationError, "Can't find #{key} in any config"
|
39
|
+
end
|
52
40
|
end
|
53
41
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'jerry/class_provider'
|
2
|
+
|
3
|
+
describe Jerry::ClassProvider do
|
4
|
+
let(:jerry) { double 'jerry' }
|
5
|
+
let(:config) { double 'config' }
|
6
|
+
let(:klass) { dummy_class }
|
7
|
+
|
8
|
+
def dummy_class
|
9
|
+
Class.new do
|
10
|
+
define_method(:initialize) { |*| }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#call' do
|
15
|
+
it 'should return an instance of the class' do
|
16
|
+
provider = Jerry::ClassProvider.new klass, []
|
17
|
+
instance = double 'instance'
|
18
|
+
allow(klass).to receive(:new).and_return(instance)
|
19
|
+
|
20
|
+
expect(provider.call jerry, config).to eq instance
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should pass constructor arguments in the right order' do
|
24
|
+
provider = Jerry::ClassProvider.new klass, [
|
25
|
+
proc { 'fi' }, proc { 'fo' }, proc { 'fum' }]
|
26
|
+
|
27
|
+
expect(klass).to receive(:new).with('fi', 'fo', 'fum')
|
28
|
+
|
29
|
+
provider.call jerry, config
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'with a class argument' do
|
34
|
+
it 'should get the instance from jerry' do
|
35
|
+
arg_klass = dummy_class
|
36
|
+
provider = Jerry::ClassProvider.new klass, [arg_klass]
|
37
|
+
|
38
|
+
expect(jerry).to receive(:[]).with(arg_klass)
|
39
|
+
|
40
|
+
provider.call jerry, config
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should pass the instance from jerry to the constructor' do
|
44
|
+
provider = Jerry::ClassProvider.new klass, [dummy_class]
|
45
|
+
instance = double 'instance'
|
46
|
+
allow(jerry).to receive(:[]).and_return(instance)
|
47
|
+
|
48
|
+
expect(klass).to receive(:new).with(instance)
|
49
|
+
|
50
|
+
provider.call jerry, config
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'with a symbol argument' do
|
55
|
+
it 'should get the instance from jerry' do
|
56
|
+
provider = Jerry::ClassProvider.new klass, [:foobar]
|
57
|
+
|
58
|
+
expect(jerry).to receive(:[]).with(:foobar)
|
59
|
+
|
60
|
+
provider.call jerry, config
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should pass the instance from jerry to the constructor' do
|
64
|
+
provider = Jerry::ClassProvider.new klass, [:foobar]
|
65
|
+
instance = double 'instance'
|
66
|
+
allow(jerry).to receive(:[]).with(:foobar).and_return(instance)
|
67
|
+
|
68
|
+
expect(klass).to receive(:new).with(instance)
|
69
|
+
|
70
|
+
provider.call jerry, config
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'with callable argument' do
|
75
|
+
it 'should call the callable' do
|
76
|
+
expect do |callable|
|
77
|
+
provider = Jerry::ClassProvider.new klass, [callable.to_proc]
|
78
|
+
provider.call jerry, config
|
79
|
+
end.to yield_control
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should pass the result of the callable to the constructor' do
|
83
|
+
instance = double 'instance'
|
84
|
+
provider = Jerry::ClassProvider.new klass, [proc { instance }]
|
85
|
+
|
86
|
+
expect(klass).to receive(:new).with(instance)
|
87
|
+
|
88
|
+
provider.call jerry, config
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should pass the jerry and config instance to the proc' do
|
92
|
+
expect do |callable|
|
93
|
+
provider = Jerry::ClassProvider.new klass, [callable.to_proc]
|
94
|
+
provider.call jerry, config
|
95
|
+
end.to yield_with_args(jerry, config)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should call the proc in the context of the config' do
|
99
|
+
config = double 'config'
|
100
|
+
config.instance_eval { @stuff = 'something private' }
|
101
|
+
callable = proc { @stuff }
|
102
|
+
provider = Jerry::ClassProvider.new klass, [callable]
|
103
|
+
|
104
|
+
expect(klass).to receive(:new).with('something private')
|
105
|
+
|
106
|
+
provider.call jerry, config
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/spec/config_spec.rb
CHANGED
@@ -1,172 +1,192 @@
|
|
1
|
-
require 'rspec'
|
2
1
|
require 'jerry/config'
|
2
|
+
require 'fixtures/house'
|
3
3
|
|
4
4
|
describe Jerry::Config do
|
5
|
-
let(:
|
5
|
+
let(:config_klass) { Class.new Jerry::Config }
|
6
|
+
let(:config) { config_klass.new }
|
7
|
+
let(:jerry) { double 'jerry' }
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
expect(klass).to respond_to :components
|
10
|
-
expect(klass).to respond_to :component
|
11
|
-
end
|
9
|
+
before do
|
10
|
+
config.jerry = jerry
|
12
11
|
end
|
13
12
|
|
14
|
-
describe '
|
15
|
-
it 'should
|
16
|
-
|
17
|
-
|
18
|
-
expect(
|
13
|
+
describe '::bind' do
|
14
|
+
it 'should create a class provider' do
|
15
|
+
klass = double 'class'
|
16
|
+
args = [Class.new, :foobar, -> { 'stuff' }]
|
17
|
+
expect(Jerry::ClassProvider).to receive(:new).with(klass, args)
|
19
18
|
|
20
|
-
|
19
|
+
Class.new Jerry::Config do
|
20
|
+
bind klass, args
|
21
|
+
end
|
21
22
|
end
|
22
|
-
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
it 'should default ctor_args to empty array' do
|
25
|
+
expect(Jerry::ClassProvider).to receive(:new).with(anything, [])
|
26
|
+
|
27
|
+
Class.new Jerry::Config do
|
28
|
+
bind Class.new
|
29
|
+
end
|
30
|
+
end
|
29
31
|
|
30
|
-
|
32
|
+
it 'should use the class to identify the provider' do
|
33
|
+
klass = Class.new
|
34
|
+
config = Class.new Jerry::Config do
|
35
|
+
bind klass
|
36
|
+
end
|
31
37
|
|
32
|
-
config.
|
38
|
+
expect(config.providers).to have_key klass
|
33
39
|
end
|
34
40
|
|
35
|
-
it 'should return the
|
36
|
-
|
37
|
-
|
38
|
-
config = klass.new
|
39
|
-
config.jerry = jerry
|
41
|
+
it 'should return the class' do
|
42
|
+
klass = Class.new
|
43
|
+
thing = nil
|
40
44
|
|
41
|
-
|
45
|
+
Class.new Jerry::Config do
|
46
|
+
thing = bind klass
|
47
|
+
end
|
48
|
+
|
49
|
+
expect(thing).to eq klass
|
42
50
|
end
|
43
51
|
end
|
44
52
|
|
45
|
-
describe '
|
46
|
-
it 'should
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
describe '::named_bind' do
|
54
|
+
it 'should create a class provider' do
|
55
|
+
klass = double 'class'
|
56
|
+
args = [Class.new, :foobar, proc { 'stuff' }]
|
57
|
+
expect(Jerry::ClassProvider).to receive(:new).with(klass, args)
|
50
58
|
|
51
|
-
|
59
|
+
Class.new Jerry::Config do
|
60
|
+
named_bind :stuff, klass, args
|
61
|
+
end
|
62
|
+
end
|
52
63
|
|
53
|
-
|
64
|
+
it 'should default ctor args to emtpy array' do
|
65
|
+
expect(Jerry::ClassProvider).to receive(:new).with(anything, [])
|
66
|
+
|
67
|
+
Class.new Jerry::Config do
|
68
|
+
named_bind :thing, Class.new
|
69
|
+
end
|
54
70
|
end
|
55
71
|
|
56
|
-
it 'should
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
config.jerry = jerry
|
72
|
+
it 'should use the given key to store the provider' do
|
73
|
+
config = Class.new Jerry::Config do
|
74
|
+
named_bind :the_name, Class.new
|
75
|
+
end
|
61
76
|
|
62
|
-
expect(config.
|
77
|
+
expect(config.providers).to have_key :the_name
|
63
78
|
end
|
64
|
-
end
|
65
79
|
|
66
|
-
|
67
|
-
|
68
|
-
it 'should create a method with the given name' do
|
69
|
-
klass.component(:my_component) {}
|
80
|
+
it 'should return the key' do
|
81
|
+
thing = nil
|
70
82
|
|
71
|
-
|
83
|
+
Class.new Jerry::Config do
|
84
|
+
thing = named_bind :foobar, Class.new
|
72
85
|
end
|
73
86
|
|
74
|
-
|
75
|
-
|
87
|
+
expect(thing).to eq :foobar
|
88
|
+
end
|
89
|
+
end
|
76
90
|
|
77
|
-
|
91
|
+
describe '::singleton' do
|
92
|
+
it 'should always use the same instance' do
|
93
|
+
config = Class.new Jerry::Config do
|
94
|
+
singleton named_bind :thing, Class.new
|
78
95
|
end
|
79
96
|
|
80
|
-
|
81
|
-
|
97
|
+
jerry = Jerry.new config.new
|
98
|
+
thing1 = jerry[:thing]
|
99
|
+
thing2 = jerry[:thing]
|
100
|
+
|
101
|
+
expect(thing1).to equal thing2
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should only instantiate the class once' do
|
105
|
+
klass = double 'class', new: double('instance')
|
106
|
+
config = Class.new Jerry::Config do
|
107
|
+
singleton bind klass
|
82
108
|
end
|
83
109
|
|
84
|
-
|
85
|
-
|
110
|
+
expect(klass).to receive(:new).once
|
111
|
+
|
112
|
+
jerry = Jerry.new config.new
|
113
|
+
2.times { jerry[klass] }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#[]' do
|
118
|
+
it 'should get the provider instance from ::bind' do
|
119
|
+
instance = double 'instance'
|
120
|
+
klass = double 'class', new: instance
|
121
|
+
|
122
|
+
config_klass.class_eval do
|
123
|
+
bind klass
|
86
124
|
end
|
87
125
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
call_count = 0
|
123
|
-
klass.component(:target, scope: :instance) {call_count += 1}
|
124
|
-
instance = klass.new
|
125
|
-
|
126
|
-
3.times {instance.target}
|
127
|
-
|
128
|
-
expect(call_count).to eq(3)
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'should return a new instance every time' do
|
132
|
-
call_count = 0
|
133
|
-
klass.component(:target, scope: :instance) {call_count += 1}
|
134
|
-
instance = klass.new
|
135
|
-
|
136
|
-
expect(instance.target).to eq(1)
|
137
|
-
expect(instance.target).to eq(2)
|
138
|
-
expect(instance.target).to eq(3)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context 'with no scope' do
|
143
|
-
it 'should only call the block once' do
|
144
|
-
call_count = 0
|
145
|
-
klass.component(:target) {call_count += 1}
|
146
|
-
instance = klass.new
|
147
|
-
|
148
|
-
3.times {instance.target}
|
149
|
-
|
150
|
-
expect(call_count).to eq(1)
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'should keep returning the first created component' do
|
154
|
-
call_count = 0
|
155
|
-
klass.component(:target) {call_count += 1}
|
156
|
-
instance = klass.new
|
157
|
-
|
158
|
-
expect(instance.target).to eq(1)
|
159
|
-
expect(instance.target).to eq(1)
|
160
|
-
expect(instance.target).to eq(1)
|
161
|
-
end
|
162
|
-
end
|
126
|
+
expect(config[klass]).to eq instance
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should pass jerry to the provider' do
|
130
|
+
provider = double 'provider'
|
131
|
+
config_klass.send(:providers)[:foobar] = provider
|
132
|
+
|
133
|
+
expect(provider).to receive(:call).with(jerry, anything)
|
134
|
+
|
135
|
+
config[:foobar]
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should pass config instance to the provider' do
|
139
|
+
provider = double 'provider'
|
140
|
+
config_klass.providers[:something] = provider
|
141
|
+
|
142
|
+
expect(provider).to receive(:call).with(anything, config)
|
143
|
+
|
144
|
+
config[:something]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should fail when provider is missing' do
|
148
|
+
expect { config[:not_there] }.to raise_error(Jerry::InstantiationError)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should wrap errors from the provider' do
|
152
|
+
provider = double 'provider'
|
153
|
+
allow(provider).to receive(:call)
|
154
|
+
.and_raise(RuntimeError, 'something blew up')
|
155
|
+
config_klass.providers[:failing] = provider
|
156
|
+
|
157
|
+
expect { config[:failing] }
|
158
|
+
.to raise_error(Jerry::InstantiationError) do |e|
|
159
|
+
expect(e.cause.message).to eq 'something blew up'
|
163
160
|
end
|
164
161
|
end
|
165
162
|
|
166
|
-
|
167
|
-
|
168
|
-
|
163
|
+
it 'should set self to config instance for all procs in spec' do
|
164
|
+
klass = Class.new do
|
165
|
+
attr_reader :thing
|
166
|
+
define_method(:initialize) { |thing| @thing = thing }
|
167
|
+
end
|
168
|
+
config_klass = Class.new(Jerry::Config) do
|
169
|
+
define_method(:initialize) { @foobar = 'something private' }
|
170
|
+
bind klass, [proc { @foobar }]
|
169
171
|
end
|
172
|
+
config = config_klass.new
|
173
|
+
config.jerry = jerry
|
174
|
+
|
175
|
+
instance = config[klass]
|
176
|
+
expect(instance.thing).to eq 'something private'
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe '#knows?' do
|
181
|
+
it 'should be true if key is in providers' do
|
182
|
+
key = double 'some key'
|
183
|
+
config_klass.providers[key] = double 'some provider'
|
184
|
+
|
185
|
+
expect(config.knows? key).to be true
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should be false if key is not known' do
|
189
|
+
expect(config.knows? double('some unknown key')).to be false
|
170
190
|
end
|
171
191
|
end
|
172
|
-
end
|
192
|
+
end
|
data/spec/error_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
describe Jerry::Error do
|
2
|
+
def raise_error_with_cause
|
3
|
+
fail 'Something went wrong'
|
4
|
+
rescue RuntimeError
|
5
|
+
raise Jerry::Error, 'wrapping error'
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should record the causing exception when there is one' do
|
9
|
+
expect { raise_error_with_cause }.to raise_error(Jerry::Error) do |ex|
|
10
|
+
expect(ex.cause.message).to eq 'Something went wrong'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should not record the causing exception when there is none' do
|
15
|
+
expect { fail Jerry::Error }.to raise_error(Jerry::Error) do |ex|
|
16
|
+
expect(ex.cause).to be_nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should have a message' do
|
21
|
+
expect { fail Jerry::Error, ':(' }.to raise_error(Jerry::Error, ':(')
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'jerry'
|
2
|
+
require 'fixtures/house'
|
3
|
+
require 'fixtures/db_app'
|
4
|
+
require 'fixtures/shopping_cart'
|
5
|
+
require 'fixtures/shopping_cart_config'
|
6
|
+
require 'fixtures/multi_db_app'
|
7
|
+
|
8
|
+
describe Jerry do
|
9
|
+
it 'should wire dependencies' do
|
10
|
+
HousingModule = Class.new(Jerry::Config) do
|
11
|
+
bind House, [Door, Window]
|
12
|
+
bind Window, []
|
13
|
+
bind Door, []
|
14
|
+
end
|
15
|
+
|
16
|
+
jerry = Jerry.new HousingModule.new
|
17
|
+
|
18
|
+
house = jerry[House]
|
19
|
+
|
20
|
+
expect(house).to be_a House
|
21
|
+
expect(house.window).to be_a Window
|
22
|
+
expect(house.door).to be_a Door
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should allow the use of procs to wire settings' do
|
26
|
+
AppConfig = Class.new Jerry::Config do
|
27
|
+
def initialize(database_uri)
|
28
|
+
@database_uri = database_uri
|
29
|
+
end
|
30
|
+
|
31
|
+
bind DbApplication, [Database]
|
32
|
+
bind Database, [proc { @database_uri }]
|
33
|
+
end
|
34
|
+
|
35
|
+
jerry = Jerry.new AppConfig.new('mongodb://localhost:27017')
|
36
|
+
app = jerry[DbApplication]
|
37
|
+
|
38
|
+
expect(app).to be_a DbApplication
|
39
|
+
expect(app.db).to be_a Database
|
40
|
+
expect(app.db.uri).to eq 'mongodb://localhost:27017'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should support multiple configs' do
|
44
|
+
jerry = Jerry.new(
|
45
|
+
ShoppingCart::DatabaseConfig.new,
|
46
|
+
ShoppingCart::ApplicationConfig.new,
|
47
|
+
ShoppingCart::UserConfig.new,
|
48
|
+
ShoppingCart::ProductConfig.new,
|
49
|
+
ShoppingCart::ShoppingCartConfig.new
|
50
|
+
)
|
51
|
+
|
52
|
+
app = jerry[ShoppingCart::Application]
|
53
|
+
|
54
|
+
expect(app).to be_a ShoppingCart::Application
|
55
|
+
|
56
|
+
expect(app.user_controller).to be_a ShoppingCart::UserController
|
57
|
+
expect(app.product_controller).to be_a ShoppingCart::ProductController
|
58
|
+
expect(app.shopping_cart_controller).to \
|
59
|
+
be_a ShoppingCart::ShoppingCartController
|
60
|
+
|
61
|
+
expect(app.user_controller.user_service).to be_a ShoppingCart::UserService
|
62
|
+
expect(app.product_controller.product_service).to \
|
63
|
+
be_a ShoppingCart::ProductService
|
64
|
+
expect(app.shopping_cart_controller.shopping_cart_service).to \
|
65
|
+
be_a ShoppingCart::ShoppingCartService
|
66
|
+
|
67
|
+
expect(app.user_controller.user_service.db).to be_a ShoppingCart::Database
|
68
|
+
expect(app.product_controller.product_service.db).to \
|
69
|
+
be_a ShoppingCart::Database
|
70
|
+
expect(app.shopping_cart_controller.shopping_cart_service.db).to \
|
71
|
+
be_a ShoppingCart::Database
|
72
|
+
|
73
|
+
shopping_cart_service = app.shopping_cart_controller.shopping_cart_service
|
74
|
+
expect(shopping_cart_service.user_service).to be_a ShoppingCart::UserService
|
75
|
+
expect(shopping_cart_service.product_service).to \
|
76
|
+
be_a ShoppingCart::ProductService
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should support wiring one class in multiple ways through naming' do
|
80
|
+
jerry = Jerry.new MultiDbApp::Config.new('db://foo', 'db://bar')
|
81
|
+
|
82
|
+
app = jerry[MultiDbApp::Application]
|
83
|
+
|
84
|
+
expect(app.foo_db.uri).to eq 'db://foo'
|
85
|
+
expect(app.bar_db.uri).to eq 'db://bar'
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should wire the same class multiple times with multiple names' do
|
89
|
+
klass = Class.new do
|
90
|
+
attr_reader :str
|
91
|
+
define_method(:initialize) { |str| @str = str }
|
92
|
+
end
|
93
|
+
config = Class.new Jerry::Config do
|
94
|
+
named_bind :foo, klass, [proc { 'foo' }]
|
95
|
+
named_bind :bar, klass, [proc { 'bar' }]
|
96
|
+
end
|
97
|
+
jerry = Jerry.new config.new
|
98
|
+
|
99
|
+
foo = jerry[:foo]
|
100
|
+
bar = jerry[:bar]
|
101
|
+
|
102
|
+
expect(foo).to be_a klass
|
103
|
+
expect(foo.str).to eq 'foo'
|
104
|
+
expect(bar).to be_a klass
|
105
|
+
expect(bar.str).to eq 'bar'
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should always wire the same instance when using singleton' do
|
109
|
+
klass = Class.new
|
110
|
+
config = Class.new Jerry::Config do
|
111
|
+
singleton bind klass
|
112
|
+
end
|
113
|
+
jerry = Jerry.new config.new
|
114
|
+
|
115
|
+
alfa = jerry[klass]
|
116
|
+
bravo = jerry[klass]
|
117
|
+
|
118
|
+
expect(alfa).to equal bravo
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# A database connector that connects to a given uri
|
2
|
+
class Database
|
3
|
+
attr_reader :uri
|
4
|
+
|
5
|
+
def initialize(uri)
|
6
|
+
@uri = uri
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# An application that uses a database
|
11
|
+
class DbApplication
|
12
|
+
attr_reader :db
|
13
|
+
|
14
|
+
def initialize(db)
|
15
|
+
@db = db
|
16
|
+
end
|
17
|
+
end
|