doodle 0.2.2 → 0.2.3

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.
Files changed (48) hide show
  1. data/History.txt +24 -0
  2. data/Manifest.txt +26 -1
  3. data/README.txt +9 -8
  4. data/lib/doodle.rb +43 -1496
  5. data/lib/doodle/app.rb +6 -0
  6. data/lib/doodle/attribute.rb +165 -0
  7. data/lib/doodle/base.rb +180 -0
  8. data/lib/doodle/collector-1.9.rb +72 -0
  9. data/lib/doodle/collector.rb +191 -0
  10. data/lib/doodle/comparable.rb +8 -0
  11. data/lib/doodle/conversion.rb +80 -0
  12. data/lib/doodle/core.rb +42 -0
  13. data/lib/doodle/datatype-holder.rb +39 -0
  14. data/lib/doodle/debug.rb +20 -0
  15. data/lib/doodle/deferred.rb +13 -0
  16. data/lib/doodle/equality.rb +21 -0
  17. data/lib/doodle/exceptions.rb +29 -0
  18. data/lib/doodle/factory.rb +91 -0
  19. data/lib/doodle/getter-setter.rb +154 -0
  20. data/lib/doodle/info.rb +298 -0
  21. data/lib/doodle/inherit.rb +40 -0
  22. data/lib/doodle/json.rb +38 -0
  23. data/lib/doodle/marshal.rb +16 -0
  24. data/lib/doodle/normalized_array.rb +512 -0
  25. data/lib/doodle/normalized_hash.rb +356 -0
  26. data/lib/doodle/ordered-hash.rb +8 -0
  27. data/lib/doodle/singleton.rb +23 -0
  28. data/lib/doodle/smoke-and-mirrors.rb +23 -0
  29. data/lib/doodle/to_hash.rb +17 -0
  30. data/lib/doodle/utils.rb +173 -11
  31. data/lib/doodle/validation.rb +122 -0
  32. data/lib/doodle/version.rb +1 -1
  33. data/lib/molic_orderedhash.rb +24 -10
  34. data/spec/assigned_spec.rb +45 -0
  35. data/spec/attributes_spec.rb +7 -7
  36. data/spec/collector_spec.rb +100 -13
  37. data/spec/doodle_context_spec.rb +5 -5
  38. data/spec/from_spec.rb +43 -3
  39. data/spec/json_spec.rb +232 -0
  40. data/spec/member_init_spec.rb +11 -11
  41. data/spec/modules_spec.rb +4 -4
  42. data/spec/multi_collector_spec.rb +91 -0
  43. data/spec/must_spec.rb +32 -0
  44. data/spec/spec_helper.rb +14 -4
  45. data/spec/specialized_attribute_class_spec.rb +2 -2
  46. data/spec/typed_collector_spec.rb +57 -0
  47. data/spec/xml_spec.rb +8 -8
  48. metadata +33 -3
@@ -11,15 +11,15 @@ describe Doodle, "doodle_context" do
11
11
  # - a proc/lamba is treated as a literal argument, i.e. the
12
12
  # - value is set to a Proc
13
13
  # - a block argument, on the other hand, is instance
14
- # - evaluated during initialization
14
+ # evaluated during initialization
15
15
  # - consequences
16
16
  # - can only be done in init block
17
17
  # - somewhat subtle difference (from programmer's point of
18
- # - view) between a proc and a block
18
+ # view) between a proc and a block
19
19
  # Also note re: Doodle.parent - its value is only valid
20
20
  # during initialization - this is a way to capture that
21
- # value for ues later
22
-
21
+ # value for use later
22
+
23
23
  init { doodle.parent }
24
24
  end
25
25
  end
@@ -29,7 +29,7 @@ describe Doodle, "doodle_context" do
29
29
  end
30
30
 
31
31
  end
32
-
32
+
33
33
  it 'should provide a means to find out the current parent of an item in initialization block' do
34
34
  dad = Parent 'Conn' do
