doodle 0.1.3 → 0.1.4

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.
@@ -57,6 +57,24 @@ class Doodle
57
57
  end
58
58
  end
59
59
 
60
+ def boolean(name, params = { }, &block)
61
+ define name, params, block, { } do
62
+ must "be true or false" do |v|
63
+ [true, false].include?(v)
64
+ end
65
+ from String, Symbol do |v|
66
+ case v.to_s
67
+ when /^(yes|true|on)$/
68
+ true
69
+ when /^(no|false|off)$/
70
+ false
71
+ else
72
+ v
73
+ end
74
+ end
75
+ end
76
+ end
77
+
60
78
  def symbol(name, params = { }, &block)
61
79
  define name, params, block, { :kind => Symbol } do
62
80
  from String do |s|
@@ -112,12 +130,7 @@ class Doodle
112
130
  # 384 = 128+1+255
113
131
  string(name, { :max => 384 }.merge(params), &block).instance_eval do
114
132
  must "be valid email address" do |s|
115
- if RUBY_VERSION >= '1.9.0'
116
- # the regex fails in 1.9 with illegal utf byte sequence error
117
- s =~ /\A.*@.*\z/
118
- else
119
- s =~ RFC822::EmailAddress
120
- end
133
+ s =~ RFC822::EmailAddress
121
134
  end
122
135
  end
123
136
  end
@@ -12,20 +12,27 @@
12
12
  # http://creativecommons.org/licenses/by-sa/2.5/
13
13
  #
14
14
  module RFC822
15
- EmailAddress = begin
16
- qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
17
- dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
18
- atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
19
- '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
20
- quoted_pair = '\\x5c[\\x00-\\x7f]'
21
- domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
22
- quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
23
- domain_ref = atom
24
- sub_domain = "(?:#{domain_ref}|#{domain_literal})"
25
- word = "(?:#{atom}|#{quoted_string})"
26
- domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
27
- local_part = "#{word}(?:\\x2e#{word})*"
28
- addr_spec = "#{local_part}\\x40#{domain}"
29
- pattern = /\A#{addr_spec}\z/
15
+ # TODO: fix the illegal multibyte sequence in 1.9
16
+ # the regex fails in 1.9 with illegal utf byte sequence error
17
+ if RUBY_VERSION < '1.9.0'
18
+ EmailAddress = begin
19
+ qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
20
+ dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
21
+ atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
22
+ '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
23
+ quoted_pair = '\\x5c[\\x00-\\x7f]'
24
+ domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
25
+ quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
26
+ domain_ref = atom
27
+ sub_domain = "(?:#{domain_ref}|#{domain_literal})"
28
+ word = "(?:#{atom}|#{quoted_string})"
29
+ domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
30
+ local_part = "#{word}(?:\\x2e#{word})*"
31
+ addr_spec = "#{local_part}\\x40#{domain}"
32
+ pattern = /\A#{addr_spec}\z/
33
+ end
34
+ else
35
+ # minimal regex until I sort out the problem above
36
+ EmailAddress = /\A.*@.*\z/
30
37
  end
31
38
  end
@@ -2,7 +2,7 @@ class Doodle #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 3
5
+ TINY = 4
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -12,9 +12,9 @@ describe 'arg_order' do
12
12
  end
13
13
  it 'should specify order of positional arguments' do
14
14
  foo = Foo.new 1, 2, 3
15
- foo.value.should == 1
16
- foo.name.should == 2
17
- foo.extra.should == 3
15
+ foo.value.should_be 1
16
+ foo.name.should_be 2
17
+ foo.extra.should_be 3
18
18
  end
19
19
 
20
20
  it 'should allow only symbols as arguments to arg_order' do
@@ -42,8 +42,8 @@ describe 'arg_order' do
42
42
  end
43
43
  it 'should specify order of positional arguments' do
44
44
  f = Bar.new 1, 2
45
- f.name.should == 1
46
- f.value.should == 2
45
+ f.name.should_be 1
46
+ f.value.should_be 2
47
47
  end
48
48
  end
49
49
  end
@@ -61,8 +61,8 @@ describe 'arg_order' do
61
61
  end
