conject 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,9 +23,10 @@ module Conject
23
23
  end
24
24
 
25
25
  def self.default_object_factory
26
+ class_finder = ClassFinder.new
26
27
  @default_object_factory ||= ObjectFactory.new(
27
- :class_finder => ClassFinder.new,
28
- :dependency_resolver => DependencyResolver.new
28
+ :class_finder => class_finder,
29
+ :dependency_resolver => DependencyResolver.new(:class_finder => class_finder)
29
30
  )
30
31
  end
31
32
 
@@ -96,7 +96,6 @@ class Class
96
96
  # * var args (eg, def initialize(*args)). args[0] will be the component map. NO OTHER ARGS WILL BE PASSED. See Footnote a)
97
97
  #
98
98
  klass.meta_def :new do |component_map|
99
-
100
99
  # We only want to do the following one time, but we've waited until now
101
100
  # in order to make sure our metaprogramming didn't get ahead of the user's
102
101
  # own definition of initialize:
@@ -7,6 +7,14 @@ module Conject
7
7
  dig_for_class Object, cname_components
8
8
  end
9
9
 
10
+ def get_module_path(klass)
11
+ cname = klass.name
12
+ return nil unless cname =~ /::/
13
+ cname_components = cname.split("::")
14
+ cname_components.pop
15
+ cname_components.join("::").underscore
16
+ end
17
+
10
18
  private
11
19
 
12
20
  def dig_for_class(within, steps)
@@ -1,5 +1,6 @@
1
1
  module Conject
2
2
  class DependencyResolver
3
+ construct_with :class_finder
3
4
  #
4
5
  # Given a Class, generate a map of dependencies needed to construct a new
5
6
  # instance of that class. Dependencies are looked up (and/or instantiated, as
@@ -10,9 +11,29 @@ module Conject
10
11
  #
11
12
  def resolve_for_class(klass, object_context)
12
13
  klass.object_definition.component_names.inject({}) do |obj_map, name|
13
- obj_map[name] = object_context.get(name)
14
+ obj_map[name] = search_for(klass, object_context, name)
14
15
  obj_map
15
16
  end
16
17
  end
18
+
19
+
20
+ private
21
+
22
+ def search_for(klass, object_context, name)
23
+ object = nil
24
+ # If the asking class has a module namespace, first try looking relative
25
+ # to that module:
26
+ if module_path = class_finder.get_module_path(klass)
27
+ qualified_name = "#{module_path}/#{name}"
28
+ begin
29
+ object = object_context.get(qualified_name)
30
+ rescue
31
+ # This means there's no relative object, which might be ok.
32
+ # Fallback is to look for the requested object in the global namespace.
33
+ end
34
+ end
35
+ # Search for the object by the specified name
36
+ object ||= object_context.get(name)
37
+ end
17
38
  end
18
39
  end
@@ -1,3 +1,3 @@
1
1
  module Conject
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -0,0 +1,78 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+
4
+ describe "module scoping" do
5
+ subject { new_object_context }
6
+
7
+ describe "using fully qualified object name" do
8
+ before do
9
+ append_test_load_path "namespace"
10
+ require 'chart/model'
11
+ require 'chart/presenter'
12
+ require 'chart/view'
13
+ end
14
+
15
+ after do
16
+ restore_load_path
17
+ end
18
+
19
+ it "constructs objects with module-scoped classes" do
20
+ obj = subject.get('chart/model')
21
+ obj.should_not be_nil
22
+ obj.class.should == Chart::Model
23
+ end
24
+
25
+ it "supports symbols as keys" do
26
+ obj = subject.get(:'chart/model')
27
+ obj.should_not be_nil
28
+ obj.class.should == Chart::Model
29
+ end
30
+
31
+ it "lets objects depend on module-namespaced components" do
32
+ obj = subject.get('chart/presenter')
33
+ obj.should_not be_nil
34
+ obj.class.should == Chart::Presenter
35
+
36
+ model = obj.send(:model)
37
+ model.should be
38
+ model.class.should == Chart::Model
39
+
40
+ view = obj.send(:view)
41
+ view.should be
42
+ view.class.should == Chart::View
43
+ end
44
+ end
45
+
46
+ describe "using module-relative object names" do
47
+ before do
48
+ append_test_load_path "namespace"
49
+ require 'deeply_nested/ez_chart/model'
50
+ require 'deeply_nested/ez_chart/presenter'
51
+ require 'deeply_nested/ez_chart/view'
52
+ end
53
+
54
+ after do
55
+ restore_load_path
56
+ end
57
+
58
+ it "lets objects depend on module-namespaced components" do
59
+ obj = subject.get('deeply_nested/ez_chart/presenter')
60
+ obj.should_not be_nil
61
+ obj.class.should == DeeplyNested::EzChart::Presenter
62
+
63
+ model = obj.send(:model)
64
+ model.should be
65
+ model.class.should == DeeplyNested::EzChart::Model
66
+
67
+ view = obj.send(:view)
68
+ view.should be
69
+ view.class.should == DeeplyNested::EzChart::View
70
+
71
+ subject.directly_has?("deeply_nested/ez_chart/model").should be_true
72
+ subject.directly_has?("deeply_nested/ez_chart/view").should be_true
73
+ end
74
+ end
75
+
76
+
77
+ end
78
+
@@ -1,59 +1,77 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
2
 
