doodle 0.1.9 → 0.2.0
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 +29 -10
- data/Manifest.txt +12 -0
- data/README.txt +5 -4
- data/lib/doodle.rb +227 -112
- data/lib/doodle/app.rb +25 -21
- data/lib/doodle/version.rb +2 -2
- data/lib/doodle/xml.rb +175 -0
- data/spec/arg_order_spec.rb +1 -1
- data/spec/block_init_spec.rb +1 -1
- data/spec/bugs_spec.rb +61 -29
- data/spec/collector_spec.rb +92 -25
- data/spec/defaults_spec.rb +13 -0
- data/spec/doodle_context_spec.rb +1 -1
- data/spec/doodle_spec.rb +4 -14
- data/spec/equality_spec.rb +118 -0
- data/spec/modules_spec.rb +67 -0
- data/spec/serialization_spec.rb +3 -3
- data/spec/spec.template +16 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/to_hash_spec.rb +12 -2
- data/spec/validation2_spec.rb +10 -10
- data/spec/validation_spec.rb +1 -1
- data/spec/xml_spec.rb +219 -0
- metadata +17 -2
data/spec/collector_spec.rb
CHANGED
@@ -14,11 +14,11 @@ describe Doodle, "Default collector" do
|
|
14
14
|
after :each do
|
15
15
|
remove_ivars :foo
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
it "should define a collector method :item" do
|
19
19
|
@foo.methods.map{ |x| x.to_sym }.include?(:item).should_be true
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
it "should collect items into attribute :list" do
|
23
23
|
@foo.list.should_be ["Hello", "World"]
|
24
24
|
end
|
@@ -40,11 +40,11 @@ describe Doodle, "Simple collector" do
|
|
40
40
|
after :each do
|
41
41
|
remove_ivars :foo
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
it "should define a collector method :item" do
|
45
45
|
@foo.methods.map{ |x| x.to_sym }.include?(:item).should_be true
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
it "should collect items into attribute :list" do
|
49
49
|
@foo.list.should_be ["Hello", "World"]
|
50
50
|
end
|
@@ -55,11 +55,11 @@ end
|
|
55
55
|
describe Doodle, "Typed collector with default collector name" do
|
56
56
|
temporary_constant :Event, :Location do
|
57
57
|
before :each do
|
58
|
-
class Location < Doodle
|
58
|
+
class ::Location < Doodle
|
59
59
|
has :name, :kind => String
|
60
60
|
end
|
61
|
-
class Event < Doodle
|
62
|
-
has :locations, :init => [], :collect => Location
|
61
|
+
class ::Event < Doodle
|
62
|
+
has :locations, :init => [], :collect => ::Location
|
63
63
|
end
|
64
64
|
@event = Event do
|
65
65
|
location "Stage 1"
|
@@ -73,11 +73,11 @@ describe Doodle, "Typed collector with default collector name" do
|
|
73
73
|
after :each do
|
74
74
|
remove_ivars :event
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
it "should define a collector method :location" do
|
78
78
|
@event.methods.map{ |x| x.to_sym }.include?(:location).should_be true
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
it "should collect items into attribute :list" do
|
82
82
|
@event.locations.map{|loc| loc.name}.should_be ["Stage 1", "Stage 2"]
|
83
83
|
end
|
@@ -88,10 +88,10 @@ end
|
|
88
88
|
describe Doodle, "Typed collector with specified collector name" do
|
89
89
|
temporary_constant :Location, :Event do
|
90
90
|
before :each do
|
91
|
-
class Location < Doodle
|
91
|
+
class ::Location < Doodle
|
92
92
|
has :name, :kind => String
|
93
93
|
end
|
94
|
-
class Event < Doodle
|
94
|
+
class ::Event < Doodle
|
95
95
|
has :locations, :init => [], :collect => { :place => :Location }
|
96
96
|
end
|
97
97
|
end
|
@@ -104,11 +104,11 @@ end
|
|
104
104
|
describe Doodle, "typed collector with specified collector name" do
|
105
105
|
temporary_constant :Location, :Event do
|
106
106
|
before :each do
|
107
|
-
class Location < Doodle
|
107
|
+
class ::Location < Doodle
|
108
108
|
has :name, :kind => String
|
109
109
|
end
|
110
110
|
class Event < Doodle
|
111
|
-
has :locations, :init => [], :collect => { :place => Location }
|
111
|
+
has :locations, :init => [], :collect => { :place => ::Location }
|
112
112
|
end
|
113
113
|
end
|
114
114
|
it "should collect items into attribute :list" do
|
@@ -120,7 +120,7 @@ describe Doodle, "typed collector with specified collector name" do
|
|
120
120
|
end
|
121
121
|
}.should_not raise_error
|
122
122
|
event.locations.map{|loc| loc.name}.should_be ["Stage 1", "Stage 2"]
|
123
|
-
event.locations.map{|loc| loc.class}.should_be [Location, Location]
|
123
|
+
event.locations.map{|loc| loc.class}.should_be [::Location, ::Location]
|
124
124
|
end
|
125
125
|
end
|
126
126
|
end
|
@@ -129,11 +129,11 @@ describe Doodle, "typed collector with specified collector name initialized from
|
|
129
129
|
# note: this spec also checks for resolving collector class
|
130
130
|
temporary_constant :Location, :Event do
|
131
131
|
before :each do
|
132
|
-
class Location < Doodle
|
132
|
+
class ::Location < Doodle
|
133
133
|
has :name, :kind => String
|
134
134
|
has :events, :collect => :Event
|
135
135
|
end
|
136
|
-
class Event < Doodle
|
136
|
+
class ::Event < Doodle
|
137
137
|
has :name, :kind => String
|
138
138
|
has :locations, :collect => :Location
|
139
139
|
end
|
@@ -154,7 +154,7 @@ describe Doodle, "typed collector with specified collector name initialized from
|
|
154
154
|
event = Event(data)
|
155
155
|
}.should_not raise_error
|
156
156
|
event.locations.map{|loc| loc.name}.should_be ["Stage 1", "Stage 2"]
|
157
|
-
event.locations.map{|loc| loc.class}.should_be [Location, Location]
|
157
|
+
event.locations.map{|loc| loc.class}.should_be [::Location, ::Location]
|
158
158
|
event.locations[0].events[0].kind_of?(Event).should_be true
|
159
159
|
end
|
160
160
|
end
|
@@ -174,11 +174,11 @@ describe Doodle, "Simple keyed collector" do
|
|
174
174
|
after :each do
|
175
175
|
remove_ivars :foo
|
176
176
|
end
|
177
|
-
|
177
|
+
|
178
178
|
it "should define a collector method :item" do
|
179
179
|
@foo.methods.map{ |x| x.to_sym }.include?(:item).should_be true
|
180
180
|
end
|
181
|
-
|
181
|
+
|
182
182
|
it "should collect items into attribute :list" do
|
183
183
|
@foo.list.should_be( { 5 => "World" } )
|
184
184
|
end
|
@@ -189,20 +189,20 @@ end
|
|
189
189
|
describe Doodle, "Simple keyed collector #2" do
|
190
190
|
temporary_constant :Foo, :Item do
|
191
191
|
before :each do
|
192
|
-
class Item < Doodle
|
192
|
+
class ::Item < Doodle
|
193
193
|
has :name
|
194
194
|
end
|
195
|
-
class Foo < Doodle
|
195
|
+
class ::Foo < Doodle
|
196
196
|
has :list, :collect => Item, :key => :name
|
197
197
|
end
|
198
198
|
end
|
199
|
-
|
199
|
+
|
200
200
|
it "should define a collector method :item" do
|
201
201
|
foo = Foo.new
|
202
202
|
foo.methods.map{ |x| x.to_sym }.include?(:item).should_be true
|
203
203
|
foo.respond_to?(:item).should_be true
|
204
204
|
end
|
205
|
-
|
205
|
+
|
206
206
|
it "should collect items into attribute :list #1" do
|
207
207
|
foo = Foo do
|
208
208
|
item "Hello"
|
@@ -220,7 +220,7 @@ describe Doodle, "Simple keyed collector #2" do
|
|
220
220
|
)
|
221
221
|
foo.list.to_a.map{ |k, v| [k, v.class, v.name] }.should_be( [["Hello", Item, "Hello"], ["World", Item, "World"]] )
|
222
222
|
end
|
223
|
-
|
223
|
+
|
224
224
|
it "should collect positional argument enumerable into attribute :list" do
|
225
225
|
foo = Foo([
|
226
226
|
{ :name => "Hello" },
|
@@ -238,6 +238,73 @@ describe Doodle, "Simple keyed collector #2" do
|
|
238
238
|
)
|
239
239
|
foo.list.to_a.map{ |k, v| [k, v.class, v.name] }.should_be( [["Hello", Item, "Hello"], ["World", Item, "World"]] )
|
240
240
|
end
|
241
|
-
|
241
|
+
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe Doodle, 'using String as collector' do
|
246
|
+
temporary_constant :Text do
|
247
|
+
before :each do
|
248
|
+
#: definition
|
249
|
+
class Text < Doodle
|
250
|
+
has :body, :init => "", :collect => :line
|
251
|
+
def to_s
|
252
|
+
body
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'should not raise an exception' do
|
258
|
+
proc {
|
259
|
+
text = Text do
|
260
|
+
line "line 1"
|
261
|
+
line "line 2"
|
262
|
+
end
|
263
|
+
}.should_not raise_error
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'should concatenate strings' do
|
267
|
+
text = Text do
|
268
|
+
line "line 1"
|
269
|
+
line "line 2"
|
270
|
+
end
|
271
|
+
text.to_s.should_be "line 1line 2"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
describe Doodle, 'collecting text values into non-String collector' do
|
277
|
+
# this is a regression test - when collecting String values into a
|
278
|
+
# non-String accumulator should instantiate from
|
279
|
+
# collector_class.new(value)
|
280
|
+
temporary_constants :Name, :TextValue, :Signature do
|
281
|
+
before :each do
|
282
|
+
class ::Name < Doodle
|
283
|
+
has :value
|
284
|
+
end
|
285
|
+
class ::Signature < Doodle
|
286
|
+
has Name
|
287
|
+
end
|
288
|
+
class ::SignedBy < Doodle
|
289
|
+
has :signatures, :collect => Signature
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'should not raise an exception' do
|
294
|
+
proc {
|
295
|
+
signed_by = SignedBy do
|
296
|
+
signature "Sean"
|
297
|
+
end
|
298
|
+
}.should_not raise_error
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'should convert String values to instances of collector class' do
|
302
|
+
signed_by = SignedBy do
|
303
|
+
signature "Sean"
|
304
|
+
end
|
305
|
+
signed_by.signatures.first.class.should_be Signature
|
306
|
+
signed_by.signatures.first.name.class.should_be Name
|
307
|
+
signed_by.signatures.first.name.value.should_be "Sean"
|
308
|
+
end
|
242
309
|
end
|
243
310
|
end
|
data/spec/defaults_spec.rb
CHANGED
@@ -96,6 +96,19 @@ describe Doodle, 'defaults which have been set' do
|
|
96
96
|
it 'should have default value set from block' do
|
97
97
|
@foo.start.should_be Date.today
|
98
98
|
end
|
99
|
+
|
100
|
+
it 'should denote that default value is a default' do
|
101
|
+
@foo.default?(:start).should_be true
|
102
|
+
@foo.default?(:baz).should_be true
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should denote that default value is not a default if it has been assigned' do
|
106
|
+
@foo.baz = "Hi"
|
107
|
+
@foo.default?(:baz).should_not_be true
|
108
|
+
@foo.start = Date.today
|
109
|
+
@foo.default?(:start).should_not_be true
|
110
|
+
end
|
111
|
+
|
99
112
|
end
|
100
113
|
end
|
101
114
|
|
data/spec/doodle_context_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
3
3
|
describe Doodle, "doodle_context" do
|
4
4
|
temporary_constants :Foo, :Bar do
|
5
5
|
before :each do
|
6
|
-
class Child < Doodle
|
6
|
+
class ::Child < Doodle
|
7
7
|
has :name
|
8
8
|
has :dad do
|
9
9
|
# there is an important difference between a block argument
|
data/spec/doodle_spec.rb
CHANGED
@@ -290,26 +290,16 @@ describe Doodle, 'inherited singleton class attributes' do
|
|
290
290
|
@foo.singleton_class.doodle.attributes[:metadata].should_be nil
|
291
291
|
@foo.singleton_class.metadata = 'foo meta'
|
292
292
|
@foo.singleton_class.instance_eval { @metadata }.should_be 'foo meta'
|
293
|
-
|
294
|
-
@foo.singleton_class.metadata.should_be 'foo meta'
|
295
|
-
else
|
296
|
-
pending 'figuring out why this fails in 1.9' do
|
297
|
-
@foo.singleton_class.metadata.should_be 'foo meta'
|
298
|
-
end
|
299
|
-
end
|
293
|
+
@foo.singleton_class.metadata.should_be 'foo meta'
|
300
294
|
end
|
301
295
|
|
302
296
|
it 'should behave predictably when setting singleton attributes' do
|
303
297
|
@bar.extra = 'bar extra'
|
304
298
|
@bar.extra.should_be 'bar extra'
|
305
299
|
@bar.singleton_class.metadata = 'bar meta metadata'
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
@bar.singleton_class.notes.should_be 'bar notes'
|
310
|
-
else
|
311
|
-
pending 'figuring out why this fails in 1.9'
|
312
|
-
end
|
300
|
+
@bar.singleton_class.metadata.should_be 'bar meta metadata'
|
301
|
+
@bar.singleton_class.notes = 'bar notes'
|
302
|
+
@bar.singleton_class.notes.should_be 'bar notes'
|
313
303
|
proc { @foo.singleton_class.notes = 1 }.should raise_error(NoMethodError)
|
314
304
|
end
|
315
305
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Doodle, 'simple equality' do
|
4
|
+
temporary_constants :Foo, :Bar, :Baz do
|
5
|
+
before(:each) do
|
6
|
+
class Bar < Doodle
|
7
|
+
has :name
|
8
|
+
end
|
9
|
+
class Foo < Doodle
|
10
|
+
has :id
|
11
|
+
has Bar
|
12
|
+
end
|
13
|
+
class Baz < Doodle
|
14
|
+
has :id
|
15
|
+
has Bar
|
16
|
+
end
|
17
|
+
@foo1 = Foo.new do
|
18
|
+
id 1
|
19
|
+
bar "Hello"
|
20
|
+
end
|
21
|
+
@foo2 = Foo.new do
|
22
|
+
id 1
|
23
|
+
bar "Hello"
|
24
|
+
end
|
25
|
+
@baz = Baz.new do
|
26
|
+
id 1
|
27
|
+
bar "Hello"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should be equal to another Doodle with the same class and values' do
|
32
|
+
@foo1.should_be @foo2
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not equal another Doodle with the same values but different class' do
|
36
|
+
@foo1.should_not_be @baz
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe Doodle, 'nested equality via inheritance' do
|
42
|
+
temporary_constants :Location, :Event do
|
43
|
+
before :each do
|
44
|
+
class ::Location < Doodle
|
45
|
+
has :name, :kind => String
|
46
|
+
has :events, :collect => :Event, :key => :name
|
47
|
+
end
|
48
|
+
|
49
|
+
class ::Event < Doodle
|
50
|
+
has :name, :kind => String
|
51
|
+
has :date, :kind => Date do
|
52
|
+
default { Date.today }
|
53
|
+
from String do |s|
|
54
|
+
Date.parse(s)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
has :locations, :collect => {:place => :Location}, :key => :name
|
58
|
+
end
|
59
|
+
|
60
|
+
@event = Event "Festival" do
|
61
|
+
date '2018-04-01'
|
62
|
+
place "The muddy field"
|
63
|
+
place "Beer tent" do
|
64
|
+
event "Drinking"
|
65
|
+
event "Dancing"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should equate object A and object B where object B has been deserialized from yaml generated by serializing object A' do
|
71
|
+
yaml = @event.to_yaml
|
72
|
+
event2 = YAML::load(yaml).validate!
|
73
|
+
@event.to_hash.should_be event2.to_hash
|
74
|
+
@event.should_be event2
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe Doodle, 'nested equality via including Doodle::Core' do
|
80
|
+
temporary_constants :Location, :Event do
|
81
|
+
before :each do
|
82
|
+
class ::Location < Doodle
|
83
|
+
has :name, :kind => String
|
84
|
+
has :events, :collect => :Event, :key => :name
|
85
|
+
end
|
86
|
+
|
87
|
+
class ::Event
|
88
|
+
# or if you want to inherit from another class
|
89
|
+
include Doodle::Core
|
90
|
+
|
91
|
+
has :name, :kind => String
|
92
|
+
has :date, :kind => Date do
|
93
|
+
default { Date.today }
|
94
|
+
from String do |s|
|
95
|
+
Date.parse(s)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
has :locations, :collect => {:place => :Location}, :key => :name
|
99
|
+
end
|
100
|
+
|
101
|
+
@event = Event "Festival" do
|
102
|
+
date '2018-04-01'
|
103
|
+
place "The muddy field"
|
104
|
+
place "Beer tent" do
|
105
|
+
event "Drinking"
|
106
|
+
event "Dancing"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should equate object A and object B where object B has been deserialized from yaml generated by serializing object A' do
|
112
|
+
yaml = @event.to_yaml
|
113
|
+
event2 = YAML::load(yaml).validate!
|
114
|
+
@event.to_hash.should_be event2.to_hash
|
115
|
+
@event.should_be event2
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Doodle, "Definitions within rspec" do
|
4
|
+
temporary_constant :Foo1 do
|
5
|
+
before :each do
|
6
|
+
class Foo1 < Doodle
|
7
|
+
has :name
|
8
|
+
end
|
9
|
+
end
|
10
|
+
it 'should define a constructor function' do
|
11
|
+
no_error { foo = Foo1("Bar") }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Doodle, "Definitions at top level" do
|
17
|
+
temporary_constant :Foo2 do
|
18
|
+
before :each do
|
19
|
+
class ::Object
|
20
|
+
class Foo2 < Doodle
|
21
|
+
has :name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
it 'should define a constructor function' do
|
26
|
+
no_error { foo = Foo2("Bar") }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Doodle, "Definitions in modules" do
|
32
|
+
temporary_constant :Foo3, :Bar3 do
|
33
|
+
before :each do
|
34
|
+
module ::Bar3
|
35
|
+
class Foo3 < Doodle
|
36
|
+
has :name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
it 'should define a constructor function' do
|
41
|
+
no_error { foo = ::Bar3.Foo3("Bar") }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe Doodle, "Definitions in module_eval" do
|
47
|
+
temporary_constant :Foo4, :Bar4 do
|
48
|
+
before :each do
|
49
|
+
module Bar4
|
50
|
+
end
|
51
|
+
Bar4.module_eval do
|
52
|
+
class Foo4 < Doodle
|
53
|
+
has :name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
it 'should define a constructor function' do
|
58
|
+
pending "Figuring out how to make this work portably"
|
59
|
+
no_error { foo = Bar4.send(:Foo4, "Bar") }
|
60
|
+
end
|
61
|
+
it 'should define a public constructor function' do
|
62
|
+
pending "Figuring out how to make this work at all"
|
63
|
+
no_error { foo = Bar4.Foo4("Bar") }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|