35
35
  child 'Sean'
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
- describe 'Doodle', 'applying Doodle type conversions' do
3
+ describe 'Doodle', 'from' do
4
4
  temporary_constant :Foo, :Name do
5
5
  before :each do
6
6
  class Name < String
@@ -25,7 +25,7 @@ describe 'Doodle', 'applying Doodle type conversions' do
25
25
  it 'should convert a value based on conversions in doodle class' do
26
26
  proc { foo = Foo 'Arthur' }.should_not raise_error
27
27
  end
28
-
28
+
29
29
  it 'should convert a value based on conversions in doodle class to the correct class' do
30
30
  foo = Foo 'Arthur'
31
31
  foo.name.class.should_be Name
@@ -38,6 +38,46 @@ describe 'Doodle', 'applying Doodle type conversions' do
38
38
  it 'should apply validations from doodle type' do
39
39
  proc { Foo 'Art' }.should raise_error(Doodle::ConversionError)
40
40
  end
41
-
41
+
42
+ end
43
+ end
44
+
45
+ describe 'Doodle', 'from' do
46
+ temporary_constant :Answer do
47
+ before :each do
48
+ end
49
+
50
+ it 'should allow specifying from in has params' do
51
+ class Answer < Doodle
52
+ has :value, :from => { Integer => proc {|i| i.to_s }}
53
+ end
54
+ name = Answer.new(42)
55
+ name.value.should_be "42"
56
+ end
57
+
58
+ it 'should allow specifying from in has params with kind specified' do
59
+ class Answer < Doodle
60
+ has :value, :kind => String, :from => { Integer => proc {|i| i.to_s }}
61
+ end
62
+ name = Answer.new(42)
63
+ name.value.should_be "42"
64
+ end
65
+
66
+ it 'should override from clause in has params with one defined in block' do
67
+ class Answer < Doodle
68
+ has :value, :kind => String, :from => { Integer => proc {|i| i.to_s }} do
69
+ # this should override :from clause in has params
70
+ from Float do |i|
71
+ (Integer(i + 20)).to_s
72
+ end
73
+ end
74
+ end
75
+
76
+ name = Answer.new(22.0)
77
+ name.value.should_be "42"
78
+
79
+ name = Answer.new(42)
80
+ name.value.should_be "42"
81
+ end
42
82
  end
43
83
  end