3
3
  describe Conject::ClassFinder do
4
- before do
5
- append_test_load_path "simple_stuff"
6
- append_test_load_path "namespace"
7
- require 'some_random_class'
8
- require 'chart/model'
9
- require 'somewhere/deep/inside/the/earth'
10
- end
4
+ describe "#find_class" do
5
+ before do
6
+ append_test_load_path "simple_stuff"
7
+ append_test_load_path "namespace"
8
+ require 'some_random_class'
9
+ require 'chart/model'
10
+ require 'somewhere/deep/inside/the/earth'
11
+ end
11
12
 
12
- after do
13
- restore_load_path
14
- end
13
+ after do
14
+ restore_load_path
15
+ end
15
16
 
16
- it "returns the class implied by the given name" do
17
- c = subject.find_class('some_random_class')
18
- c.should_not be_nil
19
- c.should == SomeRandomClass
20
- end
17
+ it "returns the class implied by the given name" do
18
+ c = subject.find_class('some_random_class')
19
+ c.should_not be_nil
20
+ c.should == SomeRandomClass
21
+ end
21
22
 
22
- it "can accept symbols for object names" do
23
- c = subject.find_class(:some_random_class)
24
- c.should_not be_nil
25
- c.should == SomeRandomClass
26
- end
23
+ it "can accept symbols for object names" do
24
+ c = subject.find_class(:some_random_class)
25
+ c.should_not be_nil
26
+ c.should == SomeRandomClass
27
+ end
27
28
 
28
- it "raises an error if the name doesn't imply a regular class in the current runtime" do
29
- lambda do
30
- subject.find_class('something_undefined')
31
- end.should raise_error(/could not find class.*SomethingUndefined/i)
32
- end
29
+ it "raises an error if the name doesn't imply a regular class in the current runtime" do
30
+ lambda do
31
+ subject.find_class('something_undefined')
32
+ end.should raise_error(/could not find class.*SomethingUndefined/i)
33
+ end
34
+
35
+ it "raises an error for nil input" do
36
+ lambda do
37
+ subject.find_class('something_undefined')
38
+ end.should raise_error(/could not find class.*SomethingUndefined/i)
39
+ end
40
+
41
+ context "namespaced" do
42
+ it "can find namespaced classes for objects with / in name" do
43
+ c = subject.find_class("chart/model")
44
+ c.should_not be_nil
45
+ c.should == Chart::Model
46
+ end
33
47
 
34
- it "raises an error for nil input" do
35
- lambda do
36
- subject.find_class('something_undefined')
37
- end.should raise_error(/could not find class.*SomethingUndefined/i)
48
+ it "can find deeply namespaced classes for objects with / in name" do
49
+ c = subject.find_class("somewhere/deep/inside/the/earth")
50
+ c.should_not be_nil
51
+ c.should == Somewhere::Deep::Inside::The::Earth
52
+ end
53
+
54
+ it "raises an error for a misstep along the way" do
55
+ lambda do
56
+ subject.find_class("somewhere/deep/above/the/earth")
57
+ end.should raise_error(/could not find.*Above within Somewhere::Deep/i)
58
+ end
59
+ end
38
60
  end
39
61
 
40
- context "namespaced" do
41
- it "can find namespaced classes for objects with / in name" do
42
- c = subject.find_class("chart/model")
43
- c.should_not be_nil
44
- c.should == Chart::Model
62
+ describe "#get_module_path" do
63
+ before do
64
+ append_test_load_path "namespace"
65
+ require 'deeply_nested/ez_chart/presenter'
45
66
  end
