doodle 0.0.10 → 0.1.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/CREDITS +22 -0
- data/{ChangeLog → History.txt} +22 -3
- data/License.txt +20 -0
- data/Manifest.txt +61 -0
- data/README.txt +166 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +77 -0
- data/config/requirements.rb +15 -0
- data/examples/doodle-errors.rb +25 -0
- data/examples/event-location.rb +3 -7
- data/examples/example-01.rb +1 -1
- data/examples/example-01.rdoc +3 -3
- data/examples/example-02.rb +15 -4
- data/examples/example-02.rdoc +17 -5
- data/examples/mail-datatypes.rb +104 -0
- data/examples/mail.rb +85 -0
- data/examples/parent.rb +40 -0
- data/examples/profile-options.rb +67 -0
- data/examples/smtp_tls.rb +65 -0
- data/examples/test-datatypes.rb +55 -0
- data/examples/yaml-example.rb +40 -0
- data/examples/yaml-example2.rb +42 -0
- data/lib/doodle.rb +364 -301
- data/lib/doodle/datatypes.rb +148 -0
- data/lib/doodle/rfc822.rb +31 -0
- data/lib/doodle/utils.rb +13 -0
- data/lib/doodle/version.rb +9 -0
- data/log/debug.log +0 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/arg_order_spec.rb +5 -5
- data/spec/attributes_spec.rb +66 -24
- data/spec/bugs_spec.rb +109 -6
- data/spec/class_spec.rb +7 -4
- data/spec/class_validation_spec.rb +46 -0
- data/spec/class_var_spec.rb +76 -0
- data/spec/collector_spec.rb +16 -30
- data/spec/conversion_spec.rb +8 -3
- data/spec/defaults_spec.rb +4 -4
- data/spec/doodle_context_spec.rb +3 -4
- data/spec/doodle_spec.rb +25 -15
- data/spec/extra_args_spec.rb +1 -1
- data/spec/factory_spec.rb +3 -3
- data/spec/init_spec.rb +11 -11
- data/spec/new_doodle_spec.rb +19 -0
- data/spec/required_spec.rb +1 -1
- data/spec/serialization_spec.rb +3 -6
- data/spec/singleton_spec.rb +5 -5
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/superclass_spec.rb +6 -5
- data/spec/validation2_spec.rb +248 -0
- data/spec/validation_spec.rb +26 -37
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- metadata +76 -20
- data/COPYING +0 -18
- data/README +0 -57
- data/examples/event.rb +0 -39
- data/examples/example-03.rb +0 -45
- data/examples/example-03.rdoc +0 -55
- data/lib/semantic.cache +0 -8
data/spec/required_spec.rb
CHANGED
data/spec/serialization_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'yaml'
|
|
4
4
|
describe Doodle, "Serialization" do
|
5
5
|
temporary_constant :Foo do
|
6
6
|
before :each do
|
7
|
-
class Foo < Doodle
|
7
|
+
class Foo < Doodle
|
8
8
|
has :var, :kind => Integer
|
9
9
|
end
|
10
10
|
@foo = Foo 42
|
@@ -15,11 +15,8 @@ describe Doodle, "Serialization" do
|
|
15
15
|
|
16
16
|
it "should be serializable to yaml" do
|
17
17
|
# is this a bug in the MRI yaml implementation? why the space after Foo?
|
18
|
-
|
19
|
-
|
20
|
-
else
|
21
|
-
@foo.to_yaml.should == "--- !ruby/object:Foo \nvar: 42\n"
|
22
|
-
end
|
18
|
+
# (note: all on one line to pass coverage)
|
19
|
+
RUBY_PLATFORM == 'java' ? @foo.to_yaml.should == "--- !ruby/object:Foo\nvar: 42\n" : @foo.to_yaml.should == "--- !ruby/object:Foo \nvar: 42\n"
|
23
20
|
end
|
24
21
|
|
25
22
|
it "should be loadable from yaml" do
|
data/spec/singleton_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + "/spec_helper.rb"
|
|
3
3
|
describe Doodle, "singletons" do
|
4
4
|
temporary_constant :Foo do
|
5
5
|
it "should allow creating attributes on classes via inheritance" do
|
6
|
-
class Foo < Doodle
|
6
|
+
class Foo < Doodle
|
7
7
|
class << self
|
8
8
|
has :c1
|
9
9
|
end
|
@@ -17,7 +17,7 @@ describe Doodle, "singletons" do
|
|
17
17
|
|
18
18
|
it "should allow creating attributes on classes via module inclusion" do
|
19
19
|
class Foo
|
20
|
-
include Doodle::
|
20
|
+
include Doodle::Core
|
21
21
|
class << self
|
22
22
|
has :c2
|
23
23
|
end
|
@@ -30,13 +30,13 @@ describe Doodle, "singletons" do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should allow creating attributes on singletons via inheritance" do
|
33
|
-
class Foo < Doodle
|
33
|
+
class Foo < Doodle
|
34
34
|
end
|
35
35
|
foo = Foo.new
|
36
36
|
class << foo
|
37
37
|
has :i1
|
38
38
|
end
|
39
|
-
foo.attributes.should ==
|
39
|
+
foo.attributes.keys.should == [:i1]
|
40
40
|
foo.singleton_class.attributes.should_not == OrderedHash.new
|
41
41
|
foo.singleton_class.attributes.map{ |name, attr| name }.should == [:i1]
|
42
42
|
foo.i1 = 1
|
@@ -45,7 +45,7 @@ describe Doodle, "singletons" do
|
|
45
45
|
|
46
46
|
it "should allow creating attributes on a singleton's singleton via module inclusion" do
|
47
47
|
class Foo
|
48
|
-
include Doodle::
|
48
|
+
include Doodle::Core
|
49
49
|
end
|
50
50
|
foo = Foo.new
|
51
51
|
class << foo
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
gem 'rspec'
|
6
|
+
require 'spec'
|
7
|
+
end
|
8
|
+
|
9
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
10
|
+
require 'doodle'
|
11
|
+
require 'date'
|
12
|
+
|
13
|
+
# functions to help clean up namespace after defining classes
|
14
|
+
def undefine_const(*consts)
|
15
|
+
consts.each do |const|
|
16
|
+
if Object.const_defined?(const)
|
17
|
+
Object.send(:remove_const, const)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def raise_if_defined(*args)
|
23
|
+
defined, undefined = args.partition{ |x| Object.const_defined?(x)}
|
24
|
+
raise "Namespace pollution: #{defined.join(', ')}" if defined.size > 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def temporary_constants(*args, &block)
|
28
|
+
before :each do
|
29
|
+
raise_if_defined(*args)
|
30
|
+
end
|
31
|
+
after :each do
|
32
|
+
undefine_const(*args)
|
33
|
+
end
|
34
|
+
raise_if_defined(*args)
|
35
|
+
yield
|
36
|
+
raise_if_defined(*args)
|
37
|
+
end
|
38
|
+
alias :temporary_constant :temporary_constants
|
39
|
+
|
40
|
+
def remove_ivars(*args)
|
41
|
+
args.each do |ivar|
|
42
|
+
remove_instance_variable "@#{ivar}"
|
43
|
+
end
|
44
|
+
end
|
data/spec/superclass_spec.rb
CHANGED
@@ -3,21 +3,22 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
3
3
|
describe 'Doodle', 'parents' do
|
4
4
|
temporary_constant :Foo do
|
5
5
|
before :each do
|
6
|
-
class Foo < Doodle
|
6
|
+
class Foo < Doodle
|
7
7
|
end
|
8
8
|
@foo = Foo.new
|
9
9
|
@sc = class << @foo; self; end
|
10
10
|
@scc = class << @sc; self; end
|
11
|
-
@sclass_doodle_root = class << Doodle
|
11
|
+
@sclass_doodle_root = class << Doodle; self; end
|
12
12
|
@sclass_foo = class << @foo; class << self; self; end; end
|
13
13
|
end
|
14
14
|
|
15
|
-
it 'should have singleton
|
16
|
-
@sc.parents.should == [
|
15
|
+
it 'should have no singleton parents ' do
|
16
|
+
@sc.parents.should == []
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should have singleton class's singleton class parents == []" do
|
20
|
-
|
20
|
+
expected_parents = RUBY_VERSION <= "1.8.6" ? [] : [Module, Object, BasicObject]
|
21
|
+
@scc.parents.should == expected_parents
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
# this file is frankly a bit of a mess - trying to do too many things
|
2
|
+
# at once
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
5
|
+
|
6
|
+
shared_code = proc do
|
7
|
+
class DateRange < Doodle
|
8
|
+
has :start_date, :kind => Date do
|
9
|
+
from String do |s|
|
10
|
+
Date.parse(s)
|
11
|
+
end
|
12
|
+
from Array do |y,m,d|
|
13
|
+
#p [:from, Array, y, m, d]
|
14
|
+
Date.new(y, m, d)
|
15
|
+
end
|
16
|
+
from Integer do |jd|
|
17
|
+
#Doodle::Debug.d { [:converting_from, Integer, jd] }
|
18
|
+
Date.new(*Date.send(:jd_to_civil, jd))
|
19
|
+
end
|
20
|
+
#Doodle::Debug.d { [:start_date, self, self.class] }
|
21
|
+
default { Date.today }
|
22
|
+
end
|
23
|
+
has :end_date, :kind => Date do
|
24
|
+
from String do |s|
|
25
|
+
Date.parse(s)
|
26
|
+
end
|
27
|
+
from Array do |y,m,d|
|
28
|
+
#p [:from, Array, y, m, d]
|
29
|
+
Date.new(y, m, d)
|
30
|
+
end
|
31
|
+
from Integer do |jd|
|
32
|
+
#Doodle::Debug.d { [:converting_from, Integer, jd] }
|
33
|
+
Date.new(*Date.send(:jd_to_civil, jd))
|
34
|
+
end
|
35
|
+
default { start_date }
|
36
|
+
end
|
37
|
+
must "have end_date >= start_date" do
|
38
|
+
end_date >= start_date
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe :DateRange, ' validation' do
|
44
|
+
temporary_constants :DateRange do
|
45
|
+
|
46
|
+
before :each, &shared_code
|
47
|
+
|
48
|
+
it 'should not raise an exception if end_date >= start_date' do
|
49
|
+
proc { DateRange.new('2007-01-01', '2007-01-02') }.should_not raise_error
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should raise an exception if end_date < start_date' do
|
53
|
+
proc { DateRange.new('2007-11-01', '2007-01-02') }.should raise_error
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
[:DateRange, :DerivedDateRange, :SecondLevelDerivedDateRange].each do |klass|
|
59
|
+
|
60
|
+
describe klass, ' validation' do
|
61
|
+
temporary_constants :DateRange, :DerivedDateRange, :SecondLevelDerivedDateRange do
|
62
|
+
|
63
|
+
before :each, &shared_code
|
64
|
+
before :each do
|
65
|
+
|
66
|
+
class DerivedDateRange < DateRange
|
67
|
+
end
|
68
|
+
|
69
|
+
class SecondLevelDerivedDateRange < DateRange
|
70
|
+
end
|
71
|
+
|
72
|
+
@klass = self.class.const_get(klass)
|
73
|
+
@meth = @klass.method(:new)
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should not raise an exception if end_date > start_date' do
|
78
|
+
proc { @meth.call('2007-01-01', '2007-01-02') }.should_not raise_error
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should not raise an exception if end_date == start_date' do
|
82
|
+
proc { @klass.new('2007-01-02', '2007-01-02') }.should_not raise_error
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should raise an exception if end_date is < start_date' do
|
86
|
+
proc { @klass.new('2007-01-03', '2007-01-02') }.should raise_error(Doodle::ValidationError)
|
87
|
+
end
|
88
|
+
|
89
|
+
# distinguish between objects which have invalid classes and objects which have classes
|
90
|
+
# which can be converted (i.e. in from clause) but which have unconvertible values
|
91
|
+
|
92
|
+
invalid_dates = [Object.new, Object, Hash.new, { :key => 42 }, 1.2, :today]
|
93
|
+
keys = [:start_date, :end_date]
|
94
|
+
|
95
|
+
keys.each do |key|
|
96
|
+
invalid_dates.each do |o|
|
97
|
+
it "should not validate #{o.inspect} for #{key}" do
|
98
|
+
proc { @klass.new(key => o) }.should raise_error(Doodle::ValidationError)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
unconvertible_dates = [
|
104
|
+
'Hello',
|
105
|
+
[],
|
106
|
+
'tomorrow',
|
107
|
+
'today',
|
108
|
+
'yesterday',
|
109
|
+
"-9999999999999991-12-31",
|
110
|
+
"9999999999999990-12-31",
|
111
|
+
9999999999999999999,
|
112
|
+
-9999999999999999999,
|
113
|
+
]
|
114
|
+
keys = [:start_date, :end_date]
|
115
|
+
|
116
|
+
keys.each do |key|
|
117
|
+
unconvertible_dates.each do |o|
|
118
|
+
it "should not convert #{o.inspect} to #{key}" do
|
119
|
+
proc { @klass.new(key => o) }.should raise_error(Doodle::ConversionError)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# could do with more bad_dates...
|
125
|
+
# note, these are splatted so need [] around args
|
126
|
+
bad_date_pairs = [
|
127
|
+
[[2007,1,2],[2007,1,1]],
|
128
|
+
[{ :end_date => '2007-01-01' }],
|
129
|
+
[{ :start_date => '2007-01-01', :end_date => '2006-01-01' }]
|
130
|
+
]
|
131
|
+
|
132
|
+
bad_date_pairs.each do |o|
|
133
|
+
it "should not allow #{o.inspect[1..-2]}" do
|
134
|
+
proc { @klass.new(*o) }.should raise_error(Doodle::ValidationError)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# note, these are splatted so need [] around args
|
139
|
+
good_dates = [
|
140
|
+
[[2007,1,1],[2007,1,2]],
|
141
|
+
[{ :start_date => '2007-01-01' }],
|
142
|
+
[{ :start_date => '2007-01-01', :end_date => '2007-01-01' }],
|
143
|
+
[{ :start_date => -1, :end_date => 0 }]
|
144
|
+
]
|
145
|
+
|
146
|
+
good_dates.each do |o|
|
147
|
+
it "should allow #{o.inspect[1..-2]}" do
|
148
|
+
proc { @klass.new(*o) }.should_not raise_error
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe klass, ' defaults' do
|
155
|
+
temporary_constants :AttributeDate, :Base, :DateRange, :DerivedDateRange, :SecondLevelDerivedDateRange do
|
156
|
+
before :each, &shared_code
|
157
|
+
before :each do
|
158
|
+
class DerivedDateRange < DateRange
|
159
|
+
end
|
160
|
+
|
161
|
+
class SecondLevelDerivedDateRange < DateRange
|
162
|
+
end
|
163
|
+
|
164
|
+
@klass = self.class.const_get(klass)
|
165
|
+
@dr = @klass.new
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'should have default start_date == Date.today' do
|
169
|
+
@dr.start_date == Date.today
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should have default end_date == start_date' do
|
173
|
+
@dr.end_date.should == @dr.start_date
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe klass, ' setting attributes after initialization' do
|
179
|
+
temporary_constants :AttributeDate, :Base, :DateRange, :DerivedDateRange, :SecondLevelDerivedDateRange do
|
180
|
+
before :each, &shared_code
|
181
|
+
before :each do
|
182
|
+
class DerivedDateRange < DateRange
|
183
|
+
end
|
184
|
+
|
185
|
+
class SecondLevelDerivedDateRange < DateRange
|
186
|
+
end
|
187
|
+
|
188
|
+
@klass = self.class.const_get(klass)
|
189
|
+
@dr = @klass.new
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should not allow end_date < start_date" do
|
193
|
+
proc { @dr.end_date = @dr.start_date - 1 }.should raise_error(Doodle::ValidationError)
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should allow end_date >= start_date" do
|
197
|
+
proc { @dr.end_date = @dr.start_date + 1 }.should_not raise_error
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should allow changing start_date (and have dependent end_date follow)" do
|
201
|
+
proc { @dr.start_date = @dr.start_date + 1 }.should_not raise_error
|
202
|
+
@dr.end_date.should == @dr.start_date
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should not raise an error when changing start_date and changing end_date using defer_validation" do
|
206
|
+
proc {
|
207
|
+
@dr.defer_validation do
|
208
|
+
self.start_date = self.start_date + 1
|
209
|
+
self.end_date = self.start_date
|
210
|
+
end
|
211
|
+
}.should_not raise_error
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should allow changing start_date and changing end_date using defer_validation" do
|
215
|
+
@dr.defer_validation do
|
216
|
+
start_date start_date + 1
|
217
|
+
end_date start_date
|
218
|
+
end
|
219
|
+
@dr.start_date.should >= @dr.end_date
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should not allow changing start_date to be > end_date" do
|
223
|
+
proc {
|
224
|
+
@dr.end_date = @dr.start_date
|
225
|
+
@dr.start_date = @dr.start_date + 1
|
226
|
+
}.should raise_error(Doodle::ValidationError)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should not allow changing start_date to be > end_date" do
|
230
|
+
proc {
|
231
|
+
@dr.instance_eval {
|
232
|
+
end_date start_date
|
233
|
+
start_date start_date + 1
|
234
|
+
}
|
235
|
+
}.should raise_error(Doodle::ValidationError)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should not allow changing end_date to be < start_date" do
|
239
|
+
proc {
|
240
|
+
@dr.instance_eval {
|
241
|
+
end_date start_date - 1
|
242
|
+
}
|
243
|
+
}.should raise_error(Doodle::ValidationError)
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
data/spec/validation_spec.rb
CHANGED
@@ -1,52 +1,41 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
|
3
3
|
describe :DateRange, 'validation & conversions' do
|
4
|
-
temporary_constants :
|
4
|
+
temporary_constants :DateRange do
|
5
5
|
|
6
6
|
before :each do
|
7
|
-
module ClassMethods
|
8
|
-
def date(*a, &b)
|
9
|
-
# if a.size > 0
|
10
|
-
name = a.shift
|
11
|
-
# else
|
12
|
-
# name = :date
|
13
|
-
# end
|
14
|
-
td = has(name, :kind => Date, *a) do
|
15
|
-
# it is a bit clumsy to define these conversions &
|
16
|
-
# conditions for every attribute/typedef - could define a
|
17
|
-
# subclass of Typedef which does this by default (so we
|
18
|
-
# instances can override or defer to class level conversions
|
19
|
-
# and conditions)
|
20
|
-
from String do |s|
|
21
|
-
Date.parse(s)
|
22
|
-
end
|
23
|
-
from Array do |y,m,d|
|
24
|
-
#p [:from, Array, y, m, d]
|
25
|
-
Date.new(y, m, d)
|
26
|
-
end
|
27
|
-
from Integer do |jd|
|
28
|
-
Doodle::Debug.d { [:converting_from, Integer, jd] }
|
29
|
-
Date.new(*Date.jd_to_civil(jd))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
Doodle::Debug.d { [:date, td] }
|
33
|
-
td.instance_eval(&b) if block_given? # user's block should override default
|
34
|
-
end
|
35
|
-
end
|
36
7
|
|
37
|
-
class
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
class DateRange < Base
|
42
|
-
date :start_date do
|
8
|
+
class DateRange < Doodle
|
9
|
+
has :start_date, :kind => Date do
|
43
10
|
Doodle::Debug.d { [:start_date, self, self.class] }
|
11
|
+
from String do |s|
|
12
|
+
Date.parse(s)
|
13
|
+
end
|
14
|
+
from Array do |y,m,d|
|
15
|
+
#p [:from, Array, y, m, d]
|
16
|
+
Date.new(y, m, d)
|
17
|
+
end
|
18
|
+
from Integer do |jd|
|
19
|
+
Doodle::Debug.d { [:converting_from, Integer, jd] }
|
20
|
+
Date.new(*Date.send(:jd_to_civil, jd))
|
21
|
+
end
|
44
22
|
default { Date.today }
|
45
23
|
must "be >= 2007-01-01" do |d|
|
46
24
|
d >= Date.new(2007, 01, 01)
|
47
25
|
end
|
48
26
|
end
|
49
|
-
|
27
|
+
has :end_date, { :kind => Date } do
|
28
|
+
from String do |s|
|
29
|
+
Date.parse(s)
|
30
|
+
end
|
31
|
+
from Array do |y,m,d|
|
32
|
+
#p [:from, Array, y, m, d]
|
33
|
+
Date.new(y, m, d)
|
34
|
+
end
|
35
|
+
from Integer do |jd|
|
36
|
+
Doodle::Debug.d { [:converting_from, Integer, jd] }
|
37
|
+
Date.new(*Date.send(:jd_to_civil, jd))
|
38
|
+
end
|
50
39
|
default { start_date }
|
51
40
|
end
|
52
41
|
must "have end_date >= start_date" do
|