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.
@@ -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