@@ -0,0 +1,232 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'doodle/json'
3
+
4
+ def compare_json(data, json)
5
+ JSON.parse(data.to_json, :create_additions => false).should_be JSON.parse(json, :create_additions => false)
6
+ end
7
+
8
+ describe Doodle, 'JSON serialization within a module' do
9
+ temporary_constants :Container, :Base, :Slideshow, :Layout do
10
+ before(:each) do
11
+ @json_source = <<EOT
12
+ {
13
+ "json_class":"Container::Slideshow",
14
+ "data":{
15
+ "name":"test",
16
+ "layout":{
17
+ "json_class":"Container::Layout",
18
+ "data":{
19
+ "template":"generic"
20
+ }
21
+ },
22
+ "id":1
23
+ }
24
+ }
25
+ EOT
26
+ @json_data = JSON.parse(@json_source, :create_additions => false)
27
+
28
+ module ::Container
29
+ class Base < Doodle
30
+ include Doodle::JSON
31
+ end
32
+ class Layout < Base
33
+ has :template
34
+ end
35
+ class Slideshow < Base
36
+ has :id, :kind => Integer do
37
+ from String do |s|
38
+ s.to_i
39
+ end
40
+ end
41
+ has :name, :kind => String
42
+ has Layout
43
+ end
44
+ end
45
+ end
46
+ it 'should serialize to json' do
47
+ slideshow = Container::Slideshow.new do
48
+ id 1
49
+ name "test"
50
+ layout "generic"
51
+ end
52
+ compare_json(slideshow, @json_source)
53
+ end
54
+ it 'should serialize from json' do
55
+ slideshow = Container::Slideshow.new do
56
+ id 1
57
+ name "test"
58
+ layout "generic"
59
+ end
60
+ ss2 = Doodle.from_json(@json_source)
61
+ ss2.should_be slideshow
62
+ end
63
+ end
64
+ end
65
+
66
+ describe Doodle, 'JSON serialization at top level' do
67
+ temporary_constants :Base, :Slideshow, :Layout do
68
+ before(:each) do
69
+ @json_source = <<EOT
70
+ {
71
+ "json_class":"Slideshow",
72
+ "data":{
73
+ "name":"test",
74
+ "layout":{
75
+ "json_class":"Layout",
76
+ "data":{
77
+ "template":"generic"
78
+ }
79
+ },
80
+ "id":1
81
+ }
82
+ }
83
+ EOT
84
+ class ::Base < Doodle
85
+ include Doodle::JSON
86
+ end
87
+ class ::Layout < Base
88
+ has :template
89
+ end
90
+ class ::Slideshow < Base
91
+ has :id, :kind => Integer do
92
+ from String do |s|
93
+ s.to_i
94
+ end
95
+ end
96
+ has :name, :kind => String
97
+ has Layout
98
+ end
99
+ end
100
+ it 'should serialize to json' do
101
+ slideshow = ::Slideshow.new do
102
+ id 1
103
+ name "test"
104
+ layout "generic"
105
+ end
106
+ compare_json(slideshow, @json_source)
107
+ end
108
+ it 'should serialize from json' do
109
+ slideshow = ::Slideshow.new do
110
+ id 1
111
+ name "test"
112
+ layout "generic"
113
+ end
114
+ ss2 = Doodle.from_json(@json_source)
115
+ ss2.should_be slideshow
116
+ end
117
+ end
118
+ end
119
+
120
+ describe Doodle, 'JSON' do
121
+ temporary_constant :Address do
122
+ before :each do
123
+ class ::Address < Doodle
124
+ include Doodle::JSON
125
+ has :where, :default => "home"
126
+ has :city
127
+ end
128
+ end
129
+
130
+ it 'should not raise an error when supplying attribute values' do
131
+ proc {
132
+ Address do
133
+ city "London"
134
+ end
135
+ }.should_not raise_error
136
+ end
137
+
138
+ it 'should accept attributes defined in block' do
139
+ a = Address do
140
+ city "London"
141
+ end
142
+ a.city.should_be "London"
143
+ end
144
+
145
+ it 'should output non-doodle attributes as JSON attributes' do
146
+ a = Address do
147
+ city "London"
148
+ end
149
+ compare_json(a, <<EOT)
150
+ {
151
+ "json_class":"Address",
152
+ "data":{
153
+ "city":"London"
154
+ }
155
+ }
156
+ EOT
157
+ end
158
+ end
159
+ end
160
+
161
+ describe Doodle, 'JSON' do
162
+ temporary_constant :Base, :City, :Address do
163
+ before :each do
164
+ class ::Base < Doodle
165
+ include Doodle::JSON
166
+ end
167
+ class ::City < Base
168
+ has :_text_
169
+ has :country, :default => "UK"
170
+ end
171
+ class ::Address < Base
172
+ has :where, :default => "home"
173
+ has City
174
+ end
175
+ end
176
+
177
+ it 'should output required tags in JSON' do
178
+ a = Address do
179
+ city "London"
180
+ end
181
+ compare_json(a, <<EOT)
182
+ {
183
+ "json_class":"Address",
184
+ "data":{
185
+ "city":{
186
+ "json_class":"City",
187
+ "data":{"_text_":"London"}
188
+ }
189
+ }
190
+ }
191
+ EOT
192
+ end
193
+
194
+ it 'should output specified optional attributes as json attributes if kind not a doodle class' do
195
+ a = Address :where => 'home' do
196
+ city "London"
197
+ end
198
+ compare_json(a, <<EOT)
199
+ {
200
+ "json_class":"Address",
201
+ "data":{
202
+ "city":{
203
+ "json_class":"City",
204
+ "data":{"_text_":"London"}
205
+ },
206
+ "where":"home"
207
+ }
208
+ }
209
+ EOT
210
+ end
211
+
212
+ it 'should output specified optional attributes' do
213
+ a = Address :where => 'home' do
214
+ city "London", :country => "England" do
215
+ country "UK"
216
+ end
217
+ end
218
+ compare_json(a, <<EOT)
219
+ {
220
+ "json_class":"Address",
221
+ "data":{
222
+ "city":{"json_class":"City", "data":{"_text_":"London", "country":"UK"}},
223
+ "where":"home"
224
+ }
225
+ }
226
+ EOT
227
+ end
228
+
229
+ end
230
+
231
+ end
232
+
@@ -13,16 +13,16 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
13
13
  has :v2, :kind => String, :default => "bar"
