doodle 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)