sequel 0.2.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,7 +11,20 @@ PGSQL_DB.create_table :test do
11
11
  index :value
12
12
  end
13
13
 
14
- context "A MySQL dataset" do
14
+ context "A PostgreSQL database" do
15
+ setup do
16
+ @db = PGSQL_DB
17
+ end
18
+
19
+ specify "should provide disconnect functionality" do
20
+ @db.tables
21
+ @db.pool.size.should == 1
22
+ @db.disconnect
23
+ @db.pool.size.should == 0
24
+ end
25
+ end
26
+
27
+ context "A PostgreSQL dataset" do
15
28
  setup do
16
29
  @d = PGSQL_DB[:test]
17
30
  @d.delete # remove all records
@@ -25,24 +38,19 @@ context "A MySQL dataset" do
25
38
  @d.count.should == 3
26
39
  end
27
40
 
28
- # specify "should return the last inserted id when inserting records" do
29
- # id = @d << {:name => 'abc', :value => 1.23}
30
- # id.should == @d.first[:id]
31
- # end
32
- #
33
-
34
- specify "should return all records" do
41
+ specify "should return the correct records" do
42
+ @d.to_a.should == []
35
43
  @d << {:name => 'abc', :value => 123}
36
44
  @d << {:name => 'abc', :value => 456}
37
45
  @d << {:name => 'def', :value => 789}
38
-
39
- @d.order(:value).all.should == [
46
+
47
+ @d.order(:value).to_a.should == [
40
48
  {:name => 'abc', :value => 123},
41
49
  {:name => 'abc', :value => 456},
42
50
  {:name => 'def', :value => 789}
43
51
  ]
44
52
  end
45
-
53
+
46
54
  specify "should update records correctly" do
47
55
  @d << {:name => 'abc', :value => 123}
48
56
  @d << {:name => 'abc', :value => 456}
@@ -84,4 +92,50 @@ context "A MySQL dataset" do
84
92
  @d.filter(:name => /bc/).count.should == 2
85
93
  @d.filter(:name => /^bc/).count.should == 1
86
94
  end
87
- end
95
+ end
96
+
97
+ context "A PostgreSQL dataset in array tuples mode" do
98
+ setup do
99
+ @d = PGSQL_DB[:test]
100
+ @d.delete # remove all records
101
+ Sequel.use_array_tuples
102
+ end
103
+
104
+ teardown do
105
+ Sequel.use_hash_tuples
106
+ end
107
+
108
+ specify "should return the correct records" do
109
+ @d.to_a.should == []
110
+ @d << {:name => 'abc', :value => 123}
111
+ @d << {:name => 'abc', :value => 456}
112
+ @d << {:name => 'def', :value => 789}
113
+
114
+ @d.order(:value).select(:name, :value).to_a.should == [
115
+ ['abc', 123],
116
+ ['abc', 456],
117
+ ['def', 789]
118
+ ]
119
+ end
120
+
121
+ specify "should work correctly with transforms" do
122
+ @d.transform(:value => [proc {|v| v.to_s}, proc {|v| v.to_i}])
123
+
124
+ @d.to_a.should == []
125
+ @d << {:name => 'abc', :value => 123}
126
+ @d << {:name => 'abc', :value => 456}
127
+ @d << {:name => 'def', :value => 789}
128
+
129
+ @d.order(:value).select(:name, :value).to_a.should == [
130
+ ['abc', '123'],
131
+ ['abc', '456'],
132
+ ['def', '789']
133
+ ]
134
+
135
+ a = @d.order(:value).first
136
+ a.values.should == ['abc', '123']
137
+ a.keys.should == [:name, :value]
138
+ a[:name].should == 'abc'
139
+ a[:value].should == '123'
140
+ end
141
+ end
@@ -72,6 +72,54 @@ context "An SQLite database" do
72
72
 
73
73
  @db[:t].order(:name).map(:name).should == ['abc', 'def']
74
74
  end
75
+
76
+ specify "should be able to execute transactions" do
77
+ @db.transaction do
78
+ @db.create_table(:t) {text :name}
79
+ end
80
+
81
+ @db.tables.should == [:t]
82
+
83
+ proc {@db.transaction do
84
+ @db.create_table(:u) {text :name}
85
+ raise ArgumentError
86
+ end}.should raise_error(ArgumentError)
87
+ # no commit
88
+ @db.tables.should == [:t]
89
+
90
+ proc {@db.transaction do
91
+ @db.create_table(:v) {text :name}
92
+ rollback!
93
+ end}.should_not raise_error
94
+ # no commit
95
+ @db.tables.should == [:t]
96
+ end
97
+
98
+ specify "should support nested transactions" do
99
+ @db.transaction do
100
+ @db.transaction do
101
+ @db.create_table(:t) {text :name}
102
+ end
103
+ end
104
+
105
+ @db.tables.should == [:t]
106
+
107
+ proc {@db.transaction do
108
+ @db.create_table(:v) {text :name}
109
+ @db.transaction do
110
+ rollback! # should roll back the top-level transaction
111
+ end
112
+ end}.should_not raise_error
113
+ # no commit
114
+ @db.tables.should == [:t]
115
+ end
116
+
117
+ specify "should provide disconnect functionality" do
118
+ @db.tables
119
+ @db.pool.size.should == 1
120
+ @db.disconnect
121
+ @db.pool.size.should == 0
122
+ end
75
123
  end
76
124
 
77
125
  context "An SQLite dataset" do
@@ -80,6 +128,18 @@ context "An SQLite dataset" do
80
128
  @d.delete # remove all records
81
129
  end
82
130
 
131
+ specify "should return the correct records" do
132
+ @d.to_a.should == []
133
+ @d << {:name => 'abc', :value => 1.23}
134
+ @d << {:name => 'abc', :value => 4.56}
135
+ @d << {:name => 'def', :value => 7.89}
136
+ @d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
137
+ {:name => 'abc', :value => 1.23},
138
+ {:name => 'abc', :value => 4.56},
139
+ {:name => 'def', :value => 7.89}
140
+ ]
141
+ end
142
+
83
143
  specify "should return the correct record count" do