14
14
  end
15
15
  end
16
-
16
+
17
17
  it 'should initialize an attribute from a hash' do
18
18
  foo = Foo do
19
- bar :name => "hello", :count => 1
19
+ bar :name => "hello", :count => 1
20
20
  end
21
21
  foo.bar.name.should_be "hello"
22
22
  foo.bar.count.should_be 1
23
23
  end
24
24
  it 'should fail trying to initialize with incorrect keyword values' do
25
- proc {
25
+ proc {
26
26
  foo = Foo do
27
27
  bar :name => 1, :count => "hello"
28
28
  end
@@ -30,7 +30,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
30
30
  end
31
31
  it 'should work with positional args' do
32
32
  foo = nil
33
- proc {
33
+ proc {
34
34
  foo = Foo do
35
35
  bar "hello", 1
36
36
  end
@@ -40,7 +40,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
40
40
  end
41
41
  it 'should work with block initialization' do
42
42
  foo = nil
43
- proc {
43
+ proc {
44
44
  foo = Foo do
45
45
  bar do
46
46
  name "hello"
@@ -53,7 +53,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
53
53
  end
54
54
  it 'should work with arg and block initialization' do
55
55
  foo = nil
56
- proc {
56
+ proc {
57
57
  foo = Foo do
58
58
  bar "hello" do
59
59
  count 1
@@ -65,7 +65,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
65
65
  end
66
66
  it 'should work with keyword and block initialization' do
67
67
  foo = nil
68
- proc {
68
+ proc {
69
69
  foo = Foo do
70
70
  bar :name => "hello" do
71
71
  count 1
@@ -77,7 +77,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
77
77
  end
78
78
  it 'should raise error with invalid keyword and block initialization' do
79
79
  foo = nil
80
- proc {
80
+ proc {
81
81
  foo = Foo do
82
82
  bar :name => 1 do
83
83
  count "hello"
@@ -87,7 +87,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
87
87
  end
88
88
  it 'should raise error with keyword and invalid block initialization' do
89
89
  foo = nil
90
- proc {
90
+ proc {
91
91
  foo = Foo do
92
92
  bar :name => "hello" do
93
93
  count "hello"
@@ -97,7 +97,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
97
97
  end
98
98
  it 'should initialize non-Doodle or Proc with simple value' do
99
99
  foo = nil
100
- proc {
100
+ proc {
101
101
  foo = Foo do
102
102
  bar :name => "hello", :count => 1
103
103
  v2 "Hello"
@@ -108,7 +108,7 @@ describe 'Doodle', 'initialization of scalar attributes from hash' do
108
108
  foo.v2.should_be "Hello"
109
109
  end
110
110
  it 'should fail trying to initialize an inappropriate attribute (not a Doodle or Proc) from a block' do
111
- proc {
111
+ proc {
112
112
  foo = Foo do
113
113
  bar :name => "hello", :count => 1
114
114
  v2 do
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
- describe Doodle, "Definitions within rspec" do
3
+ describe Doodle, "definitions within rspec" do
4
4
  temporary_constant :Foo1 do
5
5
  before :each do
6
6
  class Foo1 < Doodle
@@ -13,7 +13,7 @@ describe Doodle, "Definitions within rspec" do
13
13
  end
14
14
  end
15
15
 
16
- describe Doodle, "Definitions at top level" do
16
+ describe Doodle, "definitions at top level" do
17
17
  temporary_constant :Foo2 do
18
18
  before :each do
19
19
  class ::Object
@@ -28,7 +28,7 @@ describe Doodle, "Definitions at top level" do
28
28
  end
29
29
  end
30
30
 
31
- describe Doodle, "Definitions in modules" do
31
+ describe Doodle, "definitions in modules" do
32
32
  temporary_constant :Foo3, :Bar3 do
33
33
  before :each do
34
34
  module ::Bar3
@@ -43,7 +43,7 @@ describe Doodle, "Definitions in modules" do
43
43
  end
44
44
  end
45
45
 
46
- describe Doodle, "Definitions in module_eval" do
46
+ describe Doodle, "definitions in module_eval" do
47
47
  temporary_constant :Foo4, :Bar4 do
48
48
  before :each do
49
49
  module Bar4
@@ -0,0 +1,91 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Doodle, 'multiple collector' do
4
+ temporary_constants :Text, :Item, :List do
5
+ before :each do
6
+ #: definition
7
+ class ::Item < Doodle
8
+ has :name, :kind => String
9
+ end
10
+ class ::Text < Doodle
11
+ has :body, :kind => String
12
+ end
13
+ class ::List < Doodle
14
+ has :items, :collect => [Item, Text]
15
+ end
16
+ end
17
+
18
+ it 'should accept convertible values in collector' do
19
+ list = nil
20
+ no_error {
21
+ list = List do
22
+ item "Hello"
23
+ text "World"
24
+ end
25
+ }
26
+ list.items.size.should_be 2
27
+ list.items[0].should_be Item("Hello")
28
+ list.items[1].should_be Text("World")
29
+ end
30
+ end
31
+ end
32
+
33
+ describe Doodle, 'multiple collector' do
34
+ temporary_constants :Text, :Item, :List do
35
+ before :each do
36
+ #: definition
37
+ class ::Item < Doodle
38
+ has :name, :kind => String
39
+ end
40
+ class ::Text < Doodle
41
+ has :body, :kind => String
42
+ end
43
+ class ::List < Doodle
44
+ has :items, :collect => [ { :foo => Item }, { :bar => Text } ]
45
+ end
46
+ end
47
+
48
+ it 'should accept convertible values in collector using specified collector methods' do
49
+ list = nil
50
+ no_error {
51
+ list = List do
52
+ foo "Hello"
53
+ bar "World"
54
+ end
55
+ }
56
+ list.items.size.should_be 2
57
+ list.items[0].should_be Item("Hello")
58
+ list.items[1].should_be Text("World")
59
+ end
60
+ end
61
+ end
62
+
63
+ describe Doodle, 'multiple collector' do
64
+ temporary_constants :Text, :Item, :List do
65
+ before :each do
66
+ #: definition
67
+ class ::Item < Doodle
68
+ has :name, :kind => String
69
+ end
70
+ class ::Text < Doodle
71
+ has :body, :kind => String
72
+ end
73
+ class ::List < Doodle
74
+ has :items, :collect => { :foo => Item, :bar => Text }
75
+ end
76
+ end
77
+
78
+ it 'should accept convertible values in collector using specified collector methods' do
79
+ list = nil
80
+ no_error {
81
+ list = List do
82
+ foo "Hello"
83
+ bar "World"
84
+ end
85
+ }
86
+ list.items.size.should_be 2
87
+ list.items[0].should_be Item("Hello")
88
+ list.items[1].should_be Text("World")
89
+ end
90
+ end
91
+ end