doodle 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.
@@ -0,0 +1,243 @@
1
+ # AUTHOR
2
+ # jan molic /mig/at/1984/dot/cz/
3
+ #
4
+ # DESCRIPTION
5
+ # Hash with preserved order and some array-like extensions
6
+ # Public domain.
7
+ #
8
+ # THANKS
9
+ # Andrew Johnson for his suggestions and fixes of Hash[],
10
+ # merge, to_a, inspect and shift
11
+ class OrderedHash < ::Hash
12
+ #--{{{
13
+ attr_accessor :order
14
+
15
+ class << self
16
+ #--{{{
17
+ def [] *args
18
+ #--{{{
19
+ hsh = OrderedHash.new
20
+ if Hash === args[0]
21
+ hsh.replace args[0]
22
+ elsif (args.size % 2) != 0
23
+ raise ArgumentError, "odd number of elements for Hash"
24
+ else
25
+ hsh[args.shift] = args.shift while args.size > 0
26
+ end
27
+ hsh
28
+ #--}}}
29
+ end
30
+ #--}}}
31
+ end
32
+ # def initialize
33
+ ##--{{{
34
+ # @order = []
35
+ ##--}}}
36
+ # end
37
+ def initialize(*a, &b)
38
+ #--{{{
39
+ super
40
+ @order = []
41
+ #--}}}
42
+ end
43
+ def store_only a,b
44
+ #--{{{
45
+ store a,b
46
+ #--}}}
47
+ end
48
+ alias orig_store store
49
+ def store a,b
50
+ #--{{{
51
+ @order.push a unless has_key? a
52
+ super a,b
53
+ #--}}}
54
+ end
55
+ alias []= store
56
+ def == hsh2
57
+ #--{{{
58
+ return false if @order != hsh2.order
59
+ super hsh2
60
+ #--}}}
61
+ end
62
+ def clear
63
+ #--{{{
64
+ @order = []
65
+ super
66
+ #--}}}
67
+ end
68
+ def delete key
69
+ #--{{{
70
+ @order.delete key
71
+ super
72
+ #--}}}
73
+ end
74
+ def each_key
75
+ #--{{{
76
+ @order.each { |k| yield k }
77
+ self
78
+ #--}}}
79
+ end
80
+ def each_value
81
+ #--{{{
82
+ @order.each { |k| yield self[k] }
83
+ self
84
+ #--}}}
85
+ end
86
+ def each
87
+ #--{{{
88
+ @order.each { |k| yield k,self[k] }
89
+ self
90
+ #--}}}
91
+ end
92
+ alias each_pair each
93
+ def delete_if
94
+ #--{{{
95
+ @order.clone.each { |k|
96
+ delete k if yield
97
+ }
98
+ self
99
+ #--}}}
100
+ end
101
+ def values
102
+ #--{{{
103
+ ary = []
104
+ @order.each { |k| ary.push self[k] }
105
+ ary
106
+ #--}}}
107
+ end
108
+ def keys
109
+ #--{{{
110
+ @order
111
+ #--}}}
112
+ end
113
+ def invert
114
+ #--{{{
115
+ hsh2 = Hash.new
116
+ @order.each { |k| hsh2[self[k]] = k }
117
+ hsh2
118
+ #--}}}
119
+ end
120
+ def reject &block
121
+ #--{{{
122
+ self.dup.delete_if &block
123
+ #--}}}
124
+ end
125
+ def reject! &block
126
+ #--{{{
127
+ hsh2 = reject &block
128
+ self == hsh2 ? nil : hsh2
129
+ #--}}}
130
+ end
131
+ def replace hsh2
132
+ #--{{{
133
+ @order = hsh2.keys
134
+ super hsh2
135
+ #--}}}
136
+ end
137
+ def shift
138
+ #--{{{
139
+ key = @order.first
140
+ key ? [key,delete(key)] : super
141
+ #--}}}
142
+ end
143
+ def unshift k,v
144
+ #--{{{
145
+ unless self.include? k
146
+ @order.unshift k
147
+ orig_store(k,v)
148
+ true
149
+ else
150
+ false
151
+ end
152
+ #--}}}
153
+ end
154
+ def push k,v
155
+ #--{{{
156
+ unless self.include? k
157
+ @order.push k
158
+ orig_store(k,v)
159
+ true
160
+ else
161
+ false
162
+ end
163
+ #--}}}
164
+ end
165
+ def pop
166
+ #--{{{
167
+ key = @order.last
168
+ key ? [key,delete(key)] : nil
169
+ #--}}}
170
+ end
171
+ def to_a
172
+ #--{{{
173
+ ary = []
174
+ each { |k,v| ary << [k,v] }
175
+ ary
176
+ #--}}}
177
+ end
178
+ def to_s
179
+ #--{{{
180
+ self.to_a.to_s
181
+ #--}}}
182
+ end
183
+ def inspect
184
+ #--{{{
185
+ ary = []
186
+ each {|k,v| ary << k.inspect + "=>" + v.inspect}
187
+ '{' + ary.join(", ") + '}'
188
+ #--}}}
189
+ end
190
+ def update hsh2
191
+ #--{{{
192
+ hsh2.each { |k,v| self[k] = v }
193
+ self
194
+ #--}}}
195
+ end
196
+ alias :merge! update
197
+ def merge(hsh2)
198
+ #--{{{
199
+ self.dup.update(hsh2)
200
+ #--}}}
201
+ end
202
+ def select
203
+ #--{{{
204
+ ary = []
205
+ each { |k,v| ary << [k,v] if yield k,v }
206
+ ary
207
+ #--}}}
208
+ end
209
+ def class
210
+ #--{{{
211
+ Hash
212
+ #--}}}
213
+ end
214
+
215
+ attr_accessor "to_yaml_style"
216
+ def yaml_inline= bool
217
+ if respond_to?("to_yaml_style")
218
+ self.to_yaml_style = :inline
219
+ else
220
+ unless defined? @__yaml_inline_meth
221
+ @__yaml_inline_meth =
222
+ lambda {|opts|
223
+ YAML::quick_emit(object_id, opts) {|emitter|
224
+ emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
225
+ }
226
+ }
227
+ class << self
228
+ def to_yaml opts = {}
229
+ begin
230
+ @__yaml_inline ? @__yaml_inline_meth[ opts ] : super
231
+ rescue
232
+ @to_yaml_style = :inline
233
+ super
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
239
+ @__yaml_inline = bool
240
+ end
241
+ def yaml_inline!() self.yaml_inline = true end
242
+ #--}}}
243
+ end # class OrderedHash
@@ -0,0 +1,19 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '../.'))
2
+
3
+ require 'lib/doodle'
4
+ require 'date'
5
+
6
+ def undefine_const(*consts)
7
+ consts.each do |const|
8
+ if Object.const_defined?(const)
9
+ Object.send(:remove_const, const)
10
+ end
11
+ end
12
+ end
13
+
14
+ def raise_if_defined(*args)
15
+ defined, undefined = args.partition{ |x| Object.const_defined?(x)}
16
+ raise "Namespace pollution: #{defined.join(', ')}" if defined.size > 0
17
+ end
18
+
19
+
@@ -0,0 +1,125 @@
1
+ require 'lib/spec_helper'
2
+
3
+ describe 'arg_order' do
4
+ before :each do
5
+ raise_if_defined :Foo
6
+ class Foo < Doodle::Base
7
+ has :name
8
+ has :extra
9
+ has :value
10
+ arg_order :value, :name
11
+ end
12
+ end
13
+ after :each do
14
+ undefine_const :Foo
15
+ end
16
+ it 'should specify order of positional arguments' do
17
+ foo = Foo.new 1, 2, 3
18
+ foo.value.should == 1
19
+ foo.name.should == 2
20
+ foo.extra.should == 3
21
+ end
22
+
23
+ it 'should allow only symbols as arguments to arg_order' do
24
+ proc { Foo.arg_order Foo}.should raise_error(Doodle::InvalidOrderError)
25
+ proc { Foo.arg_order 1}.should raise_error(Doodle::InvalidOrderError)
26
+ proc { Foo.arg_order Date.new}.should raise_error(Doodle::InvalidOrderError)
27
+ end
28
+
29
+ it 'should not allow invalid positional arguments' do
30
+ proc { Foo.arg_order :smoo}.should raise_error(Doodle::InvalidOrderError)
31
+ proc { Foo.arg_order :name, :value}.should_not raise_error
32
+ end
33
+ end
34
+
35
+ describe 'arg_order' do
36
+ before :each do
37
+ raise_if_defined :Foo, :Bar
38
+ class Foo < Doodle::Base
39
+ has :name
40
+ end
41
+ class Bar < Foo
42
+ has :value
43
+ end
44
+ end
45
+ after :each do
46
+ undefine_const(:Bar)
47
+ undefine_const(:Foo)
48
+ end
49
+ it 'should specify order of positional arguments' do
50
+ f = Bar.new 1, 2
51
+ f.name.should == 1
52
+ f.value.should == 2
53
+ end
54
+ end
55
+
56
+ describe 'arg_order' do
57
+ before :each do
58
+ raise_if_defined(:Foo, :Bar)
59
+ class Foo < Doodle::Base
60
+ has :name
61
+ end
62
+ class Bar < Foo
63
+ has :value
64
+ arg_order :value, :name
65
+ end
66
+ end
67
+ after :each do
68
+ undefine_const(:Bar)
69
+ undefine_const(:Foo)
70
+ end
71
+ it 'should specify order of positional arguments' do
72
+ f = Bar.new 1, 2
73
+ f.value.should == 1
74
+ f.name.should == 2
75
+ end
76
+
77
+ end
78
+
79
+ describe 'arg_order' do
80
+ before :each do
81
+ raise_if_defined(:Foo, :Bar)
82
+ class Foo < Doodle::Base
83
+ has :name, :default => proc { self.class.to_s.downcase }
84
+ end
85
+ class Bar < Foo
86
+ has :value
87
+ arg_order :value, :name
88
+ end
89
+ end
90
+ after :each do
91
+ undefine_const(:Bar, :Foo)
92
+ end
93
+
94
+ it 'should specify order of positional arguments' do
95
+ f = Bar.new 1
96
+ f.value.should == 1
97
+ f.name.should == "bar"
98
+ end
99
+
100
+ end
101
+
102
+ describe 'arg_order' do
103
+ after :each do
104
+ undefine_const(:Bar, :Foo)
105
+ end
106
+ before :each do
107
+ raise_if_defined(:Foo, :Bar)
108
+ class Foo < Doodle::Base
109
+ has :name
110
+ end
111
+ class Bar < Foo
112
+ has :value
113
+ arg_order :value, :name
114
+ end
115
+ end
116
+
117
+ it 'should specify order of positional arguments' do
118
+ f = Bar.new 1, "bar"
119
+ f.value.should == 1
120
+ f.name.should == "bar"
121
+ end
122
+
123
+ end
124
+
125
+ raise_if_defined(:Foo, :Bar)
@@ -0,0 +1,106 @@
1
+ require 'lib/spec_helper'
2
+
3
+ describe Doodle::Attribute, 'basics' do
4
+ after :each do
5
+ undefine_const(:Bar)
6
+ undefine_const(:Foo)
7
+ end
8
+ before(:each) do
9
+ raise_if_defined(:Foo, :Bar)
10
+
11
+ class Foo
12
+ include Doodle::Helper
13
+ has :name, :default => 'Hello'
14
+ class << self
15
+ has :metadata
16
+ end
17
+ end
18
+ class Bar < Foo
19
+ has :info
20
+ class << self
21
+ has :doc
22
+ end
23
+ end
24
+
25
+ @goo = Foo.new
26
+ @baz = Bar.new :info => 'Hi'
27
+ end
28
+
29
+ it 'should have default name' do
30
+ #pending 'making it work'
31
+ #p [:name, :default, @goo.attributes[:name].default]
32
+ @goo.attributes[:name].default.should == 'Hello'
33
+ end
34
+
35
+ it 'should have default name' do
36
+ #pending 'making it work'
37
+ @goo.name.should == 'Hello'
38
+ end
39
+
40
+ it 'should have name required == false (because has default)' do
41
+ #pending 'to do required/optional'
42
+ @goo.attributes[:name].required?.should == false
43
+ end
44
+
45
+ it 'should have info required == true' do
46
+ #pending 'to do required/optional'
47
+ @baz.attributes[:info].required?.should == true
48
+ end
49
+
50
+ it 'should have name.optional? == true (because has default)' do
51
+ #pending 'to do required/optional'
52
+ @goo.attributes[:name].optional?.should == true
53
+ end
54
+
55
+ it 'should have info.optional? == false' do
56
+ #pending 'to do required/optional'
57
+ @baz.attributes[:info].optional?.should == false
58
+ end
59
+
60
+ it "should have parents in order" do
61
+ Bar.parents.should == [Foo, Object]
62
+ end
63
+
64
+ it "should have Bar's meta parents in reverse order of definition" do
65
+ @baz.meta.parents.should == [Bar.singleton_class.singleton_class, Bar.singleton_class, Foo.singleton_class]
66
+ end
67
+
68
+ it 'should have inherited meta local_attributes in order of definition' do
69
+ @baz.meta.class_eval { collect_inherited(:local_attributes).map { |x| x[0]} }.should == [:metadata, :doc]
70
+ end
71
+
72
+ it 'should have inherited meta attributes in order of definition' do
73
+ @baz.meta.attributes.keys.should == [:metadata, :doc]
74
+ end
75
+ end
76
+
77
+ describe Doodle::Attribute, 'attribute order' do
78
+ before :each do
79
+ undefine_const(:A)
80
+ undefine_const(:B)
81
+ undefine_const(:C)
82
+
83
+ class A < Doodle::Base
84
+ has :a
85
+ end
86
+
87
+ class B < A
88
+ has :b
89
+ end
90
+
91
+ class C < B
92
+ has :c
93
+ end
94
+
95
+ end
96
+
97
+ it 'should keep order of inherited attributes' do
98
+ C.parents.should == [B, A, Doodle::Base, Object]
99
+ end
100
+
101
+ it 'should keep order of inherited attributes' do
102
+ C.attributes.keys.should == [:a, :b, :c]
103
+ end
104
+ end
105
+
106
+ raise_if_defined(:Foo, :Bar, :A, :B, :C)