jerry 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|