service_provider 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(service)
5
- @service = service
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("@#{@service.to_sym}", ServiceProvider.provider.get_service(@service.to_sym))
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
- service = @service
17
- this.class.send(:define_method, "#{service}=") do |value|
18
- instance_variable_set("@#{service}", value)
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
@@ -1,3 +1,3 @@
1
1
  module ServiceProvider
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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 = ["Your Name"]
5
+ gem.authors = ["Johannes Tuchscherer"]
6
6
  gem.email = ["jtuchscherer@gmail.com"]
7
- gem.description = "DI for Ruby"
8
- gem.summary = "DI for Ruby"
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
- +Requires.new(:square_service)
60
- def initialize
61
- end
55
+ it "should be possible to override the service provider used" do
56
+ class SquareSample
57
+ extend MethodDecorators
62
58
 
63
- def do_work(num)
64
- @square_service.square (num)
65
- end
59
+ +Requires.new(:square_service)
60
+ def initialize
66
61
  end
67
62
 
68
- SquareSample.new.do_work(2).should == 4
63
+ def do_work(num)
64
+ square_service.square (num)
65
+ end
69
66
  end
70
67
 
71
- it "should work when specifying the service as a string" do
72
- class SquareSample
73
- extend MethodDecorators
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
- def do_work(num)
80
- @square_service.square (num)
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
- SquareSample.new.do_work(2).should == 4
85
- end
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
- +Requires.new("minus_two_service")
92
- def initialize
93
- end
105
+ +Requires.new("square_service")
106
+ def initialize
107
+ end
94
108
 
95
- def do_work(num)
96
- @minus_two_service.minus2 (num)
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
- SquareSample.new.do_work(4).should == 2
101
- end
117
+ it "should work when not specifying the service name" do
118
+ class SquareSample
119
+ extend MethodDecorators
102
120
 
103
- it "should work for one client using multiple service" do
104
- class SquareSample
105
- extend MethodDecorators
121
+ +Requires.new("minus_two_service")
122
+ def initialize
123
+ end
106
124
 
107
- +Requires.new(:square_service)
108
- +Requires.new(:plus_three_service)
109
- def initialize
125
+ def do_work(num)
126
+ minus_two_service.minus2 (num)
127
+ end
110
128
  end
111
129
 
112
- def do_work(num)
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
- SquareSample.new.do_work(2).should == 7
118
- end
133
+ it "should work for one client using multiple service" do
134
+ class SquareSample
135
+ extend MethodDecorators
119
136
 
120
- it "should work for a client that requires a service which requires a service" do
121
- class SuperMathSample
122
- extend MethodDecorators
137
+ +Requires.new(:square_service)
138
+ +Requires.new(:plus_three_service)
139
+ def initialize
140
+ end
123
141
 
124
- +Requires.new(:super_math_service)
125
- def initialize
142
+ def do_work(num)
143
+ plus_three_service.plus3 square_service.square(num)
144
+ end
126
145
  end
127
146
 
128
- def do_work(num)
129
- @super_math_service.calculate(num)
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
- SuperMathSample.new.do_work(19).should == 364
134
- end
166
+ it "should be possible to override the service by setting it explicitly" do
167
+ class SquareOverrideSample
168
+ extend MethodDecorators
135
169
 
136
- it "should be possible to override the service by setting it explicitly" do
137
- class SquareOverrideSample
138
- extend MethodDecorators
170
+ +Requires.new(:square_service)
171
+ def initialize
172
+ end
139
173
 
140
- +Requires.new(:square_service)
141
- def initialize
174
+ def do_work(num)
175
+ square_service.square (num)
176
+ end
142
177
  end
143
178
 
144
- def do_work(num)
145
- @square_service.square (num)
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
- square_service_mock = mock('SquareService', square: "square of a number")
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
- square_override_sample = SquareOverrideSample.new
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
- +Requires.new(:square_service)
161
- def initialize
213
+ def do_work(num)
214
+ square_service.square (num)
215
+ end
162
216
  end
163
217
 
164
- def do_work(num)
165
- @square_service.square (num)
166
- end
218
+ MethodInjectionSample.new.do_work(2).should == 4
167
219
  end
168
220
 
169
- square_service_mock = mock('SquareService', square: Math::PI)
221
+ it "should memoize the local service instance and not call the service provider twice" do
222
+ class MethodInjectionSample
170
223
 
171
- service_provider_mock = mock('ServiceProvider')
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
- ServiceProvider.provider = service_provider_mock
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
- SquareSample.new.do_work(999).should == Math::PI
240
+ require_service(:square_service)
178
241
 
179
- #cleanup
180
- ServiceProvider.provider = nil
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.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - Your Name
8
+ - Johannes Tuchscherer
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-24 00:00:00.000000000Z
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: &70264872728480 !ruby/object:Gem::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: *70264872728480
24
+ version_requirements: *8959720
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70264872728060 !ruby/object:Gem::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: *70264872728060
36
- description: DI for Ruby
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.6
78
+ rubygems_version: 1.8.10
79
79
  signing_key:
80
80
  specification_version: 3
81
- summary: DI for Ruby
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