62
62
  it 'should specify order of positional arguments' do
63
63
  f = Bar.new 1, 2
64
- f.value.should == 1
65
- f.name.should == 2
64
+ f.value.should_be 1
65
+ f.name.should_be 2
66
66
  end
67
67
  end
68
68
  end
@@ -81,8 +81,8 @@ describe 'arg_order' do
81
81
 
82
82
  it 'should specify order of positional arguments' do
83
83
  f = Bar.new 1
84
- f.value.should == 1
85
- f.name.should == "bar"
84
+ f.value.should_be 1
85
+ f.name.should_be "bar"
86
86
  end
87
87
  end
88
88
  end
@@ -101,8 +101,8 @@ describe 'arg_order' do
101
101
 
102
102
  it 'should specify order of positional arguments' do
103
103
  f = Bar.new 1, "bar"
104
- f.value.should == 1
105
- f.name.should == "bar"
104
+ f.value.should_be 1
105
+ f.name.should_be "bar"
106
106
  end
107
107
  end
108
108
  end
@@ -64,10 +64,10 @@ describe Doodle::Attribute, 'basics' do
64
64
  @bar.attributes[:ivar2].optional?.should == false
65
65
  end
66
66
 
67
- it "should have parents in correct order" do
68
- expected_parents = RUBY_VERSION <= "1.8.6" ? [Foo, Object] : [Foo, Object, BasicObject]
69
- Bar.parents.should == expected_parents
70
- end
67
+ # it "should have parents in correct order" do
68
+ # expected_parents = RUBY_VERSION <= "1.8.6" ? [Foo, Object] : [Foo, Object, BasicObject]
69
+ # Bar.parents.should == expected_parents
70
+ # end
71
71
 
72
72
  it "should have Bar's singleton parents in reverse order of definition" do
73
73
  @bar.singleton_class.parents.should == []
@@ -128,10 +128,10 @@ describe Doodle::Attribute, 'attribute order' do
128
128
  end
129
129
  end
130
130
 
131
- it 'should keep order of inherited attributes' do
132
- expected_parents = RUBY_VERSION <= "1.8.6" ? [B, A, Doodle, Object] : [B, A, Doodle, Object, BasicObject]
133
- C.parents.should == expected_parents
134
- end
131
+ # it 'should keep order of inherited attributes' do
132
+ # expected_parents = RUBY_VERSION <= "1.8.6" ? [B, A, Doodle, Object] : [B, A, Doodle, Object, BasicObject]
133
+ # C.parents.should == expected_parents
134
+ # end
135
135
 
136
136
  it 'should keep order of inherited attributes' do
137
137
  C.attributes.keys.should == [:a, :b, :c]
@@ -15,8 +15,8 @@ describe 'Doodle', 'parents' do
15
15
 
16
16
  it 'should not duplicate validations when accessing them!' do
17
17
  foo = Foo 2
18
- foo.validations.size.should == 1
19
- foo.validations.size.should == 1
18
+ foo.validations.size.should_be 1
19
+ foo.validations.size.should_be 1
20
20
  end
21
21
  end
22
22
  end
@@ -48,8 +48,8 @@ describe 'Doodle', ' loading good data from yaml' do
48
48
 
49
49
  it 'should apply conversions' do
50
50
  foo = YAML::load(@str).validate!
51
- foo.date.should == Date.new(2000, 7, 1)
52
- foo.date.class.should == Date
51
+ foo.date.should_be Date.new(2000, 7, 1)
52
+ foo.date.class.should_be Date
53
53
  end
54
54
  end
55
55
  end
@@ -124,7 +124,7 @@ describe Doodle, 'initializing from hashes and yaml' do
124
124
  yaml = person.to_yaml
125
125
  # be careful here - Ruby yaml is finicky (spaces after class names)
126
126
  yaml = yaml.gsub(/\s*\n/m, "\n")
