diy 1.0.3 → 1.1
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/History.txt +3 -0
- data/Manifest.txt +33 -0
- data/README.txt +11 -0
- data/Rakefile +9 -8
- data/TODO.txt +9 -0
- data/homepage/Notes.txt +27 -0
- data/homepage/Rakefile +14 -0
- data/homepage/diy_example.png +0 -0
- data/homepage/index.erb +36 -0
- data/homepage/index.html +45 -0
- data/homepage/objects_yml.png +0 -0
- data/homepage/page_header.graffle +0 -0
- data/homepage/page_header.html +9 -0
- data/homepage/page_header.png +0 -0
- data/lib/diy.rb +40 -12
- data/sample_code/car.rb +7 -0
- data/sample_code/chassis.rb +5 -0
- data/sample_code/diy_example.rb +26 -0
- data/sample_code/engine.rb +5 -0
- data/sample_code/objects.yml +10 -0
- data/test/constructor.rb +119 -0
- data/test/diy_test.rb +41 -3
- data/test/files/functions/invalid_method.yml +5 -0
- data/test/files/functions/nonsingleton_objects.yml +6 -0
- data/test/files/functions/objects.yml +5 -0
- data/test/files/functions/thing.rb +3 -0
- data/test/files/functions/thing_builder.rb +21 -0
- data/test/files/namespace/animal/bird.rb +5 -0
- data/test/files/namespace/animal/cat.rb +5 -0
- data/test/files/namespace/animal/reptile/hardshell/turtle.rb +8 -0
- data/test/files/namespace/animal/reptile/lizard.rb +7 -0
- data/test/files/namespace/bad_module_specified.yml +8 -0
- data/test/files/namespace/class_name_combine.yml +8 -0
- data/test/files/namespace/hello.txt +1 -0
- data/test/files/namespace/no_module_specified.yml +8 -0
- data/test/files/namespace/objects.yml +21 -0
- data/test/files/namespace/road.rb +2 -0
- data/test/files/namespace/sky.rb +2 -0
- data/test/files/namespace/subcontext.yml +22 -0
- metadata +41 -5
data/History.txt
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
== 1.1 / 2008-05-20
|
2
|
+
* Added 'method' directive for building a bounded method from an object defined in diy
|
3
|
+
|
1
4
|
== 1.0.3 / 2007-12-11
|
2
5
|
|
3
6
|
* The 1.0.1 release had a load-path search in it that resulted in requiring files with full path names (rooted in loadpath entries). This is unintuitive, and will almost always result in a double "require" if the application code ever requires a library. The "require" for library loading now relies implicitly on the load path (just like normal human-coded requires.)
|
data/Manifest.txt
CHANGED
@@ -2,7 +2,23 @@ History.txt
|
|
2
2
|
Manifest.txt
|
3
3
|
README.txt
|
4
4
|
Rakefile
|
5
|
+
TODO.txt
|
6
|
+
homepage/Notes.txt
|
7
|
+
homepage/Rakefile
|
8
|
+
homepage/diy_example.png
|
9
|
+
homepage/index.erb
|
10
|
+
homepage/index.html
|
11
|
+
homepage/objects_yml.png
|
12
|
+
homepage/page_header.graffle
|
13
|
+
homepage/page_header.html
|
14
|
+
homepage/page_header.png
|
5
15
|
lib/diy.rb
|
16
|
+
sample_code/car.rb
|
17
|
+
sample_code/chassis.rb
|
18
|
+
sample_code/diy_example.rb
|
19
|
+
sample_code/engine.rb
|
20
|
+
sample_code/objects.yml
|
21
|
+
test/constructor.rb
|
6
22
|
test/diy_test.rb
|
7
23
|
test/files/broken_construction.yml
|
8
24
|
test/files/cat/cat.rb
|
@@ -20,6 +36,11 @@ test/files/donkey/foo.rb
|
|
20
36
|
test/files/donkey/foo/bar/qux.rb
|
21
37
|
test/files/fud/objects.yml
|
22
38
|
test/files/fud/toy.rb
|
39
|
+
test/files/functions/invalid_method.yml
|
40
|
+
test/files/functions/nonsingleton_objects.yml
|
41
|
+
test/files/functions/objects.yml
|
42
|
+
test/files/functions/thing.rb
|
43
|
+
test/files/functions/thing_builder.rb
|
23
44
|
test/files/gnu/objects.yml
|
24
45
|
test/files/gnu/thinger.rb
|
25
46
|
test/files/goat/base.rb
|
@@ -32,6 +53,18 @@ test/files/goat/shirt.rb
|
|
32
53
|
test/files/goat/wings.rb
|
33
54
|
test/files/horse/holder_thing.rb
|
34
55
|
test/files/horse/objects.yml
|
56
|
+
test/files/namespace/animal/bird.rb
|
57
|
+
test/files/namespace/animal/cat.rb
|
58
|
+
test/files/namespace/animal/reptile/hardshell/turtle.rb
|
59
|
+
test/files/namespace/animal/reptile/lizard.rb
|
60
|
+
test/files/namespace/bad_module_specified.yml
|
61
|
+
test/files/namespace/class_name_combine.yml
|
62
|
+
test/files/namespace/hello.txt
|
63
|
+
test/files/namespace/no_module_specified.yml
|
64
|
+
test/files/namespace/objects.yml
|
65
|
+
test/files/namespace/road.rb
|
66
|
+
test/files/namespace/sky.rb
|
67
|
+
test/files/namespace/subcontext.yml
|
35
68
|
test/files/non_singleton/air.rb
|
36
69
|
test/files/non_singleton/fat_cat.rb
|
37
70
|
test/files/non_singleton/objects.yml
|
data/README.txt
CHANGED
@@ -182,6 +182,17 @@ a per-object override (handled in the context YAML):
|
|
182
182
|
engine:
|
183
183
|
auto_require: false
|
184
184
|
|
185
|
+
=== Method Directive
|
186
|
+
This introduces the concept of first class methods. An object can now be constructed with a method bound to
|
187
|
+
a particular object in the diy context.
|
188
|
+
|
189
|
+
---
|
190
|
+
trinket_builder:
|
191
|
+
|
192
|
+
method build_trinket:
|
193
|
+
object: trinket_builder
|
194
|
+
method: build
|
195
|
+
|
185
196
|
== LICENSE:
|
186
197
|
|
187
198
|
(The MIT License)
|
data/Rakefile
CHANGED
@@ -16,13 +16,14 @@ Hoe.new('diy', DIY::VERSION) do |p|
|
|
16
16
|
p.extra_deps << ['constructor', '>= 1.0.0']
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
if File.exists?("../tools/")
|
20
|
+
load "../tools/tasks/homepage.rake"
|
21
|
+
load "../tools/tasks/release_tagging.rake"
|
22
|
+
ReleaseTagging.new do |t|
|
23
|
+
t.package = "diy"
|
24
|
+
t.version = DIY::VERSION
|
25
|
+
end
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
t.package = "diy"
|
24
|
-
t.version = DIY::VERSION
|
27
|
+
desc "Release package to Rubyforge, tag the release in svn, and publish documentation"
|
28
|
+
task :release_full => [ :release, :tag_release, :publish_docs ]
|
25
29
|
end
|
26
|
-
|
27
|
-
desc "Release package to Rubyforge, tag the release in svn, and publish documentation"
|
28
|
-
task :release_full => [ :release, :tag_release, :publish_docs ]
|
data/TODO.txt
ADDED
data/homepage/Notes.txt
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Wed Nov 21 21:49:27 EST 2007
|
2
|
+
crosby
|
3
|
+
|
4
|
+
1. Edit page_header.graffle
|
5
|
+
2. Export as HTML imagemap
|
6
|
+
3. Open ../sample_code/synopsis.rb
|
7
|
+
4. Screen shot, save as sample_code.png
|
8
|
+
5. rake (rewrites index.html)
|
9
|
+
6. cd ..
|
10
|
+
7. rake publish_docs
|
11
|
+
|
12
|
+
page_header.graffle
|
13
|
+
Export-as-HTML-Imagemap
|
14
|
+
Use png
|
15
|
+
Use 125% scale
|
16
|
+
Remember to use the style inspector to assign actions to things that should be links.
|
17
|
+
|
18
|
+
rake index
|
19
|
+
Rewrites index.html using index.erb and page_header.html (and some values in the Rakefile)
|
20
|
+
|
21
|
+
The code sample screenshot:
|
22
|
+
Taken with Snapz Pro X (this is important, as Snapz is providing the
|
23
|
+
dropshadow and about 28 extra pixels widthwise)
|
24
|
+
|
25
|
+
Should be 650 px wide to line up with the page header.
|
26
|
+
|
27
|
+
Transparency: be conscious of WHAT'S IN THE BACKGROUND
|
data/homepage/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
desc "Rewrite index.html using index.erb and publisher_homepage.html"
|
2
|
+
task :index do
|
3
|
+
require 'erb'
|
4
|
+
@title = "DIY - atomicobject.rb"
|
5
|
+
@header_html = File.read("page_header.html")
|
6
|
+
html = ERB.new(File.read("index.erb")).result(binding)
|
7
|
+
fname = "index.html"
|
8
|
+
File.open(fname,"w") do |f|
|
9
|
+
f.print html
|
10
|
+
end
|
11
|
+
puts "Wrote #{fname}"
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :index
|
Binary file
|
data/homepage/index.erb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title><%= @title %></title>
|
4
|
+
<style>
|
5
|
+
.code_sample_title {
|
6
|
+
border-top: 1px solid grey;
|
7
|
+
width: 625px;
|
8
|
+
font: bold 12pt Trebuchet MS;
|
9
|
+
text-align:left;
|
10
|
+
margin: 5px;
|
11
|
+
padding-top: 5px;
|
12
|
+
}
|
13
|
+
</style>
|
14
|
+
</head>
|
15
|
+
|
16
|
+
<body>
|
17
|
+
|
18
|
+
<div align="center">
|
19
|
+
|
20
|
+
<%= @header_html %>
|
21
|
+
|
22
|
+
<div class="code_sample_title">
|
23
|
+
objects.yml:
|
24
|
+
</div>
|
25
|
+
<a href="rdoc/index.html"><img border="0" src="objects_yml.png"></a>
|
26
|
+
|
27
|
+
<div class="code_sample_title">
|
28
|
+
diy_example.rb:
|
29
|
+
</div>
|
30
|
+
<a href="rdoc/index.html"><img border="0" src="diy_example.png"></a>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
</body>
|
36
|
+
</html>
|
data/homepage/index.html
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>DIY - atomicobject.rb</title>
|
4
|
+
<style>
|
5
|
+
.code_sample_title {
|
6
|
+
border-top: 1px solid grey;
|
7
|
+
width: 625px;
|
8
|
+
font: bold 12pt Trebuchet MS;
|
9
|
+
text-align:left;
|
10
|
+
margin: 5px;
|
11
|
+
padding-top: 5px;
|
12
|
+
}
|
13
|
+
</style>
|
14
|
+
</head>
|
15
|
+
|
16
|
+
<body>
|
17
|
+
|
18
|
+
<div align="center">
|
19
|
+
|
20
|
+
<map name="GraffleExport">
|
21
|
+
<area shape=rect coords="486,91,635,108" href="http://atomicobjectrb.rubyforge.org/">
|
22
|
+
<area shape=rect coords="485,120,635,187" href="rdoc/index.html">
|
23
|
+
<area shape=rect coords="310,120,463,187" href="http://rubyforge.org/frs/?group_id=4897&release_id=16546">
|
24
|
+
<area shape=rect coords="14,91,206,108" href="http://atomicobject.com">
|
25
|
+
<area shape=rect coords="572,16,627,71" href="http://atomicobjectrb.rubyforge.org/">
|
26
|
+
<area shape=rect coords="21,13,83,75" href="http://atomicobject.com">
|
27
|
+
</map>
|
28
|
+
<img border=0 src="page_header.png" usemap="#GraffleExport">
|
29
|
+
|
30
|
+
|
31
|
+
<div class="code_sample_title">
|
32
|
+
objects.yml:
|
33
|
+
</div>
|
34
|
+
<a href="rdoc/index.html"><img border="0" src="objects_yml.png"></a>
|
35
|
+
|
36
|
+
<div class="code_sample_title">
|
37
|
+
diy_example.rb:
|
38
|
+
</div>
|
39
|
+
<a href="rdoc/index.html"><img border="0" src="diy_example.png"></a>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
</body>
|
45
|
+
</html>
|
Binary file
|
Binary file
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<map name="GraffleExport">
|
2
|
+
<area shape=rect coords="486,91,635,108" href="http://atomicobjectrb.rubyforge.org/">
|
3
|
+
<area shape=rect coords="485,120,635,187" href="rdoc/index.html">
|
4
|
+
<area shape=rect coords="310,120,463,187" href="http://rubyforge.org/frs/?group_id=4897&release_id=16546">
|
5
|
+
<area shape=rect coords="14,91,206,108" href="http://atomicobject.com">
|
6
|
+
<area shape=rect coords="572,16,627,71" href="http://atomicobjectrb.rubyforge.org/">
|
7
|
+
<area shape=rect coords="21,13,83,75" href="http://atomicobject.com">
|
8
|
+
</map>
|
9
|
+
<img border=0 src="page_header.png" usemap="#GraffleExport">
|
Binary file
|
data/lib/diy.rb
CHANGED
@@ -2,7 +2,7 @@ require 'yaml'
|
|
2
2
|
require 'set'
|
3
3
|
|
4
4
|
module DIY #:nodoc:#
|
5
|
-
VERSION = '1.
|
5
|
+
VERSION = '1.1'
|
6
6
|
class Context
|
7
7
|
|
8
8
|
class << self
|
@@ -24,7 +24,7 @@ module DIY #:nodoc:#
|
|
24
24
|
|
25
25
|
# store extra inputs
|
26
26
|
if extra_inputs.kind_of?(Hash)
|
27
|
-
@extra_inputs
|
27
|
+
@extra_inputs= {}
|
28
28
|
extra_inputs.each { |k,v| @extra_inputs[k.to_s] = v } # smooth out the names
|
29
29
|
else
|
30
30
|
@extra_inputs = extra_inputs
|
@@ -62,8 +62,13 @@ module DIY #:nodoc:#
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
unless obj
|
65
|
-
|
66
|
-
|
65
|
+
case @defs[key]
|
66
|
+
when MethodDef
|
67
|
+
@cache[key] = construct_method(key)
|
68
|
+
else
|
69
|
+
obj = construct_object(key)
|
70
|
+
@cache[key] = obj if @defs[key].singleton?
|
71
|
+
end
|
67
72
|
end
|
68
73
|
obj
|
69
74
|
end
|
@@ -130,7 +135,11 @@ module DIY #:nodoc:#
|
|
130
135
|
# namespace: use a module(s) prefix for the classname of contained object defs
|
131
136
|
# NOTE: namespacing is NOT scope... it's just a convenient way to setup class names for a group of objects.
|
132
137
|
get_defs_from info, parse_namespace(name)
|
133
|
-
|
138
|
+
when /^method/
|
139
|
+
key_name = name.gsub(/^method\s/, "")
|
140
|
+
@defs[key_name] = MethodDef.new(:name => key_name,
|
141
|
+
:object => info['object'],
|
142
|
+
:method => info['method'])
|
134
143
|
else
|
135
144
|
# Normal object def
|
136
145
|
info ||= {}
|
@@ -154,14 +163,21 @@ module DIY #:nodoc:#
|
|
154
163
|
end
|
155
164
|
end
|
156
165
|
|
157
|
-
|
166
|
+
|
167
|
+
def construct_method(key)
|
168
|
+
method_definition = @defs[key]
|
169
|
+
object = get_object(method_definition.object)
|
170
|
+
return object.method(method_definition.method)
|
171
|
+
rescue Exception => oops
|
172
|
+
build_and_raise_construction_error(key, oops)
|
173
|
+
end
|
174
|
+
|
158
175
|
def construct_object(key)
|
159
176
|
# Find the object definition
|
160
177
|
obj_def = @defs[key]
|
161
178
|
raise "No object definition for '#{key}'" unless obj_def
|
162
|
-
|
163
179
|
# If object def mentions a library, load it
|
164
|
-
require obj_def.library
|
180
|
+
require obj_def.library if obj_def.library
|
165
181
|
|
166
182
|
# Resolve all components for the object
|
167
183
|
arg_hash = {}
|
@@ -186,11 +202,15 @@ module DIY #:nodoc:#
|
|
186
202
|
return big_c.new
|
187
203
|
end
|
188
204
|
rescue Exception => oops
|
189
|
-
|
205
|
+
build_and_raise_construction_error(key, oops)
|
206
|
+
end
|
207
|
+
|
208
|
+
def build_and_raise_construction_error(key, oops)
|
209
|
+
cerr = ConstructionError.new(key,oops)
|
190
210
|
cerr.set_backtrace(oops.backtrace)
|
191
211
|
raise cerr
|
192
212
|
end
|
193
|
-
|
213
|
+
|
194
214
|
def get_class_for_name_with_module_delimeters(class_name)
|
195
215
|
class_name.split(/::/).inject(Object) do |mod,const_name| mod.const_get(const_name) end
|
196
216
|
end
|
@@ -206,7 +226,7 @@ module DIY #:nodoc:#
|
|
206
226
|
Namespace.new(str)
|
207
227
|
end
|
208
228
|
end
|
209
|
-
|
229
|
+
|
210
230
|
class Namespace #:nodoc:#
|
211
231
|
def initialize(str)
|
212
232
|
# 'using_namespace Animal Reptile'
|
@@ -234,7 +254,15 @@ module DIY #:nodoc:#
|
|
234
254
|
@name = obj_name
|
235
255
|
end
|
236
256
|
end
|
237
|
-
|
257
|
+
|
258
|
+
class MethodDef
|
259
|
+
attr_accessor :name, :object, :method
|
260
|
+
|
261
|
+
def initialize(opts)
|
262
|
+
@name, @object, @method = opts[:name], opts[:object], opts[:method]
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
238
266
|
class ObjectDef #:nodoc:
|
239
267
|
attr_accessor :name, :class_name, :library, :components
|
240
268
|
def initialize(opts)
|
data/sample_code/car.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "diy"
|
3
|
+
|
4
|
+
class Car
|
5
|
+
attr_reader :engine, :chassis
|
6
|
+
def initialize(arg_hash)
|
7
|
+
@engine = arg_hash[:engine]
|
8
|
+
@chassis = arg_hash[:chassis]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Chassis
|
13
|
+
def to_s
|
14
|
+
"Chassis"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Engine
|
19
|
+
def to_s
|
20
|
+
"Engine"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context = DIY::Context.from_file("objects.yml")
|
25
|
+
car = context['car']
|
26
|
+
puts "Car is made of: #{car.engine} and #{car.chassis}"
|
data/test/constructor.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
CONSTRUCTOR_VERSION = '1.0.2' #:nodoc:#
|
2
|
+
|
3
|
+
class Class #:nodoc:#
|
4
|
+
def constructor(*attrs, &block)
|
5
|
+
call_block = ''
|
6
|
+
if block_given?
|
7
|
+
@constructor_block = block
|
8
|
+
call_block = 'self.instance_eval(&self.class.constructor_block)'
|
9
|
+
end
|
10
|
+
# Look for embedded options in the listing:
|
11
|
+
opts = attrs.find { |a| a.kind_of?(Hash) and attrs.delete(a) }
|
12
|
+
do_acc = opts.nil? ? false : opts[:accessors] == true
|
13
|
+
require_args = opts.nil? ? true : opts[:strict] != false
|
14
|
+
super_args = opts.nil? ? nil : opts[:super]
|
15
|
+
|
16
|
+
# Incorporate superclass's constructor keys, if our superclass
|
17
|
+
if superclass.constructor_keys
|
18
|
+
similar_keys = superclass.constructor_keys & attrs
|
19
|
+
raise "Base class already has keys #{similar_keys.inspect}" unless similar_keys.empty?
|
20
|
+
attrs = [attrs,superclass.constructor_keys].flatten
|
21
|
+
end
|
22
|
+
# Generate ivar assigner code lines
|
23
|
+
assigns = ''
|
24
|
+
attrs.each do |k|
|
25
|
+
assigns += "@#{k.to_s} = args[:#{k.to_s}]\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
# If accessors option is on, declare accessors for the attributes:
|
29
|
+
if do_acc
|
30
|
+
self.class_eval "attr_accessor " + attrs.map {|x| ":#{x.to_s}"}.join(',')
|
31
|
+
end
|
32
|
+
|
33
|
+
# If user supplied super-constructor hints:
|
34
|
+
super_call = ''
|
35
|
+
if super_args
|
36
|
+
list = super_args.map do |a|
|
37
|
+
case a
|
38
|
+
when String
|
39
|
+
%|"#{a}"|
|
40
|
+
when Symbol
|
41
|
+
%|:#{a}|
|
42
|
+
end
|
43
|
+
end
|
44
|
+
super_call = %|super(#{list.join(',')})|
|
45
|
+
end
|
46
|
+
|
47
|
+
# If strict is on, define the constructor argument validator method,
|
48
|
+
# and setup the initializer to invoke the validator method.
|
49
|
+
# Otherwise, insert lax code into the initializer.
|
50
|
+
validation_code = "return if args.nil?"
|
51
|
+
if require_args
|
52
|
+
self.class_eval do
|
53
|
+
def _validate_constructor_args(args)
|
54
|
+
# First, make sure we've got args of some kind
|
55
|
+
unless args and args.keys and args.keys.size > 0
|
56
|
+
raise ConstructorArgumentError.new(self.class.constructor_keys)
|
57
|
+
end
|
58
|
+
# Scan for missing keys in the argument hash
|
59
|
+
a_keys = args.keys
|
60
|
+
missing = []
|
61
|
+
self.class.constructor_keys.each do |ck|
|
62
|
+
unless a_keys.member?(ck)
|
63
|
+
missing << ck
|
64
|
+
end
|
65
|
+
a_keys.delete(ck) # Delete inbound keys as we address them
|
66
|
+
end
|
67
|
+
if missing.size > 0 || a_keys.size > 0
|
68
|
+
raise ConstructorArgumentError.new(missing,a_keys)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# Setup the code to insert into the initializer:
|
73
|
+
validation_code = "_validate_constructor_args args "
|
74
|
+
end
|
75
|
+
|
76
|
+
# Generate the initializer code
|
77
|
+
self.class_eval %{
|
78
|
+
def initialize(args=nil)
|
79
|
+
#{super_call}
|
80
|
+
#{validation_code}
|
81
|
+
#{assigns}
|
82
|
+
setup if respond_to?(:setup)
|
83
|
+
#{call_block}
|
84
|
+
end
|
85
|
+
}
|
86
|
+
|
87
|
+
# Remember our constructor keys
|
88
|
+
@_ctor_keys = attrs
|
89
|
+
end
|
90
|
+
|
91
|
+
# Access the constructor keys for this class
|
92
|
+
def constructor_keys; @_ctor_keys ||=[]; end
|
93
|
+
|
94
|
+
def constructor_block #:nodoc:#
|
95
|
+
@constructor_block
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
# Fancy validation exception, based on missing and extraneous keys.
|
101
|
+
class ConstructorArgumentError < RuntimeError #:nodoc:#
|
102
|
+
def initialize(missing,rejected=[])
|
103
|
+
err_msg = ''
|
104
|
+
if missing.size > 0
|
105
|
+
err_msg = "Missing constructor args [#{missing.join(',')}]"
|
106
|
+
end
|
107
|
+
if rejected.size > 0
|
108
|
+
# Some inbound keys were not addressed earlier; this means they're unwanted
|
109
|
+
if err_msg
|
110
|
+
err_msg << "; " # Appending to earlier message about missing items
|
111
|
+
else
|
112
|
+
err_msg = ''
|
113
|
+
end
|
114
|
+
# Enumerate the rejected key names
|
115
|
+
err_msg << "Rejected constructor args [#{rejected.join(',')}]"
|
116
|
+
end
|
117
|
+
super err_msg
|
118
|
+
end
|
119
|
+
end
|
data/test/diy_test.rb
CHANGED
@@ -7,7 +7,7 @@ class DIYTest < Test::Unit::TestCase
|
|
7
7
|
|
8
8
|
def setup
|
9
9
|
# Add load paths:
|
10
|
-
%w|gnu dog cat yak donkey goat horse fud non_singleton namespace|.each do |p|
|
10
|
+
%w|gnu dog cat yak donkey goat horse fud non_singleton namespace functions|.each do |p|
|
11
11
|
libdir = path_to_test_file(p)
|
12
12
|
$: << libdir unless $:.member?(libdir)
|
13
13
|
end
|
@@ -74,7 +74,7 @@ class DIYTest < Test::Unit::TestCase
|
|
74
74
|
@diy.build_everything
|
75
75
|
assert_not_nil @diy['foo/bar/qux'], "Should have got my qux (which is hiding in a couple modules)"
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def test_keys
|
79
79
|
load_context "dog/simple.yml"
|
80
80
|
assert_equal %w|dog_model dog_presenter dog_view file_resolver other_thing|, @diy.keys.sort
|
@@ -492,7 +492,7 @@ class DIYTest < Test::Unit::TestCase
|
|
492
492
|
assert_same sky, bird.sky, "Bird has wrong Sky"
|
493
493
|
assert_same bird, lizard.bird, "Lizard has wrong Bird"
|
494
494
|
end
|
495
|
-
|
495
|
+
|
496
496
|
def test_should_combine_a_given_class_name_with_the_namespace
|
497
497
|
load_context "namespace/class_name_combine.yml"
|
498
498
|
assert_not_nil @diy['garfield'], "No garfield"
|
@@ -533,6 +533,44 @@ class DIYTest < Test::Unit::TestCase
|
|
533
533
|
assert_match(/no such file to load -- fuzzy_creature\/bird/, ex.message)
|
534
534
|
end
|
535
535
|
|
536
|
+
def test_should_be_able_define_and_access_bounded_methods
|
537
|
+
load_context "functions/objects.yml"
|
538
|
+
@diy.build_everything
|
539
|
+
build_thing = @diy['build_thing']
|
540
|
+
|
541
|
+
assert_not_nil build_thing, "should not be nil"
|
542
|
+
assert_kind_of(Method, build_thing)
|
543
|
+
assert_same(build_thing, @diy['build_thing'])
|
544
|
+
end
|
545
|
+
|
546
|
+
def test_bounded_method_can_be_used
|
547
|
+
load_context "functions/objects.yml"
|
548
|
+
@diy.build_everything
|
549
|
+
build_thing = @diy['build_thing']
|
550
|
+
|
551
|
+
thing = build_thing["the name", "flying"]
|
552
|
+
|
553
|
+
assert_equal("the name", thing.name)
|
554
|
+
assert_equal("flying", thing.ability)
|
555
|
+
end
|
556
|
+
|
557
|
+
def test_building_bounded_method_uses_object_in_diy_context_correctly
|
558
|
+
load_context "functions/objects.yml"
|
559
|
+
@diy.build_everything
|
560
|
+
assert_equal(@diy['build_thing'], @diy['thing_builder'].method(:build))
|
561
|
+
|
562
|
+
load_context "functions/nonsingleton_objects.yml"
|
563
|
+
@diy.build_everything
|
564
|
+
assert_not_equal(@diy['build_thing'], @diy['thing_builder'].method(:build))
|
565
|
+
end
|
566
|
+
|
567
|
+
def test_raises_construction_error_if_invalid_method_specified
|
568
|
+
load_context "functions/invalid_method.yml"
|
569
|
+
assert_raises DIY::ConstructionError do
|
570
|
+
@diy.build_everything
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
536
574
|
#
|
537
575
|
# HELPERS
|
538
576
|
#
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'thing'
|
2
|
+
|
3
|
+
class ThingBuilder
|
4
|
+
@@builder_count = 0
|
5
|
+
|
6
|
+
def self.reset_builder_count
|
7
|
+
@@builder_count = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.builder_count
|
11
|
+
@@builder_count
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@@builder_count += 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def build(name, ability)
|
19
|
+
Thing.new(:name => name, :ability => ability)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
this is the info
|
@@ -0,0 +1,22 @@
|
|
1
|
+
road:
|
2
|
+
|
3
|
+
sky:
|
4
|
+
|
5
|
+
using_namespace Animal:
|
6
|
+
|
7
|
+
cat:
|
8
|
+
compose: road
|
9
|
+
|
10
|
+
|
11
|
+
+aviary:
|
12
|
+
using_namespace Animal:
|
13
|
+
bird:
|
14
|
+
compose: sky
|
15
|
+
|
16
|
+
using_namespace Animal Reptile:
|
17
|
+
lizard:
|
18
|
+
compose: bird
|
19
|
+
|
20
|
+
using_namespace Animal::Reptile::Hardshell:
|
21
|
+
turtle:
|
22
|
+
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
platform:
|
4
|
+
version: "1.1"
|
5
|
+
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atomic Object
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2008-05-20 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version: 1.
|
31
|
+
version: 1.5.1
|
32
32
|
version:
|
33
33
|
description: "== DESCRIPTION: DIY (Dependency Injection in YAML) is a simple dependency injection library which focuses on declarative composition of objects through constructor injection. == INSTALL: * gem install diy"
|
34
34
|
email: dev@atomicobject.com
|
@@ -40,12 +40,31 @@ extra_rdoc_files:
|
|
40
40
|
- History.txt
|
41
41
|
- Manifest.txt
|
42
42
|
- README.txt
|
43
|
+
- TODO.txt
|
44
|
+
- homepage/Notes.txt
|
45
|
+
- test/files/namespace/hello.txt
|
43
46
|
files:
|
44
47
|
- History.txt
|
45
48
|
- Manifest.txt
|
46
49
|
- README.txt
|
47
50
|
- Rakefile
|
51
|
+
- TODO.txt
|
52
|
+
- homepage/Notes.txt
|
53
|
+
- homepage/Rakefile
|
54
|
+
- homepage/diy_example.png
|
55
|
+
- homepage/index.erb
|
56
|
+
- homepage/index.html
|
57
|
+
- homepage/objects_yml.png
|
58
|
+
- homepage/page_header.graffle
|
59
|
+
- homepage/page_header.html
|
60
|
+
- homepage/page_header.png
|
48
61
|
- lib/diy.rb
|
62
|
+
- sample_code/car.rb
|
63
|
+
- sample_code/chassis.rb
|
64
|
+
- sample_code/diy_example.rb
|
65
|
+
- sample_code/engine.rb
|
66
|
+
- sample_code/objects.yml
|
67
|
+
- test/constructor.rb
|
49
68
|
- test/diy_test.rb
|
50
69
|
- test/files/broken_construction.yml
|
51
70
|
- test/files/cat/cat.rb
|
@@ -63,6 +82,11 @@ files:
|
|
63
82
|
- test/files/donkey/foo/bar/qux.rb
|
64
83
|
- test/files/fud/objects.yml
|
65
84
|
- test/files/fud/toy.rb
|
85
|
+
- test/files/functions/invalid_method.yml
|
86
|
+
- test/files/functions/nonsingleton_objects.yml
|
87
|
+
- test/files/functions/objects.yml
|
88
|
+
- test/files/functions/thing.rb
|
89
|
+
- test/files/functions/thing_builder.rb
|
66
90
|
- test/files/gnu/objects.yml
|
67
91
|
- test/files/gnu/thinger.rb
|
68
92
|
- test/files/goat/base.rb
|
@@ -75,6 +99,18 @@ files:
|
|
75
99
|
- test/files/goat/wings.rb
|
76
100
|
- test/files/horse/holder_thing.rb
|
77
101
|
- test/files/horse/objects.yml
|
102
|
+
- test/files/namespace/animal/bird.rb
|
103
|
+
- test/files/namespace/animal/cat.rb
|
104
|
+
- test/files/namespace/animal/reptile/hardshell/turtle.rb
|
105
|
+
- test/files/namespace/animal/reptile/lizard.rb
|
106
|
+
- test/files/namespace/bad_module_specified.yml
|
107
|
+
- test/files/namespace/class_name_combine.yml
|
108
|
+
- test/files/namespace/hello.txt
|
109
|
+
- test/files/namespace/no_module_specified.yml
|
110
|
+
- test/files/namespace/objects.yml
|
111
|
+
- test/files/namespace/road.rb
|
112
|
+
- test/files/namespace/sky.rb
|
113
|
+
- test/files/namespace/subcontext.yml
|
78
114
|
- test/files/non_singleton/air.rb
|
79
115
|
- test/files/non_singleton/fat_cat.rb
|
80
116
|
- test/files/non_singleton/objects.yml
|
@@ -117,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
153
|
requirements: []
|
118
154
|
|
119
155
|
rubyforge_project: atomicobjectrb
|
120
|
-
rubygems_version:
|
156
|
+
rubygems_version: 1.1.1
|
121
157
|
signing_key:
|
122
158
|
specification_version: 2
|
123
159
|
summary: Constructor-based dependency injection container using YAML input.
|