service_provider 0.0.1 → 0.0.2
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.
- data/lib/service_provider.rb +15 -0
- data/lib/service_provider/method_decorators/requires.rb +19 -6
- data/lib/service_provider/version.rb +1 -1
- data/service_provider.gemspec +4 -4
- data/spec/service_provider_spec.rb +149 -80
- metadata +11 -11
data/lib/service_provider.rb
CHANGED
@@ -56,3 +56,18 @@ end
|
|
56
56
|
|
57
57
|
Kernel.const_set(:Requires, ServiceProvider::MethodDecorators::Requires)
|
58
58
|
Kernel.const_set(:Provides, ServiceProvider::MethodDecorators::Provides)
|
59
|
+
|
60
|
+
def require_service(service_name)
|
61
|
+
self.send(:define_method, "#{service_name}=") do |value|
|
62
|
+
instance_variable_set("@#{service_name}", value)
|
63
|
+
end
|
64
|
+
self.send(:define_method, "#{service_name.to_s}") do
|
65
|
+
service = instance_variable_get("@#{service_name.to_sym}")
|
66
|
+
unless service
|
67
|
+
service = ServiceProvider.provider.get_service(service_name.to_sym)
|
68
|
+
instance_variable_set("@#{service_name.to_sym}", service)
|
69
|
+
end
|
70
|
+
service
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -1,21 +1,34 @@
|
|
1
1
|
module ServiceProvider
|
2
2
|
module MethodDecorators
|
3
3
|
class Requires < MethodDecorator
|
4
|
-
def initialize(
|
5
|
-
@
|
4
|
+
def initialize(service_name)
|
5
|
+
@service_name = service_name
|
6
6
|
end
|
7
7
|
|
8
8
|
def call(orig, this, *args, &blk)
|
9
9
|
orig.call(*args, &blk)
|
10
|
-
this.instance_variable_set("@#{@
|
10
|
+
this.instance_variable_set("@#{@service_name.to_sym}", ServiceProvider.provider.get_service(@service_name.to_sym))
|
11
11
|
add_service_setter(this)
|
12
|
+
add_service_getter(this)
|
12
13
|
this
|
13
14
|
end
|
14
15
|
|
15
16
|
def add_service_setter(this)
|
16
|
-
|
17
|
-
this.class.send(:define_method, "#{
|
18
|
-
instance_variable_set("@#{
|
17
|
+
service_name = @service_name
|
18
|
+
this.class.send(:define_method, "#{service_name}=") do |value|
|
19
|
+
instance_variable_set("@#{service_name}", value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_service_getter(this)
|
24
|
+
service_name = @service_name
|
25
|
+
this.class.send(:define_method, "#{service_name}") do
|
26
|
+
service = instance_variable_get("@#{service_name.to_sym}")
|
27
|
+
unless service
|
28
|
+
service = ServiceProvider.provider.get_service(service_name.to_sym)
|
29
|
+
instance_variable_set("@#{service_name.to_sym}", service)
|
30
|
+
end
|
31
|
+
service
|
19
32
|
end
|
20
33
|
end
|
21
34
|
end
|
data/service_provider.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
require File.expand_path('../lib/service_provider/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["
|
5
|
+
gem.authors = ["Johannes Tuchscherer"]
|
6
6
|
gem.email = ["jtuchscherer@gmail.com"]
|
7
|
-
gem.description = "
|
8
|
-
gem.summary = "
|
9
|
-
gem.homepage = ""
|
7
|
+
gem.description = "This is an easy tool to acomplish basic dependency injection in Ruby"
|
8
|
+
gem.summary = "Dependency Injection in Ruby inspired by MethodDecorators"
|
9
|
+
gem.homepage = "https://github.com/jtuchscherer/service_provider"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -51,133 +51,202 @@ class SuperMathService
|
|
51
51
|
end
|
52
52
|
|
53
53
|
describe ServiceProvider do
|
54
|
-
describe "providing a simple service" do
|
55
|
-
it "should work for one client using one service" do
|
56
|
-
class SquareSample
|
57
|
-
extend MethodDecorators
|
58
54
|
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
it "should be possible to override the service provider used" do
|
56
|
+
class SquareSample
|
57
|
+
extend MethodDecorators
|
62
58
|
|
63
|
-
|
64
|
-
|
65
|
-
end
|
59
|
+
+Requires.new(:square_service)
|
60
|
+
def initialize
|
66
61
|
end
|
67
62
|
|
68
|
-
|
63
|
+
def do_work(num)
|
64
|
+
square_service.square (num)
|
65
|
+
end
|
69
66
|
end
|
70
67
|
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
square_service_mock = mock('SquareService', square: Math::PI)
|
69
|
+
|
70
|
+
service_provider_mock = mock('ServiceProvider')
|
71
|
+
service_provider_mock.stub(:add_service)
|
72
|
+
service_provider_mock.stub(:get_service).with(:square_service).and_return(square_service_mock)
|
73
|
+
|
74
|
+
ServiceProvider.provider = service_provider_mock
|
75
|
+
|
76
|
+
SquareSample.new.do_work(999).should == Math::PI
|
77
|
+
|
78
|
+
#cleanup
|
79
|
+
ServiceProvider.provider = nil
|
80
|
+
end
|
74
81
|
|
75
|
-
+Requires.new("square_service")
|
76
|
-
def initialize
|
77
|
-
end
|
78
82
|
|
79
|
-
|
80
|
-
|
83
|
+
context "constructor based injection" do
|
84
|
+
describe "providing a simple service" do
|
85
|
+
it "should work for one client using one service" do
|
86
|
+
class SquareSample
|
87
|
+
extend MethodDecorators
|
88
|
+
|
89
|
+
+Requires.new(:square_service)
|
90
|
+
def initialize
|
91
|
+
end
|
92
|
+
|
93
|
+
def do_work(num)
|
94
|
+
square_service.square (num)
|
95
|
+
end
|
81
96
|
end
|
97
|
+
|
98
|
+
SquareSample.new.do_work(2).should == 4
|
82
99
|
end
|
83
100
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
it "should work when not specifying the service name" do
|
88
|
-
class SquareSample
|
89
|
-
extend MethodDecorators
|
101
|
+
it "should work when specifying the service as a string" do
|
102
|
+
class SquareSample
|
103
|
+
extend MethodDecorators
|
90
104
|
|
91
|
-
|
92
|
-
|
93
|
-
|
105
|
+
+Requires.new("square_service")
|
106
|
+
def initialize
|
107
|
+
end
|
94
108
|
|
95
|
-
|
96
|
-
|
109
|
+
def do_work(num)
|
110
|
+
square_service.square (num)
|
111
|
+
end
|
97
112
|
end
|
113
|
+
|
114
|
+
SquareSample.new.do_work(2).should == 4
|
98
115
|
end
|
99
116
|
|
100
|
-
|
101
|
-
|
117
|
+
it "should work when not specifying the service name" do
|
118
|
+
class SquareSample
|
119
|
+
extend MethodDecorators
|
102
120
|
|
103
|
-
|
104
|
-
|
105
|
-
|
121
|
+
+Requires.new("minus_two_service")
|
122
|
+
def initialize
|
123
|
+
end
|
106
124
|
|
107
|
-
|
108
|
-
|
109
|
-
|
125
|
+
def do_work(num)
|
126
|
+
minus_two_service.minus2 (num)
|
127
|
+
end
|
110
128
|
end
|
111
129
|
|
112
|
-
|
113
|
-
@plus_three_service.plus3 @square_service.square(num)
|
114
|
-
end
|
130
|
+
SquareSample.new.do_work(4).should == 2
|
115
131
|
end
|
116
132
|
|
117
|
-
|
118
|
-
|
133
|
+
it "should work for one client using multiple service" do
|
134
|
+
class SquareSample
|
135
|
+
extend MethodDecorators
|
119
136
|
|
120
|
-
|
121
|
-
|
122
|
-
|
137
|
+
+Requires.new(:square_service)
|
138
|
+
+Requires.new(:plus_three_service)
|
139
|
+
def initialize
|
140
|
+
end
|
123
141
|
|
124
|
-
|
125
|
-
|
142
|
+
def do_work(num)
|
143
|
+
plus_three_service.plus3 square_service.square(num)
|
144
|
+
end
|
126
145
|
end
|
127
146
|
|
128
|
-
|
129
|
-
|
147
|
+
SquareSample.new.do_work(2).should == 7
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should work for a client that requires a service which requires a service" do
|
151
|
+
class SuperMathSample
|
152
|
+
extend MethodDecorators
|
153
|
+
|
154
|
+
+Requires.new(:super_math_service)
|
155
|
+
def initialize
|
156
|
+
end
|
157
|
+
|
158
|
+
def do_work(num)
|
159
|
+
super_math_service.calculate(num)
|
160
|
+
end
|
130
161
|
end
|
162
|
+
|
163
|
+
SuperMathSample.new.do_work(19).should == 364
|
131
164
|
end
|
132
165
|
|
133
|
-
|
134
|
-
|
166
|
+
it "should be possible to override the service by setting it explicitly" do
|
167
|
+
class SquareOverrideSample
|
168
|
+
extend MethodDecorators
|
135
169
|
|
136
|
-
|
137
|
-
|
138
|
-
|
170
|
+
+Requires.new(:square_service)
|
171
|
+
def initialize
|
172
|
+
end
|
139
173
|
|
140
|
-
|
141
|
-
|
174
|
+
def do_work(num)
|
175
|
+
square_service.square (num)
|
176
|
+
end
|
142
177
|
end
|
143
178
|
|
144
|
-
|
145
|
-
|
179
|
+
square_service_mock = mock('SquareService', square: "square of a number")
|
180
|
+
|
181
|
+
square_override_sample = SquareOverrideSample.new
|
182
|
+
square_override_sample.square_service = square_service_mock
|
183
|
+
square_override_sample.do_work(2).should == "square of a number"
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should memoize the local service instance and not call the service provider twice" do
|
187
|
+
class ServiceSample
|
188
|
+
extend MethodDecorators
|
189
|
+
|
190
|
+
+Requires.new(:square_service)
|
191
|
+
def initialize
|
192
|
+
end
|
193
|
+
|
194
|
+
def do_work(num)
|
195
|
+
square_service.square (num)
|
196
|
+
end
|
146
197
|
end
|
198
|
+
|
199
|
+
ServiceProvider::Provider::Automatic.should_receive(:get_service).once.with(:square_service).and_return(SquareService.new)
|
200
|
+
service_sample = ServiceSample.new
|
201
|
+
service_sample.do_work(2)
|
202
|
+
service_sample.do_work(2)
|
147
203
|
end
|
204
|
+
end
|
148
205
|
|
149
|
-
|
206
|
+
context "meta-programming based injection" do
|
207
|
+
it "should work with method based injection instead of instance based injection" do
|
208
|
+
class MethodInjectionSample
|
150
209
|
|
151
|
-
|
152
|
-
square_override_sample.square_service = square_service_mock
|
153
|
-
square_override_sample.do_work(2).should == "square of a number"
|
154
|
-
end
|
210
|
+
require_service(:square_service)
|
155
211
|
|
156
|
-
it "should be possible to override the service provider used" do
|
157
|
-
class SquareSample
|
158
|
-
extend MethodDecorators
|
159
212
|
|
160
|
-
|
161
|
-
|
213
|
+
def do_work(num)
|
214
|
+
square_service.square (num)
|
215
|
+
end
|
162
216
|
end
|
163
217
|
|
164
|
-
|
165
|
-
@square_service.square (num)
|
166
|
-
end
|
218
|
+
MethodInjectionSample.new.do_work(2).should == 4
|
167
219
|
end
|
168
220
|
|
169
|
-
|
221
|
+
it "should memoize the local service instance and not call the service provider twice" do
|
222
|
+
class MethodInjectionSample
|
170
223
|
|
171
|
-
|
172
|
-
service_provider_mock.stub(:add_service)
|
173
|
-
service_provider_mock.stub(:get_service).with(:square_service).and_return(square_service_mock)
|
224
|
+
require_service(:square_service)
|
174
225
|
|
175
|
-
|
226
|
+
def do_work(num)
|
227
|
+
square_service.square (num)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
ServiceProvider::Provider::Automatic.should_receive(:get_service).once.with(:square_service).and_return(SquareService.new)
|
232
|
+
sample = MethodInjectionSample.new
|
233
|
+
sample.do_work(2)
|
234
|
+
sample.do_work(2)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should work if object is constructed with allocate instead of new" do
|
238
|
+
class MethodInjectionSample
|
176
239
|
|
177
|
-
|
240
|
+
require_service(:square_service)
|
178
241
|
|
179
|
-
|
180
|
-
|
242
|
+
def do_work(num)
|
243
|
+
square_service.square (num)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
ServiceProvider::Provider::Automatic.should_receive(:get_service).once.with(:square_service).and_return(SquareService.new)
|
248
|
+
MethodInjectionSample.allocate.do_work(2).should == 4
|
249
|
+
end
|
181
250
|
end
|
182
251
|
end
|
183
252
|
end
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: service_provider
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
-
-
|
8
|
+
- Johannes Tuchscherer
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: method_decorators
|
16
|
-
requirement: &
|
16
|
+
requirement: &8959720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *8959720
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &8959300 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,8 +32,8 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
description:
|
35
|
+
version_requirements: *8959300
|
36
|
+
description: This is an easy tool to acomplish basic dependency injection in Ruby
|
37
37
|
email:
|
38
38
|
- jtuchscherer@gmail.com
|
39
39
|
executables: []
|
@@ -55,7 +55,7 @@ files:
|
|
55
55
|
- service_provider.gemspec
|
56
56
|
- spec/service_provider_spec.rb
|
57
57
|
- spec/spec_helper.rb
|
58
|
-
homepage:
|
58
|
+
homepage: https://github.com/jtuchscherer/service_provider
|
59
59
|
licenses: []
|
60
60
|
post_install_message:
|
61
61
|
rdoc_options: []
|
@@ -75,10 +75,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
version: '0'
|
76
76
|
requirements: []
|
77
77
|
rubyforge_project:
|
78
|
-
rubygems_version: 1.8.
|
78
|
+
rubygems_version: 1.8.10
|
79
79
|
signing_key:
|
80
80
|
specification_version: 3
|
81
|
-
summary:
|
81
|
+
summary: Dependency Injection in Ruby inspired by MethodDecorators
|
82
82
|
test_files:
|
83
83
|
- spec/service_provider_spec.rb
|
84
84
|
- spec/spec_helper.rb
|