rails-ioc 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -115,7 +115,7 @@ RailsIOC attempts to make these problems less painful for applications with comp
115
115
  RailsIOC::Dependencies.define do
116
116
  prototype :payment_gateway, RealPaymentGateway
117
117
  prototype :credit_card_validator, RealCardValidator
118
-
118
+
119
119
  controller PaymentsController, {
120
120
  gateway: ref(:payment_gateway)
121
121
  credit_card_validator: ref(:credit_card_validator)
@@ -126,18 +126,14 @@ RailsIOC attempts to make these problems less painful for applications with comp
126
126
  RailsIOC::Dependencies.define do
127
127
  inherit_environment(:production)
128
128
 
129
- controller PaymentsController, {
130
- gateway: prototype(RealPaymentGateway, use_testing_url: true)
131
- }
129
+ prototype :payment_gateway, RealPaymentGateway, {use_testing_url: true}
132
130
  end
133
131
 
134
132
  # config/dependencies/development.rb:
135
133
  RailsIOC::Dependencies.define do
136
134
  inherit_environment(:production)
137
135
 
138
- controller PaymentsController, {
139
- gateway: singleton(BogusPaymentGateway),
140
- credit_card_validator: singleton(BogusCardValidator)
141
- }
136
+ singleton :payment_gateway, BogusPaymentGateway),
137
+ singleton :credit_card_validator, BogusCardValidator
142
138
  end