46
67
 
47
- it "can find deeply namespaced classes for objects with / in name" do
48
- c = subject.find_class("somewhere/deep/inside/the/earth")
49
- c.should_not be_nil
50
- c.should == Somewhere::Deep::Inside::The::Earth
68
+ it "returns nil if given class doesn't have :: symbols in it" do
69
+ subject.get_module_path(Object).should be_nil
51
70
  end
52
71
 
53
- it "raises an error for a misstep along the way" do
54
- lambda do
55
- subject.find_class("somewhere/deep/above/the/earth")
56
- end.should raise_error(/could not find.*Above within Somewhere::Deep/i)
72
+ it "returns the underscored pathname of the module for the given class" do
73
+ subject.get_module_path(Conject::ObjectContext).should == "conject"
74
+ subject.get_module_path(DeeplyNested::EzChart::Presenter).should == "deeply_nested/ez_chart"
57
75
  end
58
76
  end
59
77
  end
@@ -2,6 +2,8 @@ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
2
 
3
3
  describe Conject::DependencyResolver do
4
4
 
5
+ subject { described_class.new(:class_finder => class_finder) }
6
+
5
7
  class StubbedObjectContext
6
8
  attr_accessor :objects
7
9
  def initialize(objects)
@@ -22,11 +24,34 @@ describe Conject::DependencyResolver do
22
24
 
23
25
  let :object_context do StubbedObjectContext.new(oc_objects) end
24
26
 
27
+ let :class_finder do mock("class finder") end
28
+
29
+ before do
30
+ class_finder.stub(:get_module_path)
31
+ end
32
+
25
33
  it "maps the object definition component names of the given class to a set of objects gotten from the object context" do
26
34
  subject.resolve_for_class(klass, object_context).should == {
27
35
  cow: "the cow",
28
36
  dog: "the dog"
29
37
  }
30
38
  end
39
+
40
+ describe "when the class is in a module" do
41
+ before do
42
+ class_finder.stub(:get_module_path).with(klass).and_return("a/module/path")
43
+ object_context.stub(:get).with("a/module/path/cow").and_return "the relative cow"
44
+ object_context.stub(:get).with("a/module/path/dog").and_return "the relative dog"
45
+ end
46
+
47
+ it "first tries to lookup relative component names" do
48
+ subject.resolve_for_class(klass, object_context).should == {
49
+ cow: "the relative cow",
50
+ dog: "the relative dog",
51
+ }
52
+ end
53
+
54
+
55
+ end
31
56
  end
32
57
 
@@ -0,0 +1,6 @@
1
+ module DeeplyNested
2
+ module EzChart
3
+ class Model
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ module DeeplyNested
2
+ module EzChart
3
+ class Presenter
4
+ construct_with 'model', 'view'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module DeeplyNested
2
+ module EzChart
3
+ class View
4
+ end
5
+ end
6
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conject
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-13 00:00:00.000000000 Z
12
+ date: 2012-12-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -118,7 +118,7 @@ files:
118
118
  - scratch/sample.rb
119
119
  - scratch/special_construct.rb
120
120
  - spec/acceptance/dev/README
121
- - spec/acceptance/dev/object_peers_spec.rb
121
+ - spec/acceptance/dev/module_scoping_spec.rb
122
122
  - spec/acceptance/regression/README
123
123
  - spec/acceptance/regression/basic_composition_spec.rb
124
124
  - spec/acceptance/regression/basic_object_creation_spec.rb
@@ -126,9 +126,9 @@ files:
126
126
  - spec/acceptance/regression/default_object_context_spec.rb
127
127
  - spec/acceptance/regression/inherited_dependencies_spec.rb
128
128
  - spec/acceptance/regression/inject_object_context_spec.rb
129
- - spec/acceptance/regression/module_scoping_spec.rb
130
129
  - spec/acceptance/regression/nested_contexts_spec.rb
131
130
  - spec/acceptance/regression/non_singleton_spec.rb
131
+ - spec/acceptance/regression/object_peers_spec.rb
132
132
  - spec/conject/borrowed_active_support_inflector_spec.rb
133
133
  - spec/conject/class_ext_construct_with_spec.rb
134
134
  - spec/conject/class_finder_spec.rb
@@ -165,6 +165,9 @@ files:
165
165
  - spec/test_data/namespace/chart/model.rb