84
144
  @d.count.should == 0
85
145
  @d << {:name => 'abc', :value => 1.23}
@@ -87,7 +147,7 @@ context "An SQLite dataset" do
87
147
  @d << {:name => 'def', :value => 7.89}
88
148
  @d.count.should == 3
89
149
  end
90
-
150
+
91
151
  specify "should return the last inserted id when inserting records" do
92
152
  id = @d << {:name => 'abc', :value => 1.23}
93
153
  id.should == @d.first[:id]
@@ -186,3 +246,55 @@ context "SQLite::Dataset#update" do
186
246
  end
187
247
  end
188
248
 
249
+ context "An SQLite dataset in array tuples mode" do
250
+ setup do
251
+ @d = SQLITE_DB[:items]
252
+ @d.delete # remove all records
253
+
254
+ Sequel.use_array_tuples
255
+ end
256
+
257
+ teardown do
258
+ Sequel.use_hash_tuples
259
+ end
260
+
261
+ specify "should return the correct records" do
262
+ @d.to_a.should == []
263
+ @d << {:name => 'abc', :value => 1.23}
264
+ @d << {:name => 'abc', :value => 4.56}
265
+ @d << {:name => 'def', :value => 7.89}
266
+ @d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
267
+ Array.from_hash({:name => 'abc', :value => 1.23}),
268
+ Array.from_hash({:name => 'abc', :value => 4.56}),
269
+ Array.from_hash({:name => 'def', :value => 7.89})
270
+ ]
271
+ end
272
+ end
273
+
274
+ context "SQLite dataset" do
275
+ setup do
276
+ SQLITE_DB.create_table :test do
277
+ integer :id, :primary_key => true, :auto_increment => true
278
+ text :name
279
+ float :value
280
+ end
281
+
282
+ @d = SQLITE_DB[:items]
283
+ @d.delete # remove all records
284
+ @d << {:name => 'abc', :value => 1.23}
285
+ @d << {:name => 'def', :value => 4.56}
286
+ @d << {:name => 'ghi', :value => 7.89}
287
+ end
288
+
289
+ teardown do
290
+ SQLITE_DB.drop_table :test
291
+ end
292
+
293
+ specify "should be able to insert from a subquery" do
294
+ SQLITE_DB[:test] << @d
295
+ SQLITE_DB[:test].count.should == 3
296
+ SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
297
+ @d.select(:name, :value).order(:value).to_a
298
+ end
299
+ end
300
+
@@ -0,0 +1,544 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "An array with symbol keys" do
4
+ setup do
5
+ @a = [1, 2, 3]
6
+ @a.keys = [:a, :b, :c]
7
+ end
8
+
9
+ specify "should provide subscript access" do
10
+ @a[0].should == 1
11
+ @a[0..1].should == [1, 2]
12
+
13
+ @a[1] = 4
14
+ @a.should == [1, 4, 3]
15
+ end
16
+
17
+ specify "should provide key access using symbols" do
18
+ @a[:a].should == 1
19
+ @a[:b].should == 2
20
+ @a[:B].should == nil
21
+
22
+ @a[:a] = 11
23
+ @a.should == [11, 2, 3]
24
+ @a[:a].should == 11
25
+
26
+ @a[:d] = 4
27
+ @a.should == [11, 2, 3, 4]
28
+ @a.keys.should == [:a, :b, :c, :d]
29
+ end
30
+
31
+ specify "should provide key acess using strings" do
32
+ @a['a'].should == 1
33
+ @a['A'].should be_nil
34
+
35
+ @a['d'] = 4
36
+ @a.should == [1, 2, 3, 4]
37
+ @a.keys.should == [:a, :b, :c, :d]
38
+ end
39
+
40
+ specify "should provide #store functionality" do
41
+ @a.store(:a, 11)
42
+ @a.should == [11, 2, 3]
43
+
44
+ @a.store(:d, 4)
45
+ @a.should == [11, 2, 3, 4]
46
+
47
+ @a.store('d', 44)
48
+ @a.should == [11, 2, 3, 44]
49
+ end
50
+
51
+ specify "should provide #to_hash/#to_h functionality" do
52
+ @a.to_hash.should == {:a => 1, :b => 2, :c => 3}
53
+ @a.to_h.should == {:a => 1, :b => 2, :c => 3}
54
+ end
55
+
56
+ specify "should provide #fields as alias to #keys" do
57
+ @a.fields.should == [:a, :b, :c]
58
+ @a.fields = [:x, :y, :z]
59
+
60
+ @a[:x].should == 1
61
+ end
62
+
63
+ specify "should provide #slice functionality with keys" do
64
+ s = @a.slice(0, 2)
65
+ s.should == [1, 2]
66
+ s.keys.should == [:a, :b]
67
+
68
+ s = @a.slice(1..2)
69
+ s.should == [2, 3]
70
+ s.keys.should == [:b, :c]
71
+ end
72
+
73
+ specify "should provide #each_pair iterator" do
74
+ pairs = []
75
+ @a.each_pair {|k, v| pairs << [k, v]}
76
+ pairs.should == [[:a, 1], [:b, 2], [:c, 3]]
77
+ end
78
+
79
+ specify "should provide stock #delete functionality for arrays without keys" do
80
+ a = [1, 2, 3]
81
+ a.delete(2)
82
+ a.should == [1, 3]
83
+ end
84
+
85
+ specify "should provide key-based #delete functionality" do
86
+ @a.delete(:b)
87
+ @a.should == [1, 3]
88
+ @a.keys.should == [:a, :c]
89
+ @a[:a].should == 1
90
+ @a[:c].should == 3
91
+ end
92
+
93
+ specify "should separate array keys after #delete/#delete_at" do
94
+ b = @a.dup
95
+
96
+ b.delete(:b)
97
+
98
+ @a.keys.should == [:a, :b, :c]
99
+ b.keys.should == [:a, :c]
100
+ @a.should == [1, 2, 3]
101
+ b.should == [1, 3]
102
+ @a[:b].should == 2
103
+ b[:b].should == nil
104
+ end
105
+
106
+ specify "should provide #each_key functionality" do
107
+ keys = []
108
+ @a.each_key {|k| keys << k}
109
+ keys.should == [:a, :b, :c]
110
+ end
111
+
112
+ specify "should provide #each_value functionality" do
113
+ values = []
114
+ @a.each_value {|v| values << v}
115
+ values.should == [1, 2, 3]
116
+ end
117
+
118
+ specify "should provide stock #include? functionality for arrays without keys" do
119
+ [1, 2, 3].include?(2).should be_true
120
+ [1, 2, 3].include?(4).should be_false
121
+ end
122
+
123
+ specify "should provide #has_key?/#member?/#key?/#include? functionality" do
124
+ @a.has_key?(:a).should be_true
125
+ @a.has_key?(:b).should be_true
126
+ @a.has_key?(:c).should be_true
127
+ @a.has_key?(:B).should be_false
128
+ @a.has_key?(:d).should be_false
129
+
130
+ @a.has_key?('a').should be_true
131
+ @a.has_key?('b').should be_true
132
+ @a.has_key?('c').should be_true
133
+ @a.has_key?('A').should be_false
134
+ @a.has_key?('d').should be_false
135
+
136
+ @a.key?(:a).should be_true
137
+ @a.key?(:b).should be_true
138
+ @a.key?(:c).should be_true
139
+ @a.key?(:B).should be_false
140
+ @a.key?(:d).should be_false
141
+
142
+ @a.key?('a').should be_true
143
+ @a.key?('b').should be_true
144
+ @a.key?('c').should be_true
145
+ @a.key?('A').should be_false
146
+ @a.key?('d').should be_false
147
+
148
+ @a.member?(:a).should be_true
149
+ @a.member?(:b).should be_true
150
+ @a.member?(:c).should be_true
151
+ @a.member?(:B).should be_false
152
+ @a.member?(:d).should be_false
153
+
154
+ @a.member?('a').should be_true
155
+ @a.member?('b').should be_true
156
+ @a.member?('c').should be_true
157
+ @a.member?('A').should be_false
158
+ @a.member?('d').should be_false
159
+
160
+ @a.include?(:a).should be_true
161
+ @a.include?(:b).should be_true
162
+ @a.include?(:c).should be_true
163
+ @a.include?(:B).should be_false
164
+ @a.include?(:d).should be_false
165
+
166
+ @a.include?('a').should be_true
167
+ @a.include?('b').should be_true
168
+ @a.include?('c').should be_true
169
+ @a.include?('A').should be_false
170
+ @a.include?('d').should be_false
171
+ end
172
+
173
+ specify "should provide original #include? functionality for arrays without keys" do
174
+ [1, 2, 3].include?(:a).should be_false
175
+ [1, 2, 3].include?(1).should be_true
176
+ end
177
+
178
+ specify "should provide #has_value?/#value? functionality" do
179
+ @a.has_value?(1).should be_true
180
+ @a.has_value?(2).should be_true
181
+ @a.has_value?(3).should be_true
182
+ @a.has_value?(4).should be_false
183
+
184
+ @a.value?(1).should be_true
185
+ @a.value?(2).should be_true
186
+ @a.value?(3).should be_true
187
+ @a.value?(4).should be_false
188
+ end
189
+
190
+ specify "should provide #fetch functionality" do
191
+ @a.fetch(:a).should == 1
192
+ @a.fetch(:b).should == 2
193
+ @a.fetch(:c).should == 3
194
+ proc {@a.fetch(:d)}.should raise_error(IndexError)
195
+ @a.fetch(:d, 4).should == 4
196
+ @a.fetch(:d, nil).should == nil
197
+
198
+ @a.fetch(:a) {|v| v.to_s}.should == '1'
199
+ @a.fetch(:d, 4) {|v| v.to_s}.should == '4'
200
+ end
201
+
202
+ specify "should provide #values functionality" do
203
+ @a.values.should == [1, 2, 3]
204
+ end
205
+
206
+ specify "should provide #dup functionality" do
207
+ b = @a.dup
208
+ b.should == [1, 2, 3]
209
+ b.keys.should == @a.keys
210
+
211
+ b[:a].should == 1
212
+ b[:b].should == 2
213
+ b[:c].should == 3
214
+ b[:d].should be_nil
215
+
216
+ @a.keys << :e
217
+ @a.keys.should == [:a, :b, :c, :e]
218
+ b.keys.should == @a.keys
219
+ end
220
+
221
+ specify "should provide #clone functionality" do
222
+ b = @a.clone
223
+ b.should == [1, 2, 3]
224
+ b.keys.should == @a.keys
225
+
226
+ b[:a].should == 1
227
+ b[:b].should == 2
228
+ b[:c].should == 3
229
+ b[:d].should be_nil
230
+
231
+ @a.keys << :e
232
+ @a.keys.should == [:a, :b, :c, :e]
233
+ b.keys.should_not == @a.keys
234
+ end
235
+
236
+ specify "should provide #merge functionality" do
237
+ @a.merge(@a).to_hash.should == {:a => 1, :b => 2, :c => 3}
238
+
239
+ @a.merge({:b => 22, :d => 4}).to_hash.should == {:a => 1, :b => 22, :c => 3, :d => 4}
240
+
241
+ b = [1, 2, 3]
242
+ b.keys = [:b, :c, :d]
243
+ @a.merge(b).to_hash.should == {:a => 1, :b => 1, :c => 2, :d => 3}
244
+
245
+ # call with a block. The block returns the old value passed to it
246
+ @a.merge(b) {|k, o, n| o}.to_hash.should == {:a => 1, :b => 2, :c => 3, :d => 3}
247
+ end
248
+
249
+ specify "should provide #merge!/#update!/#update functionality" do
250
+ @a.merge!(@a)
251
+ @a.to_hash.should == {:a => 1, :b => 2, :c => 3}
252
+
253
+ @a.update(:b => 22)
254
+ @a.to_hash.should == {:a => 1, :b => 22, :c => 3}
255
+
256
+ b = [1, 2, 3]
257
+ b.keys = [:b, :c, :d]
258
+ @a.update!(b)
259
+ @a.to_hash.should == {:a => 1, :b => 1, :c => 2, :d => 3}
260
+ end
261
+ end
262
+
263
+ context "An array with string keys" do
264
+ setup do
265
+ @a = [1, 2, 3]
266
+ @a.keys = ['a', 'b', 'c']
267
+ end
268
+
269
+ specify "should provide key access using symbols" do
270
+ @a[:a].should == 1
271
+ @a[:b].should == 2
272
+ @a[:B].should == nil
273
+
274
+ @a[:a] = 11
275
+ @a.should == [11, 2, 3]
276
+ @a[:a].should == 11
277
+
278
+ @a[:d] = 4
279
+ @a.should == [11, 2, 3, 4]
280
+ @a.keys.should == ['a', 'b', 'c', :d]
281
+ end
282
+
283
+ specify "should provide key acess using strings" do
284
+ @a['a'].should == 1
285
+ @a['A'].should be_nil
286
+
287
+ @a['d'] = 4
288
+ @a.should == [1, 2, 3, 4]
289
+ @a.keys.should == ['a', 'b', 'c', :d]
290
+ end
291
+
292
+ specify "should provide #store functionality" do
293
+ @a.store(:a, 11)
294
+ @a.should == [11, 2, 3]
295
+
296
+ @a.store(:d, 4)
297
+ @a.should == [11, 2, 3, 4]
298
+
299
+ @a.store('d', 44)
300
+ @a.should == [11, 2, 3, 44]
301
+ end
302
+
303
+ specify "should provide #to_hash/#to_h functionality" do
304
+ @a.to_hash.should == {:a => 1, :b => 2, :c => 3}
305
+ @a.to_h.should == {:a => 1, :b => 2, :c => 3}
306
+ end
307
+
308
+ specify "should provide #fields as alias to #keys" do
309
+ @a.fields.should == ['a', 'b', 'c']
310
+ @a.fields = [:x, :y, :z]
311
+
312
+ @a[:x].should == 1
313
+ end
314
+
315
+ specify "should provide #slice functionality with keys" do
316
+ s = @a.slice(0, 2)
317
+ s.should == [1, 2]
318
+ s.keys.should == ['a', 'b']
319
+
320
+ s = @a.slice(1..2)
321
+ s.should == [2, 3]
322
+ s.keys.should == ['b', 'c']
323
+ end
324
+
325
+ specify "should provide #each_pair iterator" do
326
+ pairs = []
327
+ @a.each_pair {|k, v| pairs << [k, v]}
328
+ pairs.should == [['a', 1], ['b', 2], ['c', 3]]
329
+ end
330
+
331
+ specify "should provide key-based #delete functionality" do
332
+ @a.delete(:b)
333
+ @a.should == [1, 3]
334
+ @a.keys.should == ['a', 'c']
335
+ @a[:a].should == 1
336
+ @a[:c].should == 3
337
+ end
338
+
339
+ specify "should provide #each_key functionality" do
340
+ keys = []
341
+ @a.each_key {|k| keys << k}
342
+ keys.should == ['a', 'b', 'c']
343
+ end
344
+
345
+ specify "should provide #each_value functionality" do
346
+ values = []
347
+ @a.each_value {|v| values << v}
348
+ values.should == [1, 2, 3]
349
+ end
350
+
351
+ specify "should provide #has_key?/#member?/#key?/#include? functionality" do
352
+ @a.has_key?(:a).should be_true
353
+ @a.has_key?(:b).should be_true
354
+ @a.has_key?(:c).should be_true
355
+ @a.has_key?(:B).should be_false
356
+ @a.has_key?(:d).should be_false
357
+
358
+ @a.has_key?('a').should be_true
359
+ @a.has_key?('b').should be_true
360
+ @a.has_key?('c').should be_true
361
+ @a.has_key?('A').should be_false
362
+ @a.has_key?('d').should be_false
363
+
364
+ @a.key?(:a).should be_true
365
+ @a.key?(:b).should be_true
366
+ @a.key?(:c).should be_true
367
+ @a.key?(:B).should be_false
368
+ @a.key?(:d).should be_false
369
+
370
+ @a.key?('a').should be_true
371
+ @a.key?('b').should be_true
372
+ @a.key?('c').should be_true
373
+ @a.key?('A').should be_false
374
+ @a.key?('d').should be_false
375
+
376
+ @a.member?(:a).should be_true
377
+ @a.member?(:b).should be_true
378
+ @a.member?(:c).should be_true
379
+ @a.member?(:B).should be_false
380
+ @a.member?(:d).should be_false
381
+
382
+ @a.member?('a').should be_true
383
+ @a.member?('b').should be_true
384
+ @a.member?('c').should be_true
385
+ @a.member?('A').should be_false
386
+ @a.member?('d').should be_false
387
+
388
+ @a.include?(:a).should be_true
389
+ @a.include?(:b).should be_true
390
+ @a.include?(:c).should be_true
391
+ @a.include?(:B).should be_false
392
+ @a.include?(:d).should be_false
393
+
394
+ @a.include?('a').should be_true
395
+ @a.include?('b').should be_true
396
+ @a.include?('c').should be_true
397
+ @a.include?('A').should be_false
398
+ @a.include?('d').should be_false
399
+ end
400
+
401
+ specify "should provide original #include? functionality for arrays without keys" do
402
+ [1, 2, 3].include?(:a).should be_false
403
+ [1, 2, 3].include?(1).should be_true
404
+ end
405
+
406
+ specify "should provide #has_value?/#value? functionality" do
407
+ @a.has_value?(1).should be_true
408
+ @a.has_value?(2).should be_true
409
+ @a.has_value?(3).should be_true
410
+ @a.has_value?(4).should be_false
411
+
412
+ @a.value?(1).should be_true
413
+ @a.value?(2).should be_true
414
+ @a.value?(3).should be_true
415
+ @a.value?(4).should be_false
416
+ end
417
+
418
+ specify "should provide #fetch functionality" do
419
+ @a.fetch(:a).should == 1
420
+ @a.fetch(:b).should == 2
421
+ @a.fetch(:c).should == 3
422
+ proc {@a.fetch(:d)}.should raise_error(IndexError)
423
+ @a.fetch(:d, 4).should == 4
424
+ @a.fetch(:d, nil).should == nil
425
+
426
+ @a.fetch(:a) {|v| v.to_s}.should == '1'
427
+ @a.fetch(:d, 4) {|v| v.to_s}.should == '4'
428
+ end
429
+
430
+ specify "should provide #values functionality" do
431
+ @a.values.should == [1, 2, 3]
432
+ end
433
+
434
+ specify "should provide #dup functionality" do
435
+ b = @a.dup
436
+ b.should == [1, 2, 3]
437
+ b.keys.should == @a.keys
438
+
439
+ b[:a].should == 1
440
+ b[:b].should == 2
441
+ b[:c].should == 3
442
+ b[:d].should be_nil
443
+
444
+ @a.keys << :e
445
+ @a.keys.should == ['a', 'b', 'c', :e]
446
+ b.keys.should == @a.keys
447
+ end
448
+
449
+ specify "should provide #clone functionality" do
450
+ b = @a.clone
451
+ b.should == [1, 2, 3]
452
+ b.keys.should == @a.keys
453
+
454
+ b[:a].should == 1
455
+ b[:b].should == 2
456
+ b[:c].should == 3
457
+ b[:d].should be_nil
458
+
459
+ @a.keys << :e
460
+ @a.keys.should == ['a', 'b', 'c', :e]
461
+ b.keys.should_not == @a.keys
462
+ end
463
+
464
+ specify "should provide #merge functionality" do
465
+ @a.merge(@a).to_hash.should == {:a => 1, :b => 2, :c => 3}
466
+
467
+ @a.merge({:b => 22, :d => 4}).to_hash.should == {:a => 1, :b => 22, :c => 3, :d => 4}
468
+
469
+ b = [1, 2, 3]
470
+ b.keys = [:b, :c, :d]
471
+ @a.merge(b).to_hash.should == {:a => 1, :b => 1, :c => 2, :d => 3}
472
+
473
+ # call with a block. The block returns the old value passed to it
474
+ @a.merge(b) {|k, o, n| o}.to_hash.should == {:a => 1, :b => 2, :c => 3, :d => 3}
475
+ end
476
+
477
+ specify "should provide #merge!/#update!/#update functionality" do
478
+ @a.merge!(@a)
479
+ @a.to_hash.should == {:a => 1, :b => 2, :c => 3}
480
+
481
+ @a.update(:b => 22)
482
+ @a.to_hash.should == {:a => 1, :b => 22, :c => 3}
483
+
484
+ b = [1, 2, 3]
485
+ b.keys = [:b, :c, :d]
486
+ @a.update!(b)
487
+ @a.to_hash.should == {:a => 1, :b => 1, :c => 2, :d => 3}
488
+ end
489
+ end
490
+
491
+ context "Array.from_hash" do
492
+ specify "should construct an array with keys from a hash" do
493
+ h = {:x => 1, :y => 2, :z => 3}
494
+ a = Array.from_hash(h)
495
+ a.to_hash.should == h
496
+ end
497
+ end
498
+
499
+ context "Sequel.use_array_tuples" do
500
+ setup do
501
+ @c = Class.new(Sequel::Dataset) do
502
+ def fetch_rows(sql, &block)
503
+ block[{:a => 1, :b => 2, :c => 3}]
504
+ end
505
+ end
506
+
507
+ @ds = @c.new(nil).from(:items)
508
+ end
509
+
510
+ teardown do
511
+ Sequel.use_hash_tuples
512
+ end
513
+
514
+ specify "should cause the dataset to return array tuples instead of hashes" do
515
+ @ds.first.should == {:a => 1, :b => 2, :c => 3}
516
+ Sequel.use_array_tuples
517
+ a = @ds.first
518
+ a.class.should == Array
519
+ a.values.sort.should == [1, 2, 3]
520
+ a.keys.map {|k| k.to_s}.sort.should == ['a', 'b', 'c']
521
+ a[:a].should == 1
522
+ a[:b].should == 2
523
+ a[:c].should == 3
524
+ a[:d].should == nil
525
+
526
+ @ds.transform(:a => [proc {|v| v.to_s}, proc {|v| v.to_i}])
527
+ a = @ds.first
528
+ a[:a].should == '1'
529
+
530
+ @ds.transform({})
531
+ a = @ds.first
532
+ a[:a].should == 1
533
+
534
+ @ds.set_model(Hash)
535
+ end
536
+
537
+ specify "should be reversible using Sequel.use_hash_tuples" do
538
+ Sequel.use_array_tuples
539
+ @ds.first.class.should == Array
540
+
541
+ Sequel.use_hash_tuples
542
+ @ds.first.should == {:a => 1, :b => 2, :c => 3}
543
+ end
544
+ end