sequel 0.2.1.1 → 0.3.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/CHANGELOG +76 -0
- data/Rakefile +1 -1
- data/lib/sequel.rb +1 -1
- data/lib/sequel/ado.rb +17 -0
- data/lib/sequel/array_keys.rb +233 -0
- data/lib/sequel/connection_pool.rb +14 -0
- data/lib/sequel/core_ext.rb +3 -3
- data/lib/sequel/database.rb +25 -7
- data/lib/sequel/dataset.rb +46 -15
- data/lib/sequel/dataset/convenience.rb +27 -2
- data/lib/sequel/dataset/sequelizer.rb +2 -2
- data/lib/sequel/dataset/sql.rb +49 -18
- data/lib/sequel/dbi.rb +17 -0
- data/lib/sequel/model.rb +276 -82
- data/lib/sequel/model/base.rb +41 -30
- data/lib/sequel/model/caching.rb +42 -0
- data/lib/sequel/model/hooks.rb +113 -27
- data/lib/sequel/model/record.rb +78 -21
- data/lib/sequel/model/relations.rb +5 -0
- data/lib/sequel/model/schema.rb +11 -1
- data/lib/sequel/mysql.rb +61 -17
- data/lib/sequel/odbc.rb +42 -1
- data/lib/sequel/postgres.rb +45 -0
- data/lib/sequel/pretty_table.rb +14 -11
- data/lib/sequel/schema/schema_generator.rb +9 -3
- data/lib/sequel/sqlite.rb +33 -1
- data/spec/adapters/mysql_spec.rb +69 -15
- data/spec/adapters/postgres_spec.rb +66 -12
- data/spec/adapters/sqlite_spec.rb +113 -1
- data/spec/array_keys_spec.rb +544 -0
- data/spec/connection_pool_spec.rb +83 -0
- data/spec/database_spec.rb +81 -2
- data/spec/dataset_spec.rb +227 -9
- data/spec/model_spec.rb +392 -68
- data/spec/schema_spec.rb +7 -0
- metadata +5 -2
@@ -11,7 +11,20 @@ PGSQL_DB.create_table :test do
|
|
11
11
|
index :value
|
12
12
|
end
|
13
13
|
|
14
|
-
context "A
|
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
|
-
|
29
|
-
|
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).
|
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
|