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