conject 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/TODO +15 -4
- data/TODO.txt +4 -0
- data/lib/conject/object_context.rb +38 -11
- data/lib/conject/object_factory.rb +23 -5
- data/lib/conject/version.rb +1 -1
- data/{spike → scratch}/arity_funny_business_in_different_ruby_versions.rb +0 -0
- data/scratch/class_singletons.rb +61 -0
- data/{spike → scratch}/depends_on_spike.rb +0 -0
- data/{spike → scratch}/donkey_fail.rb +0 -0
- data/{spike → scratch}/donkey_journey.rb +0 -0
- data/{spike → scratch}/go.rb +0 -0
- data/{spike → scratch}/metaid.rb +0 -0
- data/scratch/namespace_support.rb +3 -0
- data/{spike → scratch}/object_definition.rb +0 -0
- data/{spike → scratch}/sample.rb +0 -0
- data/scratch/special_construct.rb +6 -0
- data/spec/acceptance/regression/custom_constructor_spec.rb +56 -0
- data/spec/acceptance/regression/default_object_context_spec.rb +36 -0
- data/spec/acceptance/regression/inherited_dependencies_spec.rb +19 -4
- data/spec/acceptance/regression/non_singleton_spec.rb +62 -0
- data/spec/conject/object_context_spec.rb +30 -2
- data/spec/conject/object_factory_spec.rb +75 -25
- data/spec/test_data/basic_composition/wood.rb +3 -0
- data/spec/test_data/namespace/chart/model.rb +4 -0
- data/spec/test_data/namespace/chart/presenter.rb +7 -0
- data/spec/test_data/namespace/chart/view.rb +4 -0
- metadata +32 -16
data/TODO
CHANGED
@@ -1,9 +1,20 @@
|
|
1
|
-
|
1
|
+
Features:
|
2
|
+
customer construction lambda via configure_objects
|
3
|
+
|
4
|
+
Class singletons:
|
5
|
+
use_class_in_context
|
6
|
+
class_depends_on
|
7
|
+
|
8
|
+
context.configure( :use_class_singletons => true)
|
9
|
+
|
10
|
+
ObjectContext#no_cache? <- reimplement for recursive upward search of object configs
|
11
|
+
|
12
|
+
contexts can accept configurations targeted at named subcontext
|
13
|
+
|
14
|
+
Support classes namespaced to modules
|
15
|
+
|
2
16
|
|
3
17
|
Move / copy test data (loadable classes) into spec/acceptance/testdata
|
4
18
|
Make helpers for accessing that folder
|
5
19
|
Make helper to set load path for a specific test
|
6
20
|
|
7
|
-
Move basic object creation spec to regression
|
8
|
-
|
9
|
-
|
data/TODO.txt
ADDED
@@ -5,6 +5,7 @@ module Conject
|
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@cache = { :this_object_context => self }
|
8
|
+
@object_configs = Hash.new do |h,k| h[k] = {} end
|
8
9
|
end
|
9
10
|
|
10
11
|
# Inject a named object into this context
|
@@ -20,32 +21,31 @@ module Conject
|
|
20
21
|
# If the object exists nowhere in this or a super context: construct, cache and return a new instance of the requested object using the object factory.
|
21
22
|
def get(name)
|
22
23
|
name = name.to_sym
|
23
|
-
object = @cache[name]
|
24
24
|
return @cache[name] if @cache.keys.include?(name)
|
25
25
|
|
26
26
|
if parent_context and parent_context.has?(name)
|
27
27
|
return parent_context.get(name)
|
28
28
|
else
|
29
29
|
object = object_factory.construct_new(name,self)
|
30
|
-
@cache[name] = object
|
30
|
+
@cache[name] = object unless no_cache?(name)
|
31
31
|
return object
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
alias_method :[], :get
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def walk_up_contexts(&block)
|
38
|
+
yield self
|
39
|
+
parent_context.walk_up_contexts(&block) unless parent_context.nil?
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
return
|
44
|
-
else
|
45
|
-
# I don't have it, and neither do my ancestors.
|
46
|
-
return false
|
42
|
+
def has?(name)
|
43
|
+
walk_up_contexts do |context|
|
44
|
+
return true if context.directly_has?(name)
|
47
45
|
end
|
46
|
+
return false
|
48
47
|
end
|
48
|
+
|
49
49
|
|
50
50
|
# Indicates if this context has the requested object in its own personal cache.
|
51
51
|
# (Does not consult any parent contexts.)
|
@@ -53,9 +53,36 @@ module Conject
|
|
53
53
|
@cache.keys.include?(name.to_sym)
|
54
54
|
end
|
55
55
|
|
56
|
+
# Create and yield a new ObjectContext with this ObjectContext as its parent
|
56
57
|
def in_subcontext
|
57
58
|
yield Conject.create_object_context(self) if block_given?
|
58
59
|
end
|
59
60
|
|
61
|
+
|
62
|
+
#
|
63
|
+
# Allow configuration options to be set for named objects.
|
64
|
+
#
|
65
|
+
def configure_objects(conf={})
|
66
|
+
conf.each do |key,opts|
|
67
|
+
get_object_config(key).merge!(opts)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# Get the object configuration options for the given name
|
73
|
+
#
|
74
|
+
def get_object_config(name)
|
75
|
+
@object_configs[name.to_sym]
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
#
|
81
|
+
# Returns true if an object has been specifically declared as non-cacheable.
|
82
|
+
#
|
83
|
+
def no_cache?(name)
|
84
|
+
get_object_config(name)[:cache] == false
|
85
|
+
end
|
86
|
+
|
60
87
|
end
|
61
88
|
end
|
@@ -4,13 +4,31 @@ module Conject
|
|
4
4
|
construct_with :class_finder, :dependency_resolver
|
5
5
|
|
6
6
|
def construct_new(name, object_context)
|
7
|
+
lambda_constructor = object_context.get_object_config(name)[:construct]
|
8
|
+
if lambda_constructor
|
9
|
+
case lambda_constructor.arity
|
10
|
+
when 0
|
11
|
+
return lambda_constructor[]
|
12
|
+
when 1
|
13
|
+
return lambda_constructor[object_context]
|
14
|
+
when 2
|
15
|
+
return lambda_constructor[name, object_context]
|
16
|
+
else
|
17
|
+
raise "Constructor lambda takes 0, 1 or 2 params; this lambda takes #{lambda_constructor.arity}"
|
18
|
+
end
|
19
|
+
else
|
20
|
+
return type_1_constructor(name, object_context)
|
21
|
+
end
|
22
|
+
end
|
7
23
|
|
8
|
-
|
9
|
-
# This implementation is what I'm loosely calling "type 1" or "regular" object creation:
|
10
|
-
# - Assume we're looking for a class to create an instance with
|
11
|
-
# - it may or may not have a declared list of named objects it needs to be constructed with
|
12
|
-
#
|
24
|
+
private
|
13
25
|
|
26
|
+
#
|
27
|
+
# This implementation is what I'm loosely calling "type 1" or "regular" object creation:
|
28
|
+
# - Assume we're looking for a class to create an instance with
|
29
|
+
# - it may or may not have a declared list of named objects it needs to be constructed with
|
30
|
+
#
|
31
|
+
def type_1_constructor(name, object_context)
|
14
32
|
klass = class_finder.find_class(name)
|
15
33
|
|
16
34
|
if klass.has_object_definition?
|
data/lib/conject/version.rb
CHANGED
File without changes
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Classes-as-objects can be a convenient way to build
|
3
|
+
# systems of objects that need to collaborate, but which
|
4
|
+
# have no other need for repeated instantiation, or implementation
|
5
|
+
# substitutions within the roles. (Ie, objects are what they are, and the
|
6
|
+
# system objects are more or less free of mutable state.)
|
7
|
+
#
|
8
|
+
# Ruby's classes, when declared "normally", are named objects available globally.
|
9
|
+
# So class S3, while a Class that could be used to generate instances, is also
|
10
|
+
# and _object_, a singleton named S3, and any other object can refer to this
|
11
|
+
# singleton by name. Implement your functionality as class methods and you're ready to go.
|
12
|
+
#
|
13
|
+
# Drawbacks:
|
14
|
+
#
|
15
|
+
# You have to be right about not needing subcontexts or impl.
|
16
|
+
# substitution; without this assumption, you're left with nothing.
|
17
|
+
#
|
18
|
+
# Code NOT written this way might have difficulty using Classes-as-objects code
|
19
|
+
#
|
20
|
+
# Classes-as-objects code cannot utilize systems that aren't written in the same way
|
21
|
+
#
|
22
|
+
# A classes-as-objects system, if during development is discovered to break these assumptions,
|
23
|
+
# they must be re-written.
|
24
|
+
#
|
25
|
+
# Observations:
|
26
|
+
# Classes-as-objects is a special case of contextual objects: all system objects are
|
27
|
+
# singletons, no implementation substitution is ever required, dependency injection
|
28
|
+
# is not required, and no construction-time behavior needs to be implemented.
|
29
|
+
# (No constructors. This isn't 100% off the table; there's always in-body configuration, eg,
|
30
|
+
# via metacoding.) All objects are at the top-most (global, or root) context in the application,
|
31
|
+
# and no subcontexts are ever needed.
|
32
|
+
#
|
33
|
+
# We could provide tooling to imply context for classes, and give them more abstract
|
34
|
+
# access to their constituents, in a way that can be modified orthogonally to their
|
35
|
+
# code. (Whereas you can't change what it means for S3 to refer to NameFormatter, you _could_
|
36
|
+
# change the way name_formatter is provided to the S3 class).
|
37
|
+
#
|
38
|
+
# NEEDS:
|
39
|
+
# - Let a class singleton declare itself to participate in a Context (root context by default)
|
40
|
+
# - withing class singleton, reference collaborator objects contextually
|
41
|
+
# - ObjectContext configuration: assume all objects are serviced by class singletons
|
42
|
+
# - ObjcetContext configuration: object-by-object config to indicate class singletons
|
43
|
+
|
44
|
+
|
45
|
+
class S3
|
46
|
+
use_class_in_context
|
47
|
+
class_depends_on :name_formatter
|
48
|
+
|
49
|
+
class << self
|
50
|
+
|
51
|
+
def store_file(name, data)
|
52
|
+
formatted_name = name_formatter.format(name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context.configure :use_class_singletons => true
|
58
|
+
|
59
|
+
context.configure_object :s3 => { :use_class_singleton => true }
|
60
|
+
# same as: context[:s3] = S3 ??
|
61
|
+
|
File without changes
|
File without changes
|
File without changes
|
data/{spike → scratch}/go.rb
RENAMED
File without changes
|
data/{spike → scratch}/metaid.rb
RENAMED
File without changes
|
File without changes
|
data/{spike → scratch}/sample.rb
RENAMED
File without changes
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
|
2
|
+
|
3
|
+
describe "configuring objects to be built with a lambda" do
|
4
|
+
subject { new_object_context }
|
5
|
+
|
6
|
+
before do
|
7
|
+
append_test_load_path "basic_composition"
|
8
|
+
require 'fence'
|
9
|
+
require 'wood'
|
10
|
+
require 'nails'
|
11
|
+
end
|
12
|
+
|
13
|
+
let :wood_substitute do
|
14
|
+
Class.new do
|
15
|
+
attr_reader :name, :object_context
|
16
|
+
|
17
|
+
def initialize(name,object_context)
|
18
|
+
@name = name
|
19
|
+
@object_context = object_context
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"MDF"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
after do
|
29
|
+
restore_load_path
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
it "constructs and caches instances by running the given lamdba" do
|
34
|
+
wood_constructs = 0
|
35
|
+
|
36
|
+
subject.configure_objects(
|
37
|
+
:wood => {
|
38
|
+
:construct => lambda do |name,object_context|
|
39
|
+
wood_constructs += 1
|
40
|
+
wood_substitute.new name,object_context
|
41
|
+
end
|
42
|
+
}
|
43
|
+
)
|
44
|
+
|
45
|
+
fence = subject.get(:fence)
|
46
|
+
fence.wood.should be
|
47
|
+
fence.wood.to_s.should == "MDF"
|
48
|
+
fence.wood.name.should == :wood
|
49
|
+
fence.wood.object_context.should == subject
|
50
|
+
wood_constructs.should == 1
|
51
|
+
|
52
|
+
subject.get(:wood).should == fence.wood
|
53
|
+
wood_constructs.should == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
|
2
|
+
|
3
|
+
describe "Conject" do
|
4
|
+
before do
|
5
|
+
append_test_load_path "basic_composition"
|
6
|
+
require 'fence'
|
7
|
+
require 'wood'
|
8
|
+
require 'nails'
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".default_object_context" do
|
12
|
+
it "provides an object context" do
|
13
|
+
context = Conject.default_object_context
|
14
|
+
context[:fence].should be
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
it "provides the SAME object context on repeated use" do
|
19
|
+
context1 = Conject.default_object_context
|
20
|
+
context2 = Conject.default_object_context
|
21
|
+
|
22
|
+
context1.should be
|
23
|
+
context1.should == context2
|
24
|
+
context1[:fence].should == context2[:fence]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
after do
|
30
|
+
restore_load_path
|
31
|
+
# Sneak in and reset default object context instance inside Conject:
|
32
|
+
Conject.instance_variable_set(:@default_object_context, nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
@@ -136,10 +136,6 @@ describe "basic inheritance" do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
139
|
context "superclass has 1-arg #initialize" do
|
144
140
|
class Reptile
|
145
141
|
construct_with :scales
|
@@ -250,4 +246,23 @@ describe "basic inheritance" do
|
|
250
246
|
end
|
251
247
|
|
252
248
|
end
|
249
|
+
|
250
|
+
context "subclass not declaring deps, though its superclass DOES have deps" do
|
251
|
+
let(:parent) do
|
252
|
+
Class.new do
|
253
|
+
construct_with :home, :money
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
let(:child) do
|
258
|
+
Class.new(parent) do
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
it "raises an error at init time" do
|
263
|
+
lambda do
|
264
|
+
child.new nil
|
265
|
+
end.should raise_error(/ancestor.*construct_with.*dependencies.*instantiate/)
|
266
|
+
end
|
267
|
+
end
|
253
268
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
|
2
|
+
|
3
|
+
describe "configuring objects to be non-cacheable" do
|
4
|
+
subject { new_object_context }
|
5
|
+
|
6
|
+
before do
|
7
|
+
append_test_load_path "basic_composition"
|
8
|
+
require 'fence'
|
9
|
+
require 'wood'
|
10
|
+
require 'nails'
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
restore_load_path
|
15
|
+
end
|
16
|
+
|
17
|
+
it "causes an object to be rebuilt with every request" do
|
18
|
+
subject.configure_objects(
|
19
|
+
:fence => { :cache => false },
|
20
|
+
:nails => { :cache => false },
|
21
|
+
)
|
22
|
+
|
23
|
+
f1 = subject.get(:fence)
|
24
|
+
f2 = subject.get(:fence)
|
25
|
+
|
26
|
+
# Show new fences built:
|
27
|
+
f1.should be
|
28
|
+
f2.should be
|
29
|
+
f1.should_not == f2
|
30
|
+
|
31
|
+
# nails should also be unique:
|
32
|
+
f1.nails.should_not == f2.nails
|
33
|
+
|
34
|
+
# context should not retain references to fence or nails:
|
35
|
+
subject.has?(:fence).should == false
|
36
|
+
subject.has?(:nails).should == false
|
37
|
+
|
38
|
+
# wood should remain cached as usual, and shared
|
39
|
+
f1.wood.should == f2.wood
|
40
|
+
subject.has?(:wood).should == true
|
41
|
+
subject.get(:wood).should == f1.wood
|
42
|
+
subject.get(:wood).should == f2.wood
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# other syntax ideas:
|
49
|
+
#
|
50
|
+
# subject.no_cache(:fence)
|
51
|
+
|
52
|
+
# subject.do_not_cache(:fence)
|
53
|
+
|
54
|
+
# subject.configure(:fence, :cache => false)
|
55
|
+
|
56
|
+
# subject.configure(:fence, :singleton => false)
|
57
|
+
|
58
|
+
# subject.configure do |config|
|
59
|
+
# config.object :fence, :cache => false
|
60
|
+
# end
|
61
|
+
|
62
|
+
# subject.configure.object :fence, :cache => false
|
@@ -119,10 +119,12 @@ describe Conject::ObjectContext do
|
|
119
119
|
|
120
120
|
describe "when there is a parent context" do
|
121
121
|
it "delegates the question to the parent context" do
|
122
|
-
parent_context.should_receive(:
|
123
|
-
|
122
|
+
parent_context.should_receive(:walk_up_contexts).and_yield(parent_context)
|
123
|
+
parent_context.should_receive(:directly_has?).with(:a_clue).and_return(true)
|
124
|
+
subject.has?(:a_clue).should == true
|
124
125
|
end
|
125
126
|
end
|
127
|
+
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
@@ -183,4 +185,30 @@ describe Conject::ObjectContext do
|
|
183
185
|
subsubcontext_executed.should be_true
|
184
186
|
end
|
185
187
|
end
|
188
|
+
|
189
|
+
describe "#configure_objects" do
|
190
|
+
describe ":cache => false" do
|
191
|
+
before do
|
192
|
+
parent_context.stub(:has?).and_return(false)
|
193
|
+
parent_context.should_not_receive(:get)
|
194
|
+
@first_burger = "first burger"
|
195
|
+
@second_burger = "second burger"
|
196
|
+
|
197
|
+
subject.configure_objects :cheezburger => { :cache => false }
|
198
|
+
end
|
199
|
+
|
200
|
+
it "causes the Context not to cache a constructed object, but to build new each time" do
|
201
|
+
object_factory.should_receive(:construct_new).with(:cheezburger, subject).and_return(@first_burger)
|
202
|
+
object_factory.should_receive(:construct_new).with(:cheezburger, subject).and_return(@second_burger)
|
203
|
+
|
204
|
+
subject[:cheezburger].should == @first_burger
|
205
|
+
subject[:cheezburger].should == @second_burger
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# describe "for already-cached objects" do
|
210
|
+
# it "raises an error"
|
211
|
+
# end
|
212
|
+
|
213
|
+
end
|
186
214
|
end
|
@@ -22,46 +22,96 @@ describe Conject::ObjectFactory do
|
|
22
22
|
let :my_objects_components do mock(:my_objects_components) end
|
23
23
|
|
24
24
|
describe "#construct_new" do
|
25
|
-
|
26
|
-
class_finder.should_receive(:find_class).with(my_object_name).and_return my_object_class
|
27
|
-
Conject::Utilities.stub(:has_zero_arg_constructor?).and_return true
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "when target class has an object definition (implying composition dependencies)" do
|
25
|
+
describe "for Type 1 object construction" do
|
31
26
|
before do
|
32
|
-
|
27
|
+
object_context.stub(:get_object_config).and_return({})
|
28
|
+
|
29
|
+
class_finder.should_receive(:find_class).with(my_object_name).and_return my_object_class
|
30
|
+
Conject::Utilities.stub(:has_zero_arg_constructor?).and_return true
|
33
31
|
end
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
describe "when target class has an object definition (implying composition dependencies)" do
|
34
|
+
before do
|
35
|
+
my_object_class.should_receive(:has_object_definition?).and_return true
|
36
|
+
end
|
38
37
|
|
39
|
-
|
38
|
+
it "finds the object definition, pulls its deps, and instantiates a new instance" do
|
39
|
+
dependency_resolver.should_receive(:resolve_for_class).with(my_object_class, object_context).and_return my_objects_components
|
40
|
+
my_object_class.should_receive(:new).with(my_objects_components).and_return(my_object)
|
41
|
+
|
42
|
+
subject.construct_new(my_object_name, object_context).should == my_object
|
43
|
+
end
|
40
44
|
end
|
41
|
-
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
describe "when target class has no object definition" do
|
47
|
+
before do
|
48
|
+
my_object_class.should_receive(:has_object_definition?).and_return false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "creates a new instance of the class without any arguments" do
|
52
|
+
my_object_class.should_receive(:new).and_return(my_object)
|
53
|
+
subject.construct_new(my_object_name, object_context).should == my_object
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
48
|
-
|
49
|
-
|
50
|
-
|
57
|
+
describe "when target class has no object def, but also a non-default constructor" do
|
58
|
+
before do
|
59
|
+
my_object_class.should_receive(:has_object_definition?).and_return false
|
60
|
+
Conject::Utilities.stub(:has_zero_arg_constructor?).and_return false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises a CompositionError" do
|
64
|
+
lambda do
|
65
|
+
subject.construct_new(my_object_name, object_context)
|
66
|
+
end.should raise_error(ArgumentError)
|
67
|
+
end
|
51
68
|
end
|
52
69
|
end
|
53
70
|
|
54
|
-
describe "
|
71
|
+
describe "for custom lambda construction" do
|
72
|
+
let(:object_config) do { :construct => lambda do "The Object" end } end
|
73
|
+
let(:object_config2) do { :construct => lambda do |object_context| { :the_oc => object_context } end } end
|
74
|
+
let(:object_config3) do { :construct => lambda do |name, object_context| { :the_name => name, :the_oc => object_context } end } end
|
75
|
+
let(:object_config4) do { :construct => lambda do raise("the roof") end } end
|
76
|
+
let(:object_config5) do { :construct => lambda do |a,b,c| "whatev" end } end
|
77
|
+
|
55
78
|
before do
|
56
|
-
|
57
|
-
|
79
|
+
object_context.stub(:get_object_config).with(:the_object).and_return(object_config)
|
80
|
+
object_context.stub(:get_object_config).with(:the_other_object).and_return(object_config2)
|
81
|
+
object_context.stub(:get_object_config).with(:the_third_object).and_return(object_config3)
|
82
|
+
object_context.stub(:get_object_config).with(:the_fail_object).and_return(object_config4)
|
83
|
+
object_context.stub(:get_object_config).with(:the_two_many_params).and_return(object_config5)
|
58
84
|
end
|
59
85
|
|
60
|
-
it "
|
61
|
-
|
62
|
-
subject.construct_new(my_object_name, object_context)
|
63
|
-
end.should raise_error(ArgumentError)
|
86
|
+
it "invokes the configured lambda in order to build the object" do
|
87
|
+
subject.construct_new(:the_object, object_context).should == "The Object"
|
64
88
|
end
|
89
|
+
|
90
|
+
it "supplies object_context for lambdas with arity of 1" do
|
91
|
+
obj = subject.construct_new(:the_other_object, object_context)
|
92
|
+
obj.should be
|
93
|
+
obj[:the_oc].should == object_context
|
94
|
+
end
|
95
|
+
|
96
|
+
it "supplies name, object_context for lambdas with arity of 2" do
|
97
|
+
obj = subject.construct_new(:the_third_object, object_context)
|
98
|
+
obj.should be
|
99
|
+
obj[:the_name].should == :the_third_object
|
100
|
+
obj[:the_oc].should == object_context
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "when lambda has more than two args" do
|
104
|
+
it "raises an error" do
|
105
|
+
lambda do subject.construct_new(:the_fail_object, object_context) end.should raise_error(/the roof/)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "when lambda raises an error" do
|
110
|
+
it "raises an error" do
|
111
|
+
lambda do subject.construct_new(:the_two_many_params, object_context) end.should raise_error(/constructor lambda takes 0, 1 or 2 params/i)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
65
115
|
end
|
66
116
|
end
|
67
117
|
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.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152736840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2152736840
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2152736400 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2152736400
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: simplecov
|
38
|
-
requirement: &
|
38
|
+
requirement: &2152735900 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2152735900
|
47
47
|
description: Enable Guice-like dependency injection and contextual object interactions.
|
48
48
|
email:
|
49
49
|
- david.crosby@atomicobject.com
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- README.md
|
60
60
|
- Rakefile
|
61
61
|
- TODO
|
62
|
+
- TODO.txt
|
62
63
|
- conject.gemspec
|
63
64
|
- doc/inheritance_woes.txt
|
64
65
|
- lib/conject.rb
|
@@ -74,13 +75,27 @@ files:
|
|
74
75
|
- lib/conject/utilities.rb
|
75
76
|
- lib/conject/version.rb
|
76
77
|
- rake_tasks/rspec.rake
|
78
|
+
- scratch/arity_funny_business_in_different_ruby_versions.rb
|
79
|
+
- scratch/class_singletons.rb
|
80
|
+
- scratch/depends_on_spike.rb
|
81
|
+
- scratch/donkey_fail.rb
|
82
|
+
- scratch/donkey_journey.rb
|
83
|
+
- scratch/go.rb
|
84
|
+
- scratch/metaid.rb
|
85
|
+
- scratch/namespace_support.rb
|
86
|
+
- scratch/object_definition.rb
|
87
|
+
- scratch/sample.rb
|
88
|
+
- scratch/special_construct.rb
|
77
89
|
- spec/acceptance/dev/README
|
78
90
|
- spec/acceptance/regression/README
|
79
91
|
- spec/acceptance/regression/basic_composition_spec.rb
|
80
92
|
- spec/acceptance/regression/basic_object_creation_spec.rb
|
93
|
+
- spec/acceptance/regression/custom_constructor_spec.rb
|
94
|
+
- spec/acceptance/regression/default_object_context_spec.rb
|
81
95
|
- spec/acceptance/regression/inherited_dependencies_spec.rb
|
82
96
|
- spec/acceptance/regression/inject_object_context_spec.rb
|
83
97
|
- spec/acceptance/regression/nested_contexts_spec.rb
|
98
|
+
- spec/acceptance/regression/non_singleton_spec.rb
|
84
99
|
- spec/conject/borrowed_active_support_inflector_spec.rb
|
85
100
|
- spec/conject/class_ext_construct_with_spec.rb
|
86
101
|
- spec/conject/class_finder_spec.rb
|
@@ -112,15 +127,10 @@ files:
|
|
112
127
|
- spec/test_data/inheritance/malibu.rb
|
113
128
|
- spec/test_data/inheritance/vehicle.rb
|
114
129
|
- spec/test_data/inheritance/wheel.rb
|
130
|
+
- spec/test_data/namespace/chart/model.rb
|
131
|
+
- spec/test_data/namespace/chart/presenter.rb
|
132
|
+
- spec/test_data/namespace/chart/view.rb
|
115
133
|
- spec/test_data/simple_stuff/some_random_class.rb
|
116
|
-
- spike/arity_funny_business_in_different_ruby_versions.rb
|
117
|
-
- spike/depends_on_spike.rb
|
118
|
-
- spike/donkey_fail.rb
|
119
|
-
- spike/donkey_journey.rb
|
120
|
-
- spike/go.rb
|
121
|
-
- spike/metaid.rb
|
122
|
-
- spike/object_definition.rb
|
123
|
-
- spike/sample.rb
|
124
134
|
- src/user_model.rb
|
125
135
|
- src/user_presenter.rb
|
126
136
|
- src/user_view.rb
|
@@ -153,9 +163,12 @@ test_files:
|
|
153
163
|
- spec/acceptance/regression/README
|
154
164
|
- spec/acceptance/regression/basic_composition_spec.rb
|
155
165
|
- spec/acceptance/regression/basic_object_creation_spec.rb
|
166
|
+
- spec/acceptance/regression/custom_constructor_spec.rb
|
167
|
+
- spec/acceptance/regression/default_object_context_spec.rb
|
156
168
|
- spec/acceptance/regression/inherited_dependencies_spec.rb
|
157
169
|
- spec/acceptance/regression/inject_object_context_spec.rb
|
158
170
|
- spec/acceptance/regression/nested_contexts_spec.rb
|
171
|
+
- spec/acceptance/regression/non_singleton_spec.rb
|
159
172
|
- spec/conject/borrowed_active_support_inflector_spec.rb
|
160
173
|
- spec/conject/class_ext_construct_with_spec.rb
|
161
174
|
- spec/conject/class_finder_spec.rb
|
@@ -187,4 +200,7 @@ test_files:
|
|
187
200
|
- spec/test_data/inheritance/malibu.rb
|
188
201
|
- spec/test_data/inheritance/vehicle.rb
|
189
202
|
- spec/test_data/inheritance/wheel.rb
|
203
|
+
- spec/test_data/namespace/chart/model.rb
|
204
|
+
- spec/test_data/namespace/chart/presenter.rb
|
205
|
+
- spec/test_data/namespace/chart/view.rb
|
190
206
|
- spec/test_data/simple_stuff/some_random_class.rb
|