166
166
  - spec/test_data/namespace/chart/presenter.rb
167
167
  - spec/test_data/namespace/chart/view.rb
168
+ - spec/test_data/namespace/deeply_nested/ez_chart/model.rb
169
+ - spec/test_data/namespace/deeply_nested/ez_chart/presenter.rb
170
+ - spec/test_data/namespace/deeply_nested/ez_chart/view.rb
168
171
  - spec/test_data/namespace/somewhere/deep/inside/the/earth.rb
169
172
  - spec/test_data/object_peers/alt_game.rb
170
173
  - spec/test_data/object_peers/bullet.rb
@@ -189,7 +192,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
189
192
  version: '0'
190
193
  segments:
191
194
  - 0
192
- hash: -3446257381673869502
195
+ hash: -1030399323888719184
193
196
  required_rubygems_version: !ruby/object:Gem::Requirement
194
197
  none: false
195
198
  requirements:
@@ -198,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
198
201
  version: '0'
199
202
  segments:
200
203
  - 0
201
- hash: -3446257381673869502
204
+ hash: -1030399323888719184
202
205
  requirements: []
203
206
  rubyforge_project:
204
207
  rubygems_version: 1.8.24
@@ -207,7 +210,7 @@ specification_version: 3
207
210
  summary: Enable Guice-like dependency injection and contextual object interactions.
208
211
  test_files:
209
212
  - spec/acceptance/dev/README
210
- - spec/acceptance/dev/object_peers_spec.rb
213
+ - spec/acceptance/dev/module_scoping_spec.rb
211
214
  - spec/acceptance/regression/README
212
215
  - spec/acceptance/regression/basic_composition_spec.rb
213
216
  - spec/acceptance/regression/basic_object_creation_spec.rb
@@ -215,9 +218,9 @@ test_files:
215
218
  - spec/acceptance/regression/default_object_context_spec.rb
216
219
  - spec/acceptance/regression/inherited_dependencies_spec.rb
217
220
  - spec/acceptance/regression/inject_object_context_spec.rb
218
- - spec/acceptance/regression/module_scoping_spec.rb
219
221
  - spec/acceptance/regression/nested_contexts_spec.rb
220
222
  - spec/acceptance/regression/non_singleton_spec.rb
223
+ - spec/acceptance/regression/object_peers_spec.rb
221
224
  - spec/conject/borrowed_active_support_inflector_spec.rb
222
225
  - spec/conject/class_ext_construct_with_spec.rb
223
226
  - spec/conject/class_finder_spec.rb
@@ -254,6 +257,9 @@ test_files:
254
257
  - spec/test_data/namespace/chart/model.rb
255
258
  - spec/test_data/namespace/chart/presenter.rb
256
259
  - spec/test_data/namespace/chart/view.rb
260
+ - spec/test_data/namespace/deeply_nested/ez_chart/model.rb
261
+ - spec/test_data/namespace/deeply_nested/ez_chart/presenter.rb
262
+ - spec/test_data/namespace/deeply_nested/ez_chart/view.rb
257
263
  - spec/test_data/namespace/somewhere/deep/inside/the/earth.rb
258
264
  - spec/test_data/object_peers/alt_game.rb
259
265
  - spec/test_data/object_peers/bullet.rb
@@ -1,45 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
-
3
-
4
- describe "module scoping" do
5
- subject { new_object_context }
6
-
7
- before do
8
- append_test_load_path "namespace"
9
- require 'chart/model'
10
- require 'chart/presenter'
11
- require 'chart/view'
12
- end
13
-
14
- after do
15
- restore_load_path
16
- end
17
-
18
- it "constructs objects with module-scoped classes" do
19
- obj = subject.get('chart/model')
20
- obj.should_not be_nil
21
- obj.class.should == Chart::Model
22
- end
23
-
24
- it "supports symbols as keys" do
25
- obj = subject.get(:'chart/model')
26
- obj.should_not be_nil
27
- obj.class.should == Chart::Model
28
- end
29
-
30
- it "lets objects depend on module-namespaced components" do
31
- obj = subject.get('chart/presenter')
32
- obj.should_not be_nil
33
- obj.class.should == Chart::Presenter
34
-
35
- model = obj.send(:model)
36
- model.should be
37
- model.class.should == Chart::Model
38
-
39
- view = obj.send(:view)
40
- view.should be
41
- view.class.should == Chart::View
42
- end
43
-
44
- end
45
-