conject 0.0.8 → 0.0.9

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