rails-ioc 0.1.1 → 0.2.0

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/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