143
139
  ```
data/lib/rails-ioc.rb CHANGED
@@ -3,6 +3,9 @@ require "rails-ioc/errors"
3
3
  require "rails-ioc/dependencies"
4
4
  require "rails-ioc/dependency_constructor"
5
5
  require "rails-ioc/dependency_injector"
6
+ require "rails-ioc/singleton"
7
+ require "rails-ioc/prototype"
8
+ require "rails-ioc/reference"
6
9
 
7
10
  raise RailsIOC::NoRailsError.new(:Rails) unless defined?(Rails)
8
11
  raise RailsIOC::NoRailsError.new(:ActionController) unless defined?(ActionController)
@@ -0,0 +1,18 @@
1
+ module RailsIOC
2
+ class Reference
3
+ def initialize(name, defined_dependencies)
4
+ @name = name
5
+ @defined_dependencies = defined_dependencies
6
+ end
7
+
8
+ def build
9
+ dependency = @defined_dependencies[@name]
10
+ raise MissingReferenceError.new(@name) if dependency.nil?
11
+ if dependency.respond_to?(:build)
12
+ dependency.build
13
+ else
14
+ dependency
15
+ end
16
+ end
17
+ end
18
+ end
@@ -29,24 +29,23 @@ module RailsIOC
29
29
  end
30
30
 
31
31
  def self.singleton(*args)
32
- store_dependency(args) do |klass, constructor_args|
33
- if klass.instance_of?(Class)
34
- DependencyConstructor.new(klass, caller).construct(constructor_args)
32
+ store_dependency(args) do |klass_or_value, constructor_args|
33
+ if klass_or_value.instance_of?(Class)
34
+ RailsIOC::Singleton.new(klass_or_value, constructor_args)
35
35
  else
36
- klass
36
+ klass_or_value
37
37
  end
38
38
  end
39
39
  end
40
40
 
41
41
  def self.prototype(*args)
42
42
  store_dependency(args) do |klass, constructor_args|
43
- definition_backtrace = caller
44
- -> { DependencyConstructor.new(klass, definition_backtrace).construct(constructor_args) }
43
+ RailsIOC::Prototype.new(klass, constructor_args)
45
44
  end
46
45
  end
47
46
 
48
47
  def self.ref(name)
49
- @dependencies[name] || raise(MissingReferenceError.new(name))
48
+ RailsIOC::Reference.new(name, @dependencies)
50
49
  end
51
50
 
52
51
  def self.controllers
@@ -7,11 +7,21 @@ module RailsIOC
7
7
 
8
8
  def construct(dependencies)
9
9
  begin
10
- @klass.new(*dependencies.map { |x| x.is_a?(Proc) ? x.call : x })
10
+ @klass.new(*dependencies.map { |dependency| call_lazy_initializers(dependency) })
11
11
  rescue ArgumentError => e
12
12
  e.set_backtrace(@definition_backtrace)
13
13
  raise e
14
14
  end
15
15
  end
16
+
17
+ private
18
+
19
+ def call_lazy_initializers(dependency)
20
+ if dependency.respond_to?(:build)
21
+ call_lazy_initializers(dependency.build)
22
+ else
23
+ dependency
24
+ end
25
+ end
16
26
  end
17
27
  end
@@ -5,11 +5,20 @@ module RailsIOC
5
5
  end
6
6
 
7
7
  def inject(dependencies)
8
- dependencies.each do |field, value|
9
- value = value.call if value.is_a?(Proc)
10
- @target.instance_variable_set("@#{field}", value)
8
+ dependencies.each do |field, dependency|
9
+ @target.instance_variable_set("@#{field}", call_lazy_initializers(dependency))
11
10
  end
12
11
  @target
13
12
  end
13
+
14
+ private
15
+
16
+ def call_lazy_initializers(dependency)
17
+ if dependency.respond_to?(:build)
18
+ call_lazy_initializers(dependency.build)
19
+ else
20
+ dependency
21
+ end
22
+ end
14
23
  end
15
24
  end
@@ -0,0 +1,13 @@
1
+ module RailsIOC
2
+ class Prototype
3
+ def initialize(klass, constructor_args)
4
+ @klass = klass
5
+ @constructor_args = constructor_args
6
+ @defining_stacktrace = caller
7
+ end
8
+
9
+ def build
10
+ DependencyConstructor.new(@klass, @defining_stacktrace).construct(@constructor_args)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RailsIOC
2
+ class Singleton
3
+ def initialize(klass, constructor_args)
4
+ @klass = klass
5
+ @constructor_args = constructor_args
6
+ @defining_stacktrace = caller
7
+ end
8
+
9
+ def build
10
+ @instance ||= DependencyConstructor.new(@klass, @defining_stacktrace).construct(@constructor_args)
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module RailsIOC
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -2,4 +2,9 @@ RailsIOC::Dependencies.define do
2
2
  singleton :env_string, "Production"
3
3
  singleton :foo_string, "Foo"
4
4
  singleton :production_only_string, "This comes from production.rb"
5
+
6
+ controller ExtendedController, {
7
+ env_string: ref(:env_string),
8
+ production_only_string: ref(:production_only_string)
9
+ }
5
10
  end
@@ -19,20 +19,22 @@ describe RailsIOC::Dependencies do
19
19
  singleton :first_node, TestListNode, ref(:second_node)
20
20
  end
21
21
 
22
- first_node = RailsIOC::Dependencies.ref(:first_node)
22
+ ref = RailsIOC::Dependencies.ref(:first_node)
23
+ first_node = ref.build
23
24
  first_node.should be_a TestListNode
24
- first_node.should === RailsIOC::Dependencies.ref(:first_node)
25
- first_node.next_node.should === RailsIOC::Dependencies.ref(:second_node)
25
+ first_node.should === ref.build
26
+ first_node.next_node.should === RailsIOC::Dependencies.ref(:second_node).build
26
27
  end
27
28
 
28
29
  it "creates unreferenced singletons from a class and constructor args" do
29
30
  RailsIOC::Dependencies.define do
30
- singleton :first_node, TestListNode, singleton(TestListNode)
31
+ prototype :first_node, TestListNode, singleton(TestListNode)
31
32
  end
32
33
 
33
- first_node = RailsIOC::Dependencies.ref(:first_node)
34
- first_node.should be_a(TestListNode)
34
+ ref = RailsIOC::Dependencies.ref(:first_node)
35
+ first_node = ref.build
35
36
  first_node.next_node.should be_a TestListNode
37
+ first_node.next_node.should === ref.build.next_node
36
38
  end
37
39
 
38
40
  it "does not require a class for simple types" do
@@ -40,15 +42,17 @@ describe RailsIOC::Dependencies do
40
42
  singleton :a_number, 12345
41
43
  end
42
44
 
43
- RailsIOC::Dependencies.ref(:a_number).should == 12345
45
+ RailsIOC::Dependencies.ref(:a_number).build.should == 12345
44
46
  end
45
47
 
46
48
  it "raises an error containing information about original definition if the wrong number of constructor args are defined" do
47
- defining_line = __LINE__ + 3
49
+ defining_line = __LINE__ + 2
50
+ RailsIOC::Dependencies.define do
51
+ singleton :a_string, String, "Too", "many", "args"
52
+ end
53
+
48
54
  -> {
49
- RailsIOC::Dependencies.define do
50
- singleton :a_string, String, "Too", "many", "args"
51
- end
55
+ RailsIOC::Dependencies.ref(:a_string).build
52
56
  }.should raise_error(ArgumentError) { |e|
53
57
  e.backtrace.find { |l| l =~ /dependencies_spec.rb:#{defining_line}/ }.should_not be_nil
54
58
  }
@@ -63,13 +67,11 @@ describe RailsIOC::Dependencies do
63
67
  end
64
68
 
65
69
  ref = RailsIOC::Dependencies.ref(:first_node)
66
- ref.should be_a Proc
67
- first_node = ref.call
70
+ first_node = ref.build
68
71
  first_node.should be_a TestListNode
69
- first_node.should_not === ref.call
70
-
71
72
  first_node.next_node.should be_a TestListNode
72
- first_node.next_node.should_not === RailsIOC::Dependencies.ref(:second_node).call
73
+
74
+ first_node.should_not === ref.build
73
75
  end
74
76
 
75
77
  it "creates unreferenced prototypes from a class and constructor args" do
@@ -78,10 +80,11 @@ describe RailsIOC::Dependencies do
78
80
  end
79
81
 
80
82
  ref = RailsIOC::Dependencies.ref(:first_node)
81
- ref.should be_a Proc
82
- first_node = ref.call
83
- first_node.should be_a(TestListNode)
83
+ first_node = ref.build
84
+ first_node.should be_a TestListNode
84
85
  first_node.next_node.should be_a TestListNode
86
+
87
+ first_node.next_node.should_not === ref.build.next_node
85
88
  end
86
89
 
87
90
  it "raises an error containing information about original definition if the wrong number of constructor args are defined" do
@@ -89,13 +92,22 @@ describe RailsIOC::Dependencies do
89
92
  RailsIOC::Dependencies.define do
90
93
  prototype :a_string, String, "Too", "many", "args"
91
94
  end
92
-
93
- -> { RailsIOC::Dependencies.ref(:a_string).call }.should raise_error(ArgumentError) { |e|
95
+ -> { RailsIOC::Dependencies.ref(:a_string).build }.should raise_error(ArgumentError) { |e|
94
96
  e.backtrace.find { |l| l =~ /dependencies_spec.rb:#{defining_line}/ }.should_not be_nil
95
97
  }
96
98
  end
97
99
  end
98
100
 
101
+ describe "lazy initialization" do
102
+ it "allows dependencies to be referenced before they are defined" do
103
+ RailsIOC::Dependencies.define do
104
+ singleton :first_node, TestListNode, ref(:second_node)
105
+ singleton :second_node, TestListNode
106
+ end
107
+ RailsIOC::Dependencies.ref(:first_node).build.next_node.should === RailsIOC::Dependencies.ref(:second_node).build
108
+ end
109
+ end
110
+
99
111
  describe "controllers" do
100
112
  it "stores controller dependencies for later injection by Rails' before_filter" do
101
113
  RailsIOC::Dependencies.define do
@@ -111,7 +123,7 @@ describe RailsIOC::Dependencies do
111
123
  dependencies = RailsIOC::Dependencies.controllers[TestController]
112
124
  RailsIOC::DependencyInjector.new(controller).inject(dependencies)
113
125
 
114
- controller.foo.should === RailsIOC::Dependencies.ref(:first_node)
126
+ controller.foo.should === RailsIOC::Dependencies.ref(:first_node).build
115
127
  controller.bar.should == "The Sheep Says Bar"
116
128
  end
117
129
 
@@ -140,10 +152,10 @@ describe RailsIOC::Dependencies do
140
152
  Rails.application.config.cache_classes = false
141
153
 
142
154
  RailsIOC::Dependencies.load!
143
- RailsIOC::Dependencies.ref(:counter).should == 1
155
+ RailsIOC::Dependencies.ref(:counter).build.should == 1
144
156
 
145
157
  RailsIOC::Dependencies.load!
146
- RailsIOC::Dependencies.ref(:counter).should == 2
158
+ RailsIOC::Dependencies.ref(:counter).build.should == 2
147
159
  end
148
160
 
149
161
  it "does not reload the file if cache_classes is true" do
@@ -151,26 +163,36 @@ describe RailsIOC::Dependencies do
151
163
  Rails.application.config.cache_classes = true
152
164
 
153
165
  RailsIOC::Dependencies.load!
154
- RailsIOC::Dependencies.ref(:counter).should == 1
166
+ RailsIOC::Dependencies.ref(:counter).build.should == 1
155
167
 
156
168
  RailsIOC::Dependencies.load!
157
- RailsIOC::Dependencies.ref(:counter).should == 1
169
+ RailsIOC::Dependencies.ref(:counter).build.should == 1
158
170
  end
159
171
  end
160
172
 
161
173
  describe "inheriting environments" do
162
174
  it "loads the corresponding dependencies file" do
163
175
  RailsIOC::Dependencies.inherit_environment("production")
164
- RailsIOC::Dependencies.ref(:env_string).should == "Production"
165
- RailsIOC::Dependencies.ref(:foo_string).should == "Foo"
166
- RailsIOC::Dependencies.ref(:production_only_string).should == "This comes from production.rb"
167
- -> { RailsIOC::Dependencies.ref(:test_only_string) }.should raise_error RailsIOC::MissingReferenceError
176
+ RailsIOC::Dependencies.ref(:env_string).build.should == "Production"
177
+ RailsIOC::Dependencies.ref(:foo_string).build.should == "Foo"
178
+ RailsIOC::Dependencies.ref(:production_only_string).build.should == "This comes from production.rb"
179
+ -> { RailsIOC::Dependencies.ref(:test_only_string).build }.should raise_error RailsIOC::MissingReferenceError
180
+
181
+ RailsIOC::Dependencies.inherit_environment("test")
182
+ RailsIOC::Dependencies.ref(:env_string).build.should == "Test"
183
+ RailsIOC::Dependencies.ref(:foo_string).build.should == "Foo"
184
+ RailsIOC::Dependencies.ref(:production_only_string).build.should == "This comes from production.rb"
185
+ RailsIOC::Dependencies.ref(:test_only_string).build.should == "This comes from test.rb"
186
+ end
187
+
188
+ it "allows controller dependencies which use references to be overridden" do
189
+ RailsIOC::Dependencies.inherit_environment("production")
190
+ RailsIOC::Dependencies.controllers[ExtendedController][:env_string].build.should == "Production"
191
+ RailsIOC::Dependencies.controllers[ExtendedController][:production_only_string].build.should == "This comes from production.rb"
168
192
 
169
193
  RailsIOC::Dependencies.inherit_environment("test")
170
- RailsIOC::Dependencies.ref(:env_string).should == "Test"
171
- RailsIOC::Dependencies.ref(:foo_string).should == "Foo"
172
- RailsIOC::Dependencies.ref(:production_only_string).should == "This comes from production.rb"
173
- RailsIOC::Dependencies.ref(:test_only_string).should == "This comes from test.rb"
194
+ RailsIOC::Dependencies.controllers[ExtendedController][:production_only_string].build.should == "This comes from production.rb"
195
+ RailsIOC::Dependencies.controllers[ExtendedController][:env_string].build.should == "Test"
174
196
  end
175
197
  end
176
198
  end
@@ -14,10 +14,10 @@ describe RailsIOC::DependencyConstructor do
14
14
  instance.bar.should == :abc
15
15
  end
16
16
 
17
- it "calls any procs which are provided in constructor args" do
18
- returns_7 = -> { 3 + 4 }
17
+ it "builds any dependencies which are provided in constructor args" do
18
+ returns_7 = RailsIOC::Prototype.new(String, ["7"])
19
19
  instance = RailsIOC::DependencyConstructor.new(ConstructorTestClass, []).construct([returns_7, :abc])
20
- instance.foo.should == 7
20
+ instance.foo.should == "7"
21
21
  instance.bar.should == :abc
22
22
  end
23
23
 
@@ -12,9 +12,9 @@ describe RailsIOC::DependencyInjector do
12
12
  end
13
13
 
14
14
  it "calls any procs which are provided in constructor args" do
15
- returns_7 = -> { 3 + 4 }
15
+ returns_7 = RailsIOC::Prototype.new(String, ["7"])
16
16
  instance = RailsIOC::DependencyInjector.new(InjectorTestClass.new).inject(foo: returns_7, bar: :abc)
17
- instance.foo.should == 7
17
+ instance.foo.should == "7"
18
18
  instance.bar.should == :abc
19
19
  end
20
20
  end
@@ -0,0 +1,16 @@
1
+ require File.expand_path("../../spec_helper.rb", __FILE__)
2
+
3
+ describe RailsIOC::Prototype do
4
+ class TestClass
5
+ attr_reader :text
6
+ def initialize(text)
7
+ @text = text
8
+ end
9
+ end
10
+
11
+ it "builds a new instance every time build is called" do
12
+ prototype = RailsIOC::Prototype.new(TestClass, ["I am a prototype"])
13
+ prototype.build.text.should == "I am a prototype"
14
+ prototype.build.should_not === prototype.build
15
+ end
16
+ end
@@ -11,15 +11,15 @@ describe RailsIOC::RSpecExtension do
11
11
  end
12
12
 
13
13
  it "resets before this test" do
14
- -> { RailsIOC::Dependencies.ref(:defined?) }.should raise_error RailsIOC::MissingReferenceError
14
+ -> { RailsIOC::Dependencies.ref(:defined?).build }.should raise_error RailsIOC::MissingReferenceError
15
15
  end
16
16
 
17
17
  it "also resets before this test" do
18
- -> { RailsIOC::Dependencies.ref(:defined?) }.should raise_error RailsIOC::MissingReferenceError
18
+ -> { RailsIOC::Dependencies.ref(:defined?).build }.should raise_error RailsIOC::MissingReferenceError
19
19
  end
20
20
  end
21
21
 
22
- it "provides a shorthand way to define and expose controller dependencies" do
22
+ it "provides a shorthand way to define and expose controller depend3encies" do
23
23
  Rails.application.config.cache_classes = true
24
24
  RailsIOC::Dependencies.instance_variable_set :@loaded, true
25
25
 
@@ -0,0 +1,16 @@
1
+ require File.expand_path("../../spec_helper.rb", __FILE__)
2
+
3
+ describe RailsIOC::Singleton do
4
+ class TestClass
5
+ attr_reader :text
6
+ def initialize(text)
7
+ @text = text
8
+ end
9
+ end
10
+
11
+ it "always returns the same instance once build has been called" do
12
+ singleton = RailsIOC::Singleton.new(TestClass, ["I am a singleton"])
13
+ singleton.build.text.should == "I am a singleton"
14
+ singleton.build.should === singleton.build
15
+ end
16
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-ioc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-29 00:00:00.000000000Z
12
+ date: 2011-09-06 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70311518245340 !ruby/object:Gem::Requirement
16
+ requirement: &70174147087040 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70311518245340
24
+ version_requirements: *70174147087040
25
25
  description: Simple dependency injection for Rails.
26
26
  email:
27
27
  - rick@rickgrundy.com
@@ -34,12 +34,15 @@ files:
34
34
  - README.markdown
35
35
  - Rakefile
36
36
  - lib/rails-ioc.rb
37
+ - lib/rails-ioc/Reference.rb
37
38
  - lib/rails-ioc/controller_extension.rb
38
39
  - lib/rails-ioc/dependencies.rb
39
40
  - lib/rails-ioc/dependency_constructor.rb
40
41
  - lib/rails-ioc/dependency_injector.rb
41
42
  - lib/rails-ioc/errors.rb
43
+ - lib/rails-ioc/prototype.rb
42
44
  - lib/rails-ioc/rspec_extension.rb
45
+ - lib/rails-ioc/singleton.rb
43
46
  - lib/rails-ioc/version.rb
44
47
  - rails-ioc.gemspec
45
48
  - spec/fixtures/config/dependencies/incrementing_test.rb
@@ -49,7 +52,9 @@ files:
49
52
  - spec/rails-ioc/dependencies_spec.rb
50
53
  - spec/rails-ioc/dependency_constructor_spec.rb
51
54
  - spec/rails-ioc/dependency_injector_spec.rb
55
+ - spec/rails-ioc/prototype_spec.rb
52
56
  - spec/rails-ioc/rspec_extension_spec.rb
57
+ - spec/rails-ioc/singleton_spec.rb
53
58
  - spec/spec_helper.rb
54
59
  - spec/spec_helper_spec_spec_spec_spec.rb
55
60
  homepage: http://www.github.com/rickgrundy/rails-ioc
@@ -84,6 +89,8 @@ test_files:
84
89
  - spec/rails-ioc/dependencies_spec.rb
85
90
  - spec/rails-ioc/dependency_constructor_spec.rb
86
91
  - spec/rails-ioc/dependency_injector_spec.rb
92
+ - spec/rails-ioc/prototype_spec.rb
87
93
  - spec/rails-ioc/rspec_extension_spec.rb
94
+ - spec/rails-ioc/singleton_spec.rb
88
95
  - spec/spec_helper.rb
89
96
  - spec/spec_helper_spec_spec_spec_spec.rb