conject 0.1.7 → 0.1.8
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/CHANGELOG +4 -0
- data/LICENSE +20 -0
- data/README.md +63 -53
- data/lib/conject/class_finder.rb +2 -2
- data/lib/conject/version.rb +1 -1
- data/spec/acceptance/regression/module_scoping_spec.rb +9 -0
- data/spec/conject/class_finder_spec.rb +8 -0
- data/spec/conject/dependency_resolver_spec.rb +1 -1
- data/spec/conject/object_context_spec.rb +2 -2
- data/spec/conject/object_factory_spec.rb +5 -5
- data/spec/test_data/namespace/showing/ancestor.rb +4 -0
- data/spec/test_data/namespace/showing/no/fear/fear.rb +9 -0
- data/spec/test_data/namespace/showing/no/subject.rb +7 -0
- metadata +10 -9
data/CHANGELOG
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 David Crosby
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -6,29 +6,29 @@ Retrieve and relate objects within contexts. Provides dependency injection conv
|
|
6
6
|
|
7
7
|
Declare required component objects for a class using .construct_with
|
8
8
|
|
9
|
+
```ruby
|
10
|
+
require 'conject'
|
9
11
|
|
10
|
-
|
12
|
+
class Wood
|
13
|
+
def to_s; "Wood"; end
|
14
|
+
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
class Nails
|
17
|
-
def to_s; "Nails"; end
|
18
|
-
end
|
16
|
+
class Nails
|
17
|
+
def to_s; "Nails"; end
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
class Fence
|
21
|
+
construct_with :wood, :nails
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
fence = Conject.default_object_context.get(:fence)
|
29
|
-
puts fence
|
30
|
-
#=> "I'm made of Wood and Nails"
|
23
|
+
def to_s
|
24
|
+
"I'm made of #{wood} and #{nails}"
|
25
|
+
end
|
26
|
+
end
|
31
27
|
|
28
|
+
fence = Conject.default_object_context.get(:fence)
|
29
|
+
puts fence
|
30
|
+
#=> "I'm made of Wood and Nails"
|
31
|
+
```
|
32
32
|
# Configuring objects #
|
33
33
|
|
34
34
|
Call #configure_object or #configure_objects to configure one or more objects wrt
|
@@ -47,39 +47,43 @@ Eg.
|
|
47
47
|
|
48
48
|
# Modules as namespaces #
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
```ruby
|
51
|
+
module Chart
|
52
|
+
class Presenter
|
53
|
+
construct_with 'chart/model', 'chart/view'
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
55
|
+
def to_s
|
56
|
+
"I'm a Chart::Presenter composed of a #{model} and a #{view}"
|
58
57
|
end
|
59
|
-
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
60
61
|
# Subcontexts #
|
61
62
|
|
62
|
-
|
63
|
-
|
63
|
+
```ruby
|
64
|
+
first_fence = nil
|
65
|
+
second_fence = nil
|
64
66
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
Conject.default_object_context.in_subcontext do |sub|
|
70
|
-
second_fence = sub[:fence]
|
71
|
-
end
|
67
|
+
Conject.default_object_context.in_subcontext do |sub|
|
68
|
+
first_fence = sub[:fence]
|
69
|
+
end
|
72
70
|
|
73
|
-
|
71
|
+
Conject.default_object_context.in_subcontext do |sub|
|
72
|
+
second_fence = sub[:fence]
|
73
|
+
end
|
74
74
|
|
75
|
+
# second_fence != first_fence
|
76
|
+
```
|
75
77
|
If you'd like to ensure that certain dependencies needed by objects built in subcontexts are actually housed in the parent context, but they
|
76
78
|
have not necessarily been cached or injected in advance, AND you've got an "owner"-like object living in that context, you can declare
|
77
79
|
object peers within the class definition of that owner object. This ensures that collaborators in the subcontext will not cause the peer
|
78
80
|
objects to be instantiated in those subcontexts as well.
|
79
81
|
|
80
|
-
|
81
|
-
|
82
|
-
|
82
|
+
```ruby
|
83
|
+
class Game
|
84
|
+
object_peers: :missile_coordinator, :wind_affector
|
85
|
+
end
|
86
|
+
```
|
83
87
|
|
84
88
|
In this example, the instantiation of a Game instance in an object context will cause missile coordinator and wind affector to be "anchored"
|
85
89
|
in the same context as the game instance, meaning they prefer to be instantiated here, if needed by any objects in this same context or any
|
@@ -94,12 +98,16 @@ is available as early as the call to #initialize.
|
|
94
98
|
The following will cause one object to be fulfilled by another. In this case, 'album' is not expected to be built
|
95
99
|
as an instance of the Album class, but rather will be set up as another name for 'and_justice_for_all':
|
96
100
|
|
97
|
-
|
101
|
+
```ruby
|
102
|
+
context.configure_objects album: { is: 'and_justice_for_all' }
|
103
|
+
```
|
98
104
|
|
99
105
|
Both 'album' and 'and_justice_for_all' will be built in the context when 'album' is first requested.
|
100
106
|
This is more or less expressive shorthand for:
|
101
107
|
|
102
|
-
|
108
|
+
```ruby
|
109
|
+
context['album'] = context['and_justice_for_all']
|
110
|
+
```
|
103
111
|
|
104
112
|
...EXCEPT that it's a lazy approach: using 'is' means nothing actually gets built or set in the context before it
|
105
113
|
is requested or composed into another object.
|
@@ -109,18 +117,20 @@ is requested or composed into another object.
|
|
109
117
|
To declare objects as instances of a specific class, you may specify the :class of the object via #configure_objects.
|
110
118
|
Furthermore, you can specialize the instance by indicating which specific objects you would like to supply as the object's collaborators:
|
111
119
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
```ruby
|
121
|
+
context.configure_objects({
|
122
|
+
adventure_time: {
|
123
|
+
class: Team,
|
124
|
+
specialize: {
|
125
|
+
hero: "finn",
|
126
|
+
sidekick: "jake" }},
|
127
|
+
dark_knight: {
|
128
|
+
class: Team,
|
129
|
+
specialize: {
|
130
|
+
hero: "batman",
|
131
|
+
sidekick: "robin" }}
|
132
|
+
})
|
133
|
+
```
|
124
134
|
|
125
135
|
The keys in :specialize match some or all of the keys defined in the class (in this case, the Team class is defined to be #construct_with :hero, :sidekick, :clock.
|
126
136
|
The values are object names within the ObjectContext; they will be resolved in the usual manner.
|
data/lib/conject/class_finder.rb
CHANGED
@@ -28,8 +28,8 @@ module Conject
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def get_constant(within, name)
|
31
|
-
if within.const_defined?(name)
|
32
|
-
within.const_get(name)
|
31
|
+
if within.const_defined?(name, false)
|
32
|
+
within.const_get(name, false)
|
33
33
|
else
|
34
34
|
raise "Could not find class or module named #{name} within #{within}"
|
35
35
|
end
|
data/lib/conject/version.rb
CHANGED
@@ -10,6 +10,9 @@ describe "module scoping" do
|
|
10
10
|
require 'chart/model'
|
11
11
|
require 'chart/presenter'
|
12
12
|
require 'chart/view'
|
13
|
+
require 'showing/no/subject'
|
14
|
+
require 'showing/ancestor'
|
15
|
+
require 'showing/no/fear/fear'
|
13
16
|
end
|
14
17
|
|
15
18
|
after do
|
@@ -28,6 +31,12 @@ describe "module scoping" do
|
|
28
31
|
obj.class.should == Chart::Model
|
29
32
|
end
|
30
33
|
|
34
|
+
it "correctly finds a dependency for modules at different levels" do
|
35
|
+
obj1 = subject.get('showing/no/subject')
|
36
|
+
obj2 = subject.get('showing/no/fear/fear')
|
37
|
+
obj1.send(:ancestor).should == obj2.send(:ancestor)
|
38
|
+
end
|
39
|
+
|
31
40
|
it "lets objects depend on module-namespaced components" do
|
32
41
|
obj = subject.get('chart/presenter')
|
33
42
|
obj.should_not be_nil
|
@@ -8,6 +8,8 @@ describe Conject::ClassFinder do
|
|
8
8
|
require 'some_random_class'
|
9
9
|
require 'chart/model'
|
10
10
|
require 'somewhere/deep/inside/the/earth'
|
11
|
+
require 'showing/no/subject'
|
12
|
+
require 'showing/ancestor'
|
11
13
|
end
|
12
14
|
|
13
15
|
after do
|
@@ -51,6 +53,12 @@ describe Conject::ClassFinder do
|
|
51
53
|
c.should == Somewhere::Deep::Inside::The::Earth
|
52
54
|
end
|
53
55
|
|
56
|
+
it "does not search for ancestors" do
|
57
|
+
lambda do
|
58
|
+
subject.find_class("showing/no/showing/ancestor")
|
59
|
+
end.should raise_error(/Could not find class.*/)
|
60
|
+
end
|
61
|
+
|
54
62
|
it "raises an error for a misstep along the way" do
|
55
63
|
lambda do
|
56
64
|
subject.find_class("somewhere/deep/above/the/earth")
|
@@ -24,7 +24,7 @@ describe Conject::DependencyResolver do
|
|
24
24
|
|
25
25
|
let :object_context do StubbedObjectContext.new(oc_objects) end
|
26
26
|
|
27
|
-
let :class_finder do
|
27
|
+
let :class_finder do double("class finder") end
|
28
28
|
|
29
29
|
before do
|
30
30
|
class_finder.stub(:get_module_path)
|
@@ -5,8 +5,8 @@ describe Conject::ObjectContext do
|
|
5
5
|
Conject::ObjectContext.new(:parent_context => parent_context, :object_factory => object_factory)
|
6
6
|
end
|
7
7
|
|
8
|
-
let :parent_context do
|
9
|
-
let :object_factory do
|
8
|
+
let :parent_context do double(:parent_context) end
|
9
|
+
let :object_factory do double(:object_factory) end
|
10
10
|
|
11
11
|
describe "#get" do
|
12
12
|
describe "when an object has been #put" do
|
@@ -12,14 +12,14 @@ describe Conject::ObjectFactory do
|
|
12
12
|
|
13
13
|
let :my_object_name do :my_object_name end
|
14
14
|
|
15
|
-
let :class_finder do
|
16
|
-
let :dependency_resolver do
|
15
|
+
let :class_finder do double(:class_finder) end
|
16
|
+
let :dependency_resolver do double(:dependency_resolver) end
|
17
17
|
|
18
|
-
let :object_context do
|
18
|
+
let :object_context do double(:object_context) end
|
19
19
|
|
20
20
|
let :my_object_class do Class.new end
|
21
|
-
let :my_object do
|
22
|
-
let :my_objects_components do
|
21
|
+
let :my_object do double(:my_object) end
|
22
|
+
let :my_objects_components do double(:my_objects_components) end
|
23
23
|
|
24
24
|
describe "#construct_new" do
|
25
25
|
describe "for Type 1 object construction" do
|
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.1.
|
4
|
+
version: 0.1.8
|
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:
|
12
|
+
date: 2014-03-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -84,6 +84,7 @@ extra_rdoc_files: []
|
|
84
84
|
files:
|
85
85
|
- CHANGELOG
|
86
86
|
- Gemfile
|
87
|
+
- LICENSE
|
87
88
|
- README.md
|
88
89
|
- Rakefile
|
89
90
|
- conject.gemspec
|
@@ -177,6 +178,9 @@ files:
|
|
177
178
|
- spec/test_data/namespace/deeply_nested/ez_chart/model.rb
|
178
179
|
- spec/test_data/namespace/deeply_nested/ez_chart/presenter.rb
|
179
180
|
- spec/test_data/namespace/deeply_nested/ez_chart/view.rb
|
181
|
+
- spec/test_data/namespace/showing/ancestor.rb
|
182
|
+
- spec/test_data/namespace/showing/no/fear/fear.rb
|
183
|
+
- spec/test_data/namespace/showing/no/subject.rb
|
180
184
|
- spec/test_data/namespace/somewhere/deep/inside/the/earth.rb
|
181
185
|
- spec/test_data/object_peers/alt_game.rb
|
182
186
|
- spec/test_data/object_peers/bullet.rb
|
@@ -206,21 +210,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
206
210
|
- - ! '>='
|
207
211
|
- !ruby/object:Gem::Version
|
208
212
|
version: '0'
|
209
|
-
segments:
|
210
|
-
- 0
|
211
|
-
hash: -2747476053760078928
|
212
213
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
214
|
none: false
|
214
215
|
requirements:
|
215
216
|
- - ! '>='
|
216
217
|
- !ruby/object:Gem::Version
|
217
218
|
version: '0'
|
218
|
-
segments:
|
219
|
-
- 0
|
220
|
-
hash: -2747476053760078928
|
221
219
|
requirements: []
|
222
220
|
rubyforge_project:
|
223
|
-
rubygems_version: 1.8.
|
221
|
+
rubygems_version: 1.8.23
|
224
222
|
signing_key:
|
225
223
|
specification_version: 3
|
226
224
|
summary: Enable Guice-like dependency injection and contextual object interactions.
|
@@ -284,6 +282,9 @@ test_files:
|
|
284
282
|
- spec/test_data/namespace/deeply_nested/ez_chart/model.rb
|
285
283
|
- spec/test_data/namespace/deeply_nested/ez_chart/presenter.rb
|
286
284
|
- spec/test_data/namespace/deeply_nested/ez_chart/view.rb
|
285
|
+
- spec/test_data/namespace/showing/ancestor.rb
|
286
|
+
- spec/test_data/namespace/showing/no/fear/fear.rb
|
287
|
+
- spec/test_data/namespace/showing/no/subject.rb
|
287
288
|
- spec/test_data/namespace/somewhere/deep/inside/the/earth.rb
|
288
289
|
- spec/test_data/object_peers/alt_game.rb
|
289
290
|
- spec/test_data/object_peers/bullet.rb
|