lumberjack-dsl 0.0.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/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +19 -0
- data/README.markdown +57 -0
- data/Rakefile +8 -0
- data/examples/people.rb +5 -0
- data/lumberjack.gemspec +19 -0
- data/lumberjack.rb +153 -0
- data/lumberjack_spec.rb +311 -0
- metadata +72 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2007-2008 Ryan Allen, FlashDen Pty Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
Lumberjack is best summed up as a generic DSL for constructing object trees.
|
2
|
+
|
3
|
+
It works great for configuration files, for generating a tree of configuration
|
4
|
+
objects for later reflection or what-not. But in reality you could use it for
|
5
|
+
whatever you're willing to dream up.
|
6
|
+
|
7
|
+
I apologise for the lack of documentation :) Below is a code example to get you
|
8
|
+
started, any questions, shoot me a message!
|
9
|
+
|
10
|
+
Now, that code example:
|
11
|
+
|
12
|
+
require 'lumberjack'
|
13
|
+
|
14
|
+
class Person
|
15
|
+
|
16
|
+
attr_accessor :age, :gripes, :chums
|
17
|
+
|
18
|
+
def initialize(name)
|
19
|
+
@name = name
|
20
|
+
@gripes = []
|
21
|
+
@chums = []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Gripe
|
26
|
+
def initialize(desc)
|
27
|
+
@desc = desc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
tree = Lumberjack.construct do
|
32
|
+
|
33
|
+
# we're in list / instanciate object scope
|
34
|
+
|
35
|
+
@john = person 'John (is a doondy head)' do
|
36
|
+
# we instanticated an object, so now we're in attr assignment scope
|
37
|
+
age 12 # this is equiv to @john.age = 12
|
38
|
+
gripes do # open up a colection on john...
|
39
|
+
# now we're back in list / instanticate object scope
|
40
|
+
gripe 'untested code' # creating a gripe
|
41
|
+
gripe 'no beer' # and another
|
42
|
+
end # out of gripes, back to john attr assignment
|
43
|
+
end # out of john
|
44
|
+
|
45
|
+
# we're back to creating people:
|
46
|
+
|
47
|
+
person 'Ryan' do
|
48
|
+
age 25
|
49
|
+
end
|
50
|
+
|
51
|
+
person 'Tim' do
|
52
|
+
age 'Infinite'
|
53
|
+
chums @john # instance vars are shared across Lumberjack.construct
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
puts tree.inspect
|
data/Rakefile
ADDED
data/examples/people.rb
ADDED
data/lumberjack.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = "lumberjack-dsl"
|
4
|
+
s.version = "0.0.1"
|
5
|
+
s.authors = ["Ryan Allen", "Steve Hodgkiss", "John Barton", "James Dowling"]
|
6
|
+
s.email = ["ryan@yeahnah.org", "steve@hodgkiss.me", "jrbarton@gmail.com", "jamesd741@gmail.com"]
|
7
|
+
s.homepage = ""
|
8
|
+
s.summary = %q{Lumberjack is best summed up as a generic DSL for constructing object trees.}
|
9
|
+
s.description = %q{}
|
10
|
+
|
11
|
+
s.rubyforge_project = "lumberjack-dsl"
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["."]
|
17
|
+
|
18
|
+
s.add_development_dependency "rspec"
|
19
|
+
end
|
data/lumberjack.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
class Lumberjack
|
2
|
+
|
3
|
+
def self.construct(initial_scope = [], &block)
|
4
|
+
builder = new(initial_scope)
|
5
|
+
builder.__process(block)
|
6
|
+
end
|
7
|
+
|
8
|
+
@@methods_to_keep = /^__/, /class/, /instance_eval/, /method_missing/,
|
9
|
+
/instance_variable_(g|s)et/, /instance_variables/, /inspect/, /send/,
|
10
|
+
/^object_id/, /^respond_to/
|
11
|
+
|
12
|
+
instance_methods.each do |m|
|
13
|
+
undef_method m unless @@methods_to_keep.find { |r| r.match m }
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(initial_scope)
|
17
|
+
@initial_scope = initial_scope
|
18
|
+
@scope_stack ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def __process(block)
|
22
|
+
@scope = [@initial_scope]
|
23
|
+
instance_eval(&block) if block
|
24
|
+
tree
|
25
|
+
rescue
|
26
|
+
raise $!
|
27
|
+
end
|
28
|
+
|
29
|
+
# syntatic sugar for scope resolution
|
30
|
+
def /(ignore_me)
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_tree_file(filename)
|
35
|
+
File.open filename, 'r' do |f|
|
36
|
+
eval f.read, binding, __FILE__, __LINE__
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def shared_branch(branch_name, &block)
|
41
|
+
instance_variable_set "@#{branch_name}", lambda(&block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def graft_branch(branch_name)
|
45
|
+
branch = instance_variable_get("@#{branch_name}")
|
46
|
+
raise "Attemption to graft branch #{branch_name} which is undefined" unless branch
|
47
|
+
instance_eval(&branch)
|
48
|
+
end
|
49
|
+
|
50
|
+
def prune(method, value)
|
51
|
+
current_scope.delete_if do |twig|
|
52
|
+
twig.respond_to?(method) && twig.send(method) == value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(*args, &block)
|
57
|
+
if still_modifying_scope?(args, block)
|
58
|
+
@scope_stack << args.first
|
59
|
+
else
|
60
|
+
assign_to_current_scope(args, block)
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def assign_to_current_scope(args, block)
|
68
|
+
if current_scope.respond_to?(:<<)
|
69
|
+
assign_to_array_with(args, block)
|
70
|
+
else
|
71
|
+
assign_to_instance_with(args, block)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def assign_to_instance_with(args, block)
|
76
|
+
accessor = args.shift
|
77
|
+
if accessor.to_s[-1].chr == '!'
|
78
|
+
# create class based on the accessor name
|
79
|
+
assign_subvalues_to_instance(accessor, args, block)
|
80
|
+
elsif block and args.empty?
|
81
|
+
# accessor is to refer to an array
|
82
|
+
current_array_instance = get_accessor_value(accessor)
|
83
|
+
evaluate_block_within_context(current_array_instance, block)
|
84
|
+
elsif args.length == 1
|
85
|
+
# splat to avoid array and directly assign the argument
|
86
|
+
current_scope.send("#{accessor}=", *args)
|
87
|
+
else
|
88
|
+
# assign array
|
89
|
+
current_scope.send("#{accessor}=", args)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def assign_to_array_with(args, block)
|
94
|
+
klass = args.shift
|
95
|
+
instance = build_class(klass, args)
|
96
|
+
current_scope << instance # add this instance to the scoped Array
|
97
|
+
evaluate_block_within_context(instance, block) if block
|
98
|
+
end
|
99
|
+
|
100
|
+
def assign_subvalues_to_instance(accessor, args, block)
|
101
|
+
accessor_class = accessor.to_s[0...-1]
|
102
|
+
instance = build_class(accessor_class, args)
|
103
|
+
instance.parent = current_scope if instance.respond_to?(:parent=)
|
104
|
+
current_scope.send("#{accessor_class}=", instance)
|
105
|
+
evaluate_block_within_context(instance, block) if block
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_class(klass, args)
|
109
|
+
@scope_stack << klass
|
110
|
+
scoped_class = @scope_stack.join('/')
|
111
|
+
@scope_stack = []
|
112
|
+
classify(scoped_class).new(*args)
|
113
|
+
end
|
114
|
+
|
115
|
+
def evaluate_block_within_context(accessor, block)
|
116
|
+
@scope.push accessor
|
117
|
+
instance_eval(&block)
|
118
|
+
@scope.pop
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_accessor_value(accessor)
|
122
|
+
if current_scope.send("#{accessor}").nil?
|
123
|
+
current_scope.send("#{accessor}=", [])
|
124
|
+
end
|
125
|
+
current_scope.send("#{accessor}")
|
126
|
+
end
|
127
|
+
|
128
|
+
def still_modifying_scope?(args, block)
|
129
|
+
# if we only have one arg, and no block, then we're trying to build a
|
130
|
+
# module scope, i.e. a/b/c/d would resolve to A::B::C::D,
|
131
|
+
args.length == 1 && block.nil?
|
132
|
+
end
|
133
|
+
|
134
|
+
def current_scope
|
135
|
+
@scope.last
|
136
|
+
end
|
137
|
+
|
138
|
+
def tree
|
139
|
+
@scope.first
|
140
|
+
end
|
141
|
+
|
142
|
+
# Turns an underscored path into the class it represents
|
143
|
+
#
|
144
|
+
# Usage: classify("some/cool_klass") => Some::CoolKlass
|
145
|
+
def classify(class_name)
|
146
|
+
klass = class_name.split('/').collect do |component|
|
147
|
+
camels = component.split('_')
|
148
|
+
camels.collect { |c| c.capitalize }.join
|
149
|
+
end.join('::')
|
150
|
+
eval("::#{klass}")
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
data/lumberjack_spec.rb
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require
|
3
|
+
$: << '.'
|
4
|
+
require 'lumberjack'
|
5
|
+
|
6
|
+
class Family
|
7
|
+
attr_accessor :name, :members, :heritage
|
8
|
+
def initialize(name = nil, args = {})
|
9
|
+
@name = name
|
10
|
+
args.each { |k,v| send "#{k}=", v }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Person
|
15
|
+
attr_accessor :given_name, :age
|
16
|
+
def initialize(name = nil, age = nil)
|
17
|
+
@given_name, @age = name, age
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Showroom < Array
|
22
|
+
end
|
23
|
+
|
24
|
+
class Vehicle
|
25
|
+
class Heavy < Vehicle
|
26
|
+
class ReallyHeavy < Heavy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
attr_accessor :name, :wheels, :person
|
30
|
+
def initialize(args = {:name => 'A Car, ya mum'})
|
31
|
+
@name = args[:name]
|
32
|
+
@wheels = SetOfWheels.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class SetOfWheels < Array
|
37
|
+
end
|
38
|
+
|
39
|
+
class Wheel
|
40
|
+
attr_accessor :wear
|
41
|
+
def initialize(args)
|
42
|
+
@wear = args[:wear]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe Lumberjack do
|
47
|
+
|
48
|
+
it 'construct returns an empty list' do
|
49
|
+
Lumberjack.construct.should be_empty
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'testcan create a single class' do
|
53
|
+
tree = Lumberjack.construct do
|
54
|
+
family {} # api change w/ scoping requires a block to be passed, otherwise can't tell if you're
|
55
|
+
# trying to resolve a nested scope
|
56
|
+
end
|
57
|
+
tree.length.should eq 1
|
58
|
+
tree.first.should be_instance_of Family
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'test can create a single class passing in args' do
|
62
|
+
tree = Lumberjack.construct do
|
63
|
+
family 'Allen', :heritage => :mixed
|
64
|
+
end
|
65
|
+
tree.length.should eq 1
|
66
|
+
tree.first.should be_instance_of Family
|
67
|
+
tree.first.name.should eq 'Allen'
|
68
|
+
tree.first.heritage.should eq :mixed
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'can create two classes passing in args' do
|
72
|
+
tree = Lumberjack.construct do
|
73
|
+
family 'Allen', :heritage => [:english, :irish]
|
74
|
+
family 'Ta\'eed', :heritage => [:iranian, :english]
|
75
|
+
end
|
76
|
+
tree.length.should eq 2
|
77
|
+
tree[0].should be_instance_of Family
|
78
|
+
tree[0].name.should eq 'Allen'
|
79
|
+
tree[0].heritage.should eq [:english, :irish]
|
80
|
+
tree[1].should be_instance_of Family
|
81
|
+
tree[1].name.should eq 'Ta\'eed'
|
82
|
+
tree[1].heritage.should eq [:iranian, :english]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'can set instance members with block' do
|
86
|
+
tree = Lumberjack.construct do
|
87
|
+
family do
|
88
|
+
name 'Allen'
|
89
|
+
heritage [:english, :irish]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
tree.length.should eq 1
|
93
|
+
tree[0].should be_instance_of Family
|
94
|
+
tree[0].name.should eq 'Allen'
|
95
|
+
tree[0].heritage.should eq [:english, :irish]
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'can used mixed constructor and instance members in_blocke' do
|
99
|
+
tree = Lumberjack.construct do
|
100
|
+
family 'Allen' do
|
101
|
+
heritage [:english, :irish]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
tree.length.should eq 1
|
105
|
+
tree[0].should be_instance_of Family
|
106
|
+
tree[0].name.should eq 'Allen'
|
107
|
+
tree[0].heritage.should eq [:english, :irish]
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'create list in scoped instance if block with no args' do
|
111
|
+
tree = Lumberjack.construct do
|
112
|
+
family 'Allen' do
|
113
|
+
heritage [:english, :irish]
|
114
|
+
members do # working from here
|
115
|
+
person 'Tim', 58
|
116
|
+
person 'Jan', 54
|
117
|
+
person 'Ryan' do
|
118
|
+
age 24
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
tree.length.should eq 1
|
124
|
+
tree[0].should be_instance_of Family
|
125
|
+
tree[0].name.should eq 'Allen'
|
126
|
+
tree[0].heritage.should eq [:english, :irish]
|
127
|
+
tree[0].members.length.should eq 3
|
128
|
+
tree[0].members[0].given_name.should eq 'Tim'
|
129
|
+
tree[0].members[0].age.should eq 58
|
130
|
+
tree[0].members[1].given_name.should eq 'Jan'
|
131
|
+
tree[0].members[1].age.should eq 54
|
132
|
+
tree[0].members[2].given_name.should eq 'Ryan'
|
133
|
+
tree[0].members[2].age.should eq 24
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'can take generate arrays with comma semantics and tell the difference' do
|
137
|
+
tree = Lumberjack.construct do
|
138
|
+
family 'Allen' do
|
139
|
+
heritage :english, :irish
|
140
|
+
end
|
141
|
+
end
|
142
|
+
tree[0].heritage.should eq [:english, :irish]
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'will_push element onto object if list accessor is already initialized' do
|
146
|
+
vehicles = Lumberjack.construct do
|
147
|
+
vehicle :name => 'unicycle' do
|
148
|
+
wheels do
|
149
|
+
wheel :wear => 'bald'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
vehicles[0].wheels.should be_instance_of SetOfWheels
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'can set initial context to something else besdies an array' do
|
157
|
+
showroom = Lumberjack.construct Showroom.new do
|
158
|
+
vehicle :name => 'a FERRARRI!!!1'
|
159
|
+
vehicle :name => 'a MASERATI!!!1'
|
160
|
+
vehicle :name => 'a PORCHE OMG!!!'
|
161
|
+
end
|
162
|
+
showroom.should be_instance_of Showroom
|
163
|
+
showroom.length.should eq 3
|
164
|
+
end
|
165
|
+
|
166
|
+
# biggest hack ever, use a ! to isntanciate a class to an accessor, must be
|
167
|
+
# inferable by the accessor name, such a large hack, but we need it for
|
168
|
+
# production, and i'm sure other people will need it, so lets leave this
|
169
|
+
# gaping flaw of lumberjack for the time being till we can think of something
|
170
|
+
# more nice and appropriate :/ :D
|
171
|
+
it 'can create instance of class via bang method' do
|
172
|
+
cars = Lumberjack.construct do
|
173
|
+
vehicle :name => 'Prius (are owned by rich hippies)' do
|
174
|
+
person! 'Ryan' do # i so put my foot in here, i'm not a rich hippy!
|
175
|
+
age 25
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
eval('Vehicle').should eq Vehicle
|
180
|
+
cars[0].class.should eq Vehicle
|
181
|
+
cars[0].name.should eq 'Prius (are owned by rich hippies)'
|
182
|
+
cars[0].person.should be_instance_of Person
|
183
|
+
cars[0].person.age.should eq 25
|
184
|
+
cars[0].person.given_name.should eq 'Ryan'
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'can create list of primitives' do # not sure this is valid useage (of course it is you big dummy ryan from the past!)
|
188
|
+
tree = Lumberjack.construct do
|
189
|
+
array [:one, :two, :three]
|
190
|
+
array [:four, :five, :six]
|
191
|
+
end
|
192
|
+
tree.should eq [[:one, :two, :three], [:four, :five, :six]]
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'we got backslashes that resolve scope or something' do
|
196
|
+
cars = Lumberjack.construct do
|
197
|
+
vehicle :name => 'Normal Car'
|
198
|
+
# unfortunatley we need to use parantehseshtheses here :(
|
199
|
+
vehicle/heavy(:name => 'Heavy Car')
|
200
|
+
vehicle/heavy/really_heavy(:name => 'Really Heavy Heavy Car')
|
201
|
+
end
|
202
|
+
cars[0].should be_instance_of Vehicle
|
203
|
+
cars[1].should be_instance_of Vehicle::Heavy
|
204
|
+
cars[2].should be_instance_of Vehicle::Heavy::ReallyHeavy
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'we can load in other files' do
|
208
|
+
family = Lumberjack.construct do
|
209
|
+
family 'Barton' do
|
210
|
+
heritage [:dutch, :mongrel_aussie]
|
211
|
+
members do
|
212
|
+
load_tree_file 'examples/people.rb'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
family.length.should eq 1
|
218
|
+
family.first.should be_instance_of Family
|
219
|
+
family.first.name.should eq 'Barton'
|
220
|
+
family.first.heritage.should eq [:dutch, :mongrel_aussie]
|
221
|
+
|
222
|
+
family.first.members.size.should eq 5
|
223
|
+
|
224
|
+
family.first.members.first.given_name.should eq 'John S'
|
225
|
+
family.first.members.first.age.should eq 50
|
226
|
+
|
227
|
+
family.first.members.last.given_name.should eq 'Ethan'
|
228
|
+
family.first.members.last.age.should eq 10
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'we can share branches that are defined' do
|
232
|
+
families = Lumberjack.construct do
|
233
|
+
|
234
|
+
shared_branch :kids do
|
235
|
+
person 'Jack', 11
|
236
|
+
person 'Jill', 10
|
237
|
+
end
|
238
|
+
|
239
|
+
family "Dad's new family" do
|
240
|
+
members do
|
241
|
+
person 'Dad', 45
|
242
|
+
graft_branch :kids
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
family "Mum's new family" do
|
247
|
+
members do
|
248
|
+
person 'Mum', 40
|
249
|
+
person 'Red-headed step-child', 8
|
250
|
+
graft_branch :kids
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
families.length.should eq 2
|
256
|
+
families[0].should be_instance_of Family
|
257
|
+
families[1].should be_instance_of Family
|
258
|
+
|
259
|
+
families[0].members.size.should eq 3
|
260
|
+
families[0].members.any? {|m| m.given_name == 'Jack'}.should be_true
|
261
|
+
families[0].members.any? {|m| m.given_name == 'Jill'}.should be_true
|
262
|
+
|
263
|
+
families[1].members.size.should eq 4
|
264
|
+
families[1].members.any? {|m| m.given_name == 'Jack'}.should be_true
|
265
|
+
families[1].members.any? {|m| m.given_name == 'Jill'}.should be_true
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'we can remove twigs with prune' do
|
269
|
+
families = Lumberjack.construct do
|
270
|
+
|
271
|
+
shared_branch :kids do
|
272
|
+
person 'Jack', 12
|
273
|
+
person 'Jane', 10
|
274
|
+
person 'Bob', 10
|
275
|
+
end
|
276
|
+
|
277
|
+
shared_branch :update_kids do
|
278
|
+
prune :age, 10
|
279
|
+
person 'Will', 11
|
280
|
+
end
|
281
|
+
|
282
|
+
family "Dad's family" do
|
283
|
+
members do
|
284
|
+
person 'Dad', 45
|
285
|
+
person 'Mum', 49
|
286
|
+
prune :given_name, 'Mum'
|
287
|
+
person 'Mum', 26
|
288
|
+
|
289
|
+
graft_branch :kids
|
290
|
+
graft_branch :update_kids
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
families[0].members.any? {|m| m.given_name == 'Will' && m.age == 11}.should be_true
|
296
|
+
families[0].members.any? {|m| m.given_name == 'Jack' && m.age == 12}.should be_true
|
297
|
+
families[0].members.any? {|m| m.given_name == 'Mum' && m.age == 26}.should be_true
|
298
|
+
families[0].members.any? {|m| m.given_name == 'Dad' && m.age == 45}.should be_true
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'doesnt share branches that are undefined' do
|
302
|
+
# TODO: why does this output funny stuff
|
303
|
+
expect {
|
304
|
+
Lumberjack.construct do
|
305
|
+
family 'wont work' do
|
306
|
+
graft_branch :non_existant
|
307
|
+
end
|
308
|
+
end
|
309
|
+
}.to raise_error RuntimeError
|
310
|
+
end
|
311
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lumberjack-dsl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Allen
|
9
|
+
- Steve Hodgkiss
|
10
|
+
- John Barton
|
11
|
+
- James Dowling
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
date: 2012-03-13 00:00:00.000000000 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: rspec
|
19
|
+
requirement: &70259449806300 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ! '>='
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '0'
|
25
|
+
type: :development
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: *70259449806300
|
28
|
+
description: ''
|
29
|
+
email:
|
30
|
+
- ryan@yeahnah.org
|
31
|
+
- steve@hodgkiss.me
|
32
|
+
- jrbarton@gmail.com
|
33
|
+
- jamesd741@gmail.com
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- .rspec
|
40
|
+
- Gemfile
|
41
|
+
- MIT-LICENSE
|
42
|
+
- README.markdown
|
43
|
+
- Rakefile
|
44
|
+
- examples/people.rb
|
45
|
+
- lumberjack.gemspec
|
46
|
+
- lumberjack.rb
|
47
|
+
- lumberjack_spec.rb
|
48
|
+
homepage: ''
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- .
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project: lumberjack-dsl
|
68
|
+
rubygems_version: 1.8.11
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Lumberjack is best summed up as a generic DSL for constructing object trees.
|
72
|
+
test_files: []
|