conject 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/conject.rb +3 -2
- data/lib/conject/class_ext_construct_with.rb +0 -1
- data/lib/conject/class_finder.rb +8 -0
- data/lib/conject/dependency_resolver.rb +22 -1
- data/lib/conject/version.rb +1 -1
- data/spec/acceptance/dev/module_scoping_spec.rb +78 -0
- data/spec/acceptance/{dev → regression}/object_peers_spec.rb +0 -0
- data/spec/conject/class_finder_spec.rb +60 -42
- data/spec/conject/dependency_resolver_spec.rb +25 -0
- data/spec/test_data/namespace/deeply_nested/ez_chart/model.rb +6 -0
- data/spec/test_data/namespace/deeply_nested/ez_chart/presenter.rb +7 -0
- data/spec/test_data/namespace/deeply_nested/ez_chart/view.rb +6 -0
- metadata +14 -8
- data/spec/acceptance/regression/module_scoping_spec.rb +0 -45
data/lib/conject.rb
CHANGED
@@ -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 =>
|
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:
|
data/lib/conject/class_finder.rb
CHANGED
@@ -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
|
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
|
data/lib/conject/version.rb
CHANGED
@@ -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
|
+
|
File without changes
|
@@ -1,59 +1,77 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
2
|
|
3
3
|
describe Conject::ClassFinder do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
13
|
+
after do
|
14
|
+
restore_load_path
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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 "
|
48
|
-
|
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 "
|
54
|
-
|
55
|
-
|
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
|
|
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.
|
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-
|
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/
|
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: -
|
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: -
|
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/
|
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
|
-
|