127
- yaml.should == %[--- !ruby/object:Person
127
+ yaml.should_be %[--- !ruby/object:Person
128
128
  address:
129
129
  - !ruby/object:AddressLine
130
130
  text: Henry Wood House
@@ -134,7 +134,7 @@ name: Sean
134
134
  ]
135
135
  person = YAML.load(yaml)
136
136
  proc { person.validate! }.should_not raise_error
137
- person.address.all?{ |x| x.kind_of? AddressLine }.should == true
137
+ person.address.all?{ |x| x.kind_of? AddressLine }.should_be true
138
138
 
139
139
  end
140
140
  end
@@ -167,7 +167,7 @@ describe 'Doodle', 'hiding @__doodle__' do
167
167
  end
168
168
  it 'should not include @__doodle__ in instance_variables' do
169
169
  foo = Foo 2
170
- foo.instance_variables.size.should == 1
170
+ foo.instance_variables.size.should_be 1
171
171
  foo.instance_variables.first.should =~ /^@var1$/
172
172
  end
173
173
  it 'should not reveal @__doodle__ in inspect string' do
@@ -176,7 +176,7 @@ describe 'Doodle', 'hiding @__doodle__' do
176
176
  end
177
177
  it 'should not include @__doodle__ in instance_variables' do
178
178
  foo = Bar 2
179
- foo.instance_variables.size.should == 1
179
+ foo.instance_variables.size.should_be 1
180
180
  foo.instance_variables.first.should =~ /^@var2$/
181
181
  end
182
182
  it 'should correctly inspect when using included module' do
@@ -185,17 +185,17 @@ describe 'Doodle', 'hiding @__doodle__' do
185
185
  end
186
186
  it 'should correctly inspect string' do
187
187
  foo = DString("Hello")
188
- foo.inspect.should == '"Hello"'
188
+ foo.inspect.should_be '"Hello"'
189
189
  end
190
190
  it 'should correctly inspect hash' do
191
191
  foo = DHash.new(2)
192
192
  foo[:a] = 1
193
- foo.inspect.should == '{:a=>1}'
194
- foo[:b].should == 2
193
+ foo.inspect.should_be '{:a=>1}'
194
+ foo[:b].should_be 2
195
195
  end
196
196
  it 'should correctly inspect array' do
197
197
  foo = DArray(3, 2)
198
- foo.inspect.should == '[2, 2, 2]'
198
+ foo.inspect.should_be '[2, 2, 2]'
199
199
  end
200
200
  end
201
201
  end
@@ -22,65 +22,65 @@ describe Doodle, 'class attributes' do
22
22
 
23
23
  it 'should create class attribute' do
24
24
  Foo.metadata = 'Foo metadata'
25
- Foo.metadata.should == 'Foo metadata'
25
+ Foo.metadata.should_be 'Foo metadata'
26
26
  end
27
27
 
28
28
  it 'should access @foo class attribute via self.class' do
29
29
  @foo.class.metadata = '@foo metadata'
30
- @foo.class.metadata.should == '@foo metadata'
31
- Foo.metadata.should == '@foo metadata'
30
+ @foo.class.metadata.should_be '@foo metadata'
31
+ Foo.metadata.should_be '@foo metadata'
32
32
 
33
33
  Foo.metadata = 'Foo metadata'
34
- Foo.metadata.should == 'Foo metadata'
35
- @foo.class.metadata.should == 'Foo metadata'
34
+ Foo.metadata.should_be 'Foo metadata'
35
+ @foo.class.metadata.should_be 'Foo metadata'
36
36
  end
37
37
 
38
38
  it "should list all class's own attributes" do
39
- Foo.singleton_class.attributes(false).keys.should == [:metadata]
39
+ Foo.singleton_class.attributes(false).keys.should_be [:metadata]
40
40
  end
41
41
 
42
42
  it "should list all class's own attributes" do
43
- Foo.singleton_class.attributes.keys.should == [:metadata]
43
+ Foo.singleton_class.attributes.keys.should_be [:metadata]
44
44
  end
45
45
 
46
46
  it 'should create Bar class attribute' do
47
47
  Bar.metadata = 'Bar metadata'
48
- Bar.metadata.should == 'Bar metadata'
48
+ Bar.metadata.should_be 'Bar metadata'
49
49
  end
50
50
 
51
51
  it 'should access @bar class attribute via self.class' do
52
52
  @bar.class.metadata = '@bar metadata'
53
- @bar.class.metadata.should == '@bar metadata'
54
- Bar.metadata.should == '@bar metadata'
53
+ @bar.class.metadata.should_be '@bar metadata'
54
+ Bar.metadata.should_be '@bar metadata'
55
55
 
56
56
  Bar.metadata = 'Bar metadata'
57
- Bar.metadata.should == 'Bar metadata'
58
- @bar.class.metadata.should == 'Bar metadata'
57
+ Bar.metadata.should_be 'Bar metadata'
58
+ @bar.class.metadata.should_be 'Bar metadata'
59
59
  end
60
60
 
61
61
  it 'should not allow inherited class attributes to interfere with each other' do
62
62
  Foo.metadata = 'Foo metadata'
63
63
  @bar.class.metadata = '@bar metadata'
64
- @bar.class.metadata.should == '@bar metadata'
65
- Bar.metadata.should == '@bar metadata'
64
+ @bar.class.metadata.should_be '@bar metadata'
65
+ Bar.metadata.should_be '@bar metadata'
66
66
 
67
67
  Bar.metadata = 'Bar metadata'
68
- Bar.metadata.should == 'Bar metadata'
69
- @bar.class.metadata.should == 'Bar metadata'
68
+ Bar.metadata.should_be 'Bar metadata'
69
+ @bar.class.metadata.should_be 'Bar metadata'
70
70
 
71
- Foo.metadata.should == 'Foo metadata'
72
- @foo.class.metadata.should == 'Foo metadata'
71
+ Foo.metadata.should_be 'Foo metadata'
72
+ @foo.class.metadata.should_be 'Foo metadata'
73
73
  end
74
74
 
75
75
  it "should list all class's own attributes" do
76
- Bar.singleton_class.attributes(false).keys.should == [:doc]
76
+ Bar.singleton_class.attributes(false).keys.should_be [:doc]
77
77
  end
78
78
 
79
79
  it "should list all class's singleton attributes" do
80
- Bar.singleton_class.attributes.keys.should == [:doc]
80
+ Bar.singleton_class.attributes.keys.should_be [:doc]
81
81
  end
82
82
  it "should list all class's class_attributes" do
83
- Bar.class_attributes.keys.should == [:metadata, :doc]
83
+ Bar.class_attributes.keys.should_be [:metadata, :doc]
84
84
  end
85
85
  end
86
86
  end
@@ -16,11 +16,11 @@ describe Doodle, "Simple collector" do
16
16
  end
17
17
 
18
18
  it "should define a collector method :item" do
19
- @foo.methods.map{ |x| x.to_sym }.include?(:item).should == true
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
- @foo.list.should == ["Hello", "World"]
23
+ @foo.list.should_be ["Hello", "World"]
24
24
  end
25
25
 
26
26
  end
@@ -37,7 +37,11 @@ describe Doodle, "Typed collector with default collector name" do
37
37
  end
38
38
  @event = Event do
39
39
  location "Stage 1"
40
- location "Stage 2"
40
+ # todo: move this into spec
41
+ # should handle collected arguments with block only
42
+ location do
43
+ name "Stage 2"
44
+ end
41
45
  end
42
46
  end
43
47
  after :each do
@@ -45,11 +49,11 @@ describe Doodle, "Typed collector with default collector name" do
45
49
  end
46
50
 
47
51
  it "should define a collector method :location" do
48
- @event.methods.map{ |x| x.to_sym }.include?(:location).should == true
52
+ @event.methods.map{ |x| x.to_sym }.include?(:location).should_be true
49
53
  end
50
54
 
51
55
  it "should collect items into attribute :list" do
52
- @event.locations.map{|loc| loc.name}.should == ["Stage 1", "Stage 2"]
56
+ @event.locations.map{|loc| loc.name}.should_be ["Stage 1", "Stage 2"]
53
57
  end
54
58
 
55
59
  end
@@ -66,7 +70,7 @@ describe Doodle, "Typed collector with specified collector name" do
66
70
  end
67
71
  end
68
72
  it "should define a collector method :place" do
69
- Event.instance_methods.map{ |x| x.to_sym}.include?(:place).should == true
73
+ Event.instance_methods.map{ |x| x.to_sym}.include?(:place).should_be true
70
74
  end
71
75
  end
72
76
  end
@@ -89,8 +93,8 @@ describe Doodle, "typed collector with specified collector name" do
89
93
  place "Stage 2"
90
94
  end
91
95
  }.should_not raise_error
92
- event.locations.map{|loc| loc.name}.should == ["Stage 1", "Stage 2"]
93
- event.locations.map{|loc| loc.class}.should == [Location, Location]
96
+ event.locations.map{|loc| loc.name}.should_be ["Stage 1", "Stage 2"]
97
+ event.locations.map{|loc| loc.class}.should_be [Location, Location]
94
98
  end
95
99
  end
96
100
  end
@@ -122,10 +126,82 @@ describe Doodle, "typed collector with specified collector name initialized from
122
126
  proc {
123
127
  event = Event(data)
124
128
  }.should_not raise_error
125
- event.locations.map{|loc| loc.name}.should == ["Stage 1", "Stage 2"]
126
- event.locations.map{|loc| loc.class}.should == [Location, Location]
127
- event.locations[0].events[0].kind_of?(Event).should == true
129
+ event.locations.map{|loc| loc.name}.should_be ["Stage 1", "Stage 2"]
130
+ event.locations.map{|loc| loc.class}.should_be [Location, Location]
131
+ event.locations[0].events[0].kind_of?(Event).should_be true
128
132
  end
129
133
  end
130
134
  end
131
135
 
136
+ describe Doodle, "Simple keyed collector" do
137
+ temporary_constant :Foo do
138
+ before :each do
139
+ class Foo < Doodle
140
+ has :list, :collect => :item, :key => :size
141
+ end
142
+ @foo = Foo do
143
+ item "Hello"
144
+ item "World"
145
+ end
146
+ end
147
+ after :each do
148
+ remove_ivars :foo
149
+ end
150
+
151
+ it "should define a collector method :item" do
152
+ @foo.methods.map{ |x| x.to_sym }.include?(:item).should_be true
153
+ end
154
+
155
+ it "should collect items into attribute :list" do
156
+ @foo.list.should_be( { 5 => "World" } )
157
+ end
158
+
159
+ end
160
+ end
161
+
162
+ describe Doodle, "Simple keyed collector #2" do
163
+ temporary_constant :Foo, :Item do
164
+ before :each do
165
+ class Item < Doodle
166
+ has :name
167
+ end
168
+ class Foo < Doodle
169
+ has :list, :collect => Item, :key => :name
170
+ end
171
+ end
172
+
173
+ it "should define a collector method :item" do
174
+ foo = Foo.new
175
+ foo.methods.map{ |x| x.to_sym }.include?(:item).should_be true
176
+ foo.respond_to?(:item).should_be true
177
+ end
178
+
179
+ it "should collect items into attribute :list #1" do
180
+ foo = Foo do
181
+ item "Hello"
182
+ item "World"
183
+ end
184
+ foo.list.to_a.map{ |k, v| [k, v.class, v.name] }.should_be( [["Hello", Item, "Hello"], ["World", Item, "World"]] )
185
+ end
186
+
187
+ it "should collect keyword argument enumerable into attribute :list" do
188
+ foo = Foo(:list =>
189
+ [
190
+ { :name => "Hello" },
191
+ { :name => "World" }
192
+ ]
193
+ )
194
+ foo.list.to_a.map{ |k, v| [k, v.class, v.name] }.should_be( [["Hello", Item, "Hello"], ["World", Item, "World"]] )
195
+ end
196
+
197
+ it "should collect positional argument enumerable into attribute :list" do
198
+ foo = Foo([
199
+ { :name => "Hello" },
200
+ { :name => "World" }
201
+ ]
202
+ )
203
+ foo.list.to_a.map{ |k, v| [k, v.class, v.name] }.should_be( [["Hello", Item, "Hello"], ["World", Item, "World"]] )
204
+ end
205
+
206
+ end
207
+ end