sequel 3.3.0 → 3.4.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 +62 -0
- data/README.rdoc +4 -4
- data/doc/release_notes/3.3.0.txt +1 -1
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/sharding.rdoc +3 -3
- data/lib/sequel/adapters/amalgalite.rb +1 -1
- data/lib/sequel/adapters/firebird.rb +4 -9
- data/lib/sequel/adapters/jdbc.rb +21 -7
- data/lib/sequel/adapters/mysql.rb +2 -1
- data/lib/sequel/adapters/odbc.rb +7 -21
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +6 -1
- data/lib/sequel/adapters/shared/mssql.rb +11 -0
- data/lib/sequel/adapters/shared/mysql.rb +8 -12
- data/lib/sequel/adapters/shared/oracle.rb +13 -0
- data/lib/sequel/adapters/shared/postgres.rb +5 -10
- data/lib/sequel/adapters/shared/sqlite.rb +21 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/core.rb +147 -11
- data/lib/sequel/database.rb +21 -9
- data/lib/sequel/dataset.rb +31 -6
- data/lib/sequel/dataset/convenience.rb +1 -1
- data/lib/sequel/dataset/sql.rb +76 -18
- data/lib/sequel/extensions/inflector.rb +2 -51
- data/lib/sequel/model.rb +16 -10
- data/lib/sequel/model/associations.rb +4 -1
- data/lib/sequel/model/base.rb +13 -6
- data/lib/sequel/model/default_inflections.rb +46 -0
- data/lib/sequel/model/inflections.rb +1 -51
- data/lib/sequel/plugins/boolean_readers.rb +52 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +13 -1
- data/lib/sequel/plugins/nested_attributes.rb +171 -0
- data/lib/sequel/plugins/serialization.rb +35 -16
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/validation_helpers.rb +8 -1
- data/lib/sequel/sql.rb +33 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +11 -6
- data/spec/core/core_sql_spec.rb +29 -0
- data/spec/core/database_spec.rb +16 -7
- data/spec/core/dataset_spec.rb +264 -20
- data/spec/extensions/boolean_readers_spec.rb +86 -0
- data/spec/extensions/inflector_spec.rb +67 -4
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +45 -5
- data/spec/extensions/nested_attributes_spec.rb +272 -0
- data/spec/extensions/serialization_spec.rb +64 -1
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/validation_helpers_spec.rb +18 -0
- data/spec/integration/dataset_test.rb +79 -2
- data/spec/integration/schema_test.rb +17 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/model/associations_spec.rb +19 -7
- data/spec/model/model_spec.rb +29 -0
- data/spec/model/record_spec.rb +36 -0
- data/spec/spec_config.rb +1 -1
- metadata +14 -2
@@ -1,6 +1,7 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
2
|
|
3
3
|
require 'yaml'
|
4
|
+
require 'json'
|
4
5
|
|
5
6
|
describe "Serialization plugin" do
|
6
7
|
before do
|
@@ -10,7 +11,7 @@ describe "Serialization plugin" do
|
|
10
11
|
end
|
11
12
|
end)
|
12
13
|
no_primary_key
|
13
|
-
columns :id, :abc, :def
|
14
|
+
columns :id, :abc, :def, :ghi
|
14
15
|
end
|
15
16
|
MODEL_DB.reset
|
16
17
|
end
|
@@ -23,6 +24,10 @@ describe "Serialization plugin" do
|
|
23
24
|
@c.plugin :serialization, :marshal, :def
|
24
25
|
@c.create(:abc => 1, :def=> 1)
|
25
26
|
MODEL_DB.sqls.last.should =~ /INSERT INTO items \((abc, def|def, abc)\) VALUES \(('--- 1\n', 'BAhpBg==\n'|'BAhpBg==\n', '--- 1\n')\)/
|
27
|
+
|
28
|
+
@c.plugin :serialization, :json, :ghi
|
29
|
+
@c.create(:ghi => [123])
|
30
|
+
MODEL_DB.sqls.last.should =~ /INSERT INTO items \((ghi)\) VALUES \('\[123\]'\)/
|
26
31
|
end
|
27
32
|
|
28
33
|
it "should allow serializing attributes to yaml" do
|
@@ -57,6 +62,18 @@ describe "Serialization plugin" do
|
|
57
62
|
"INSERT INTO items (abc) VALUES ('#{x}')", \
|
58
63
|
]
|
59
64
|
end
|
65
|
+
|
66
|
+
it "should allow serializing attributes to json" do
|
67
|
+
@c.plugin :serialization, :json, :ghi
|
68
|
+
@c.create(:ghi => [1])
|
69
|
+
@c.create(:ghi => ["hello"])
|
70
|
+
|
71
|
+
x = JSON.generate ["hello"]
|
72
|
+
MODEL_DB.sqls.should == [ \
|
73
|
+
"INSERT INTO items (ghi) VALUES ('[1]')", \
|
74
|
+
"INSERT INTO items (ghi) VALUES ('#{x}')", \
|
75
|
+
]
|
76
|
+
end
|
60
77
|
|
61
78
|
it "should translate values to and from yaml serialization format using accessor methods" do
|
62
79
|
@c.set_primary_key :id
|
@@ -102,6 +119,29 @@ describe "Serialization plugin" do
|
|
102
119
|
MODEL_DB.sqls.should == ["UPDATE items SET abc = '#{[Marshal.dump(23)].pack('m')}' WHERE (id = 1)",
|
103
120
|
"INSERT INTO items (abc) VALUES ('#{[Marshal.dump([1, 2, 3])].pack('m')}')"]
|
104
121
|
end
|
122
|
+
|
123
|
+
it "should translate values to and from json serialization format using accessor methods" do
|
124
|
+
@c.set_primary_key :id
|
125
|
+
@c.plugin :serialization, :json, :abc, :def
|
126
|
+
|
127
|
+
ds = @c.dataset
|
128
|
+
def ds.fetch_rows(sql, &block)
|
129
|
+
block.call(:id => 1, :abc => JSON.generate([1]), :def => JSON.generate(["hello"]))
|
130
|
+
end
|
131
|
+
|
132
|
+
o = @c.first
|
133
|
+
o.id.should == 1
|
134
|
+
o.abc.should == [1]
|
135
|
+
o.abc.should == [1]
|
136
|
+
o.def.should == ["hello"]
|
137
|
+
o.def.should == ["hello"]
|
138
|
+
|
139
|
+
o.update(:abc => [23])
|
140
|
+
@c.create(:abc => [1,2,3])
|
141
|
+
|
142
|
+
MODEL_DB.sqls.should == ["UPDATE items SET abc = '#{JSON.generate([23])}' WHERE (id = 1)",
|
143
|
+
"INSERT INTO items (abc) VALUES ('#{JSON.generate([1,2,3])}')"]
|
144
|
+
end
|
105
145
|
|
106
146
|
it "should copy serialization formats and columns to subclasses" do
|
107
147
|
@c.set_primary_key :id
|
@@ -143,4 +183,27 @@ describe "Serialization plugin" do
|
|
143
183
|
lambda{o.send(:serialize_value, :abc, 1)}.should raise_error(Sequel::Error)
|
144
184
|
lambda{o.send(:deserialize_value, :abc, "--- hello\n")}.should raise_error(Sequel::Error)
|
145
185
|
end
|
186
|
+
|
187
|
+
it "should add the accessors to a module included in the class, so they can be easily overridden" do
|
188
|
+
@c.class_eval do
|
189
|
+
def abc
|
190
|
+
"#{super}-blah"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
@c.plugin :serialization, :yaml, :abc
|
194
|
+
o = @c.load(:abc => "--- 1\n")
|
195
|
+
o.abc.should == "1-blah"
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should call super to get the deserialized value from a previous accessor" do
|
199
|
+
m = Module.new do
|
200
|
+
def abc
|
201
|
+
"--- #{@values[:abc]*3}\n"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
@c.send(:include, m)
|
205
|
+
@c.plugin :serialization, :yaml, :abc
|
206
|
+
o = @c.load(:abc => 3)
|
207
|
+
o.abc.should == 9
|
208
|
+
end
|
146
209
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "Sequel::Plugins::Timestamps" do
|
4
|
+
before do
|
5
|
+
dc = Object.new
|
6
|
+
dc.instance_eval do
|
7
|
+
def now
|
8
|
+
'2009-08-01'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
Sequel.datetime_class = dc
|
12
|
+
@c = Class.new(Sequel::Model(:t))
|
13
|
+
@c.class_eval do
|
14
|
+
columns :id, :created_at, :updated_at
|
15
|
+
plugin :timestamps
|
16
|
+
db.reset
|
17
|
+
def _refresh(ds); self end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
after do
|
21
|
+
Sequel.datetime_class = Time
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set the create timestamp field on creation" do
|
25
|
+
o = @c.create
|
26
|
+
@c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
|
27
|
+
o.created_at.should == '2009-08-01'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set the update timestamp field on update" do
|
31
|
+
o = @c.load(:id=>1).save
|
32
|
+
@c.db.sqls.should == ["UPDATE t SET updated_at = '2009-08-01' WHERE (id = 1)"]
|
33
|
+
o.updated_at.should == '2009-08-01'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not update the update timestamp on creation" do
|
37
|
+
@c.create.updated_at.should == nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use the same value for the creation and update timestamps when creating if the :update_on_create option is given" do
|
41
|
+
@c.plugin :timestamps, :update_on_create=>true
|
42
|
+
o = @c.create
|
43
|
+
@c.db.sqls.length.should == 1
|
44
|
+
@c.db.sqls.first.should =~ /INSERT INTO t \((creat|updat)ed_at, (creat|updat)ed_at\) VALUES \('2009-08-01', '2009-08-01'\)/
|
45
|
+
o.created_at.should === o.updated_at
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should allow specifying the create timestamp field via the :create option" do
|
49
|
+
c = Class.new(Sequel::Model(:t))
|
50
|
+
c.class_eval do
|
51
|
+
columns :id, :c
|
52
|
+
plugin :timestamps, :create=>:c
|
53
|
+
db.reset
|
54
|
+
def _refresh(ds); self end
|
55
|
+
end
|
56
|
+
o = c.create
|
57
|
+
c.db.sqls.should == ["INSERT INTO t (c) VALUES ('2009-08-01')"]
|
58
|
+
o.c.should == '2009-08-01'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should allow specifying the update timestamp field via the :update option" do
|
62
|
+
c = Class.new(Sequel::Model(:t))
|
63
|
+
c.class_eval do
|
64
|
+
columns :id, :u
|
65
|
+
plugin :timestamps, :update=>:u
|
66
|
+
db.reset
|
67
|
+
def _refresh(ds); self end
|
68
|
+
end
|
69
|
+
o = c.load(:id=>1).save
|
70
|
+
c.db.sqls.should == ["UPDATE t SET u = '2009-08-01' WHERE (id = 1)"]
|
71
|
+
o.u.should == '2009-08-01'
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should not raise an error if the model doesn't have the timestamp columns" do
|
75
|
+
c = Class.new(Sequel::Model(:t))
|
76
|
+
c.class_eval do
|
77
|
+
columns :id, :x
|
78
|
+
plugin :timestamps
|
79
|
+
db.reset
|
80
|
+
def _refresh(ds); self end
|
81
|
+
end
|
82
|
+
c.create(:x=>2)
|
83
|
+
c.load(:id=>1, :x=>2).save
|
84
|
+
c.db.sqls.should == ["INSERT INTO t (x) VALUES (2)", "UPDATE t SET x = 2 WHERE (id = 1)"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should not overwrite an existing create timestamp" do
|
88
|
+
o = @c.create(:created_at=>'2009-08-03')
|
89
|
+
@c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-03')"]
|
90
|
+
o.created_at.should == '2009-08-03'
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should overwrite an existing create timestamp if the :force option is used" do
|
94
|
+
@c.plugin :timestamps, :force=>true
|
95
|
+
o = @c.create(:created_at=>'2009-08-03')
|
96
|
+
@c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
|
97
|
+
o.created_at.should == '2009-08-01'
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should have create_timestamp_field give the create timestamp field" do
|
101
|
+
@c.create_timestamp_field.should == :created_at
|
102
|
+
@c.plugin :timestamps, :create=>:c
|
103
|
+
@c.create_timestamp_field.should == :c
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should have update_timestamp_field give the update timestamp field" do
|
107
|
+
@c.update_timestamp_field.should == :updated_at
|
108
|
+
@c.plugin :timestamps, :update=>:u
|
109
|
+
@c.update_timestamp_field.should == :u
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should have create_timestamp_overwrite? give the whether to overwrite an existing create timestamp" do
|
113
|
+
@c.create_timestamp_overwrite?.should == false
|
114
|
+
@c.plugin :timestamps, :force=>true
|
115
|
+
@c.create_timestamp_overwrite?.should == true
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should have set_update_timestamp_on_create? give whether to set the update timestamp on create" do
|
119
|
+
@c.set_update_timestamp_on_create?.should == false
|
120
|
+
@c.plugin :timestamps, :update_on_create=>true
|
121
|
+
@c.set_update_timestamp_on_create?.should == true
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should work with subclasses" do
|
125
|
+
c = Class.new(@c)
|
126
|
+
o = c.create
|
127
|
+
o.created_at.should == '2009-08-01'
|
128
|
+
o.updated_at.should == nil
|
129
|
+
o = c.load(:id=>1).save
|
130
|
+
o.updated_at.should == '2009-08-01'
|
131
|
+
c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')", "UPDATE t SET updated_at = '2009-08-01' WHERE (id = 1)"]
|
132
|
+
c.create(:created_at=>'2009-08-03').created_at.should == '2009-08-03'
|
133
|
+
|
134
|
+
c.class_eval do
|
135
|
+
columns :id, :c, :u
|
136
|
+
plugin :timestamps, :create=>:c, :update=>:u, :force=>true, :update_on_create=>true
|
137
|
+
end
|
138
|
+
c2 = Class.new(c)
|
139
|
+
c2.db.reset
|
140
|
+
o = c2.create
|
141
|
+
o.c.should == '2009-08-01'
|
142
|
+
o.u.should === o.c
|
143
|
+
c2.db.sqls.first.should =~ /INSERT INTO t \([cu], [cu]\) VALUES \('2009-08-01', '2009-08-01'\)/
|
144
|
+
c2.db.reset
|
145
|
+
o = c2.load(:id=>1).save
|
146
|
+
o.u.should == '2009-08-01'
|
147
|
+
c2.db.sqls.should == ["UPDATE t SET u = '2009-08-01' WHERE (id = 1)"]
|
148
|
+
c2.create(:c=>'2009-08-03').c.should == '2009-08-01'
|
149
|
+
end
|
150
|
+
end
|
@@ -288,4 +288,22 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
288
288
|
@user.should be_valid
|
289
289
|
MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"
|
290
290
|
end
|
291
|
+
|
292
|
+
it "should support validates_unique with a block" do
|
293
|
+
@c.columns(:id, :username, :password)
|
294
|
+
@c.set_dataset MODEL_DB[:items]
|
295
|
+
@c.set_validations{validates_unique(:username){|ds| ds.filter(:active)}}
|
296
|
+
@c.dataset.extend(Module.new {
|
297
|
+
def fetch_rows (sql)
|
298
|
+
@db << sql
|
299
|
+
yield({:v => 0})
|
300
|
+
end
|
301
|
+
})
|
302
|
+
|
303
|
+
MODEL_DB.reset
|
304
|
+
@c.new(:username => "0records", :password => "anothertest").should be_valid
|
305
|
+
@c.load(:id=>3, :username => "0records", :password => "anothertest").should be_valid
|
306
|
+
MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND active) LIMIT 1",
|
307
|
+
"SELECT COUNT(*) AS count FROM items WHERE (((username = '0records') AND active) AND (id != 3)) LIMIT 1"]
|
308
|
+
end
|
291
309
|
end
|
@@ -135,6 +135,15 @@ describe Sequel::Dataset do
|
|
135
135
|
@d.count.should == 1
|
136
136
|
@d.first[:name].should == 'def'
|
137
137
|
end
|
138
|
+
|
139
|
+
specify "should be able to truncate the table" do
|
140
|
+
@d << {:name => 'abc', :value => 123}
|
141
|
+
@d << {:name => 'abc', :value => 456}
|
142
|
+
@d << {:name => 'def', :value => 789}
|
143
|
+
@d.count.should == 3
|
144
|
+
@d.truncate.should == nil
|
145
|
+
@d.count.should == 0
|
146
|
+
end
|
138
147
|
|
139
148
|
specify "should be able to literalize booleans" do
|
140
149
|
proc {@d.literal(true)}.should_not raise_error
|
@@ -164,7 +173,7 @@ describe Sequel::Database do
|
|
164
173
|
end
|
165
174
|
end
|
166
175
|
|
167
|
-
context
|
176
|
+
context Sequel::Dataset do
|
168
177
|
before do
|
169
178
|
INTEGRATION_DB.create_table! :items do
|
170
179
|
primary_key :id
|
@@ -418,4 +427,72 @@ if INTEGRATION_DB.dataset.supports_window_functions?
|
|
418
427
|
[{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
|
419
428
|
end
|
420
429
|
end
|
421
|
-
end
|
430
|
+
end
|
431
|
+
|
432
|
+
describe Sequel::SQL::Constants do
|
433
|
+
before do
|
434
|
+
@db = INTEGRATION_DB
|
435
|
+
@ds = @db[:constants]
|
436
|
+
@c = proc do |v|
|
437
|
+
case v
|
438
|
+
when Time
|
439
|
+
v
|
440
|
+
when DateTime, String
|
441
|
+
Time.parse(v.to_s)
|
442
|
+
else
|
443
|
+
v
|
444
|
+
end
|
445
|
+
end
|
446
|
+
@c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
|
447
|
+
end
|
448
|
+
after do
|
449
|
+
@db.drop_table(:constants)
|
450
|
+
end
|
451
|
+
|
452
|
+
it "should have working CURRENT_DATE" do
|
453
|
+
@db.create_table!(:constants){Date :d}
|
454
|
+
@ds.insert(:d=>Sequel::CURRENT_DATE)
|
455
|
+
Date.today.should == @c2[@ds.get(:d)]
|
456
|
+
end
|
457
|
+
|
458
|
+
it "should have working CURRENT_TIME" do
|
459
|
+
@db.create_table!(:constants){Time :t, :only_time=>true}
|
460
|
+
@ds.insert(:t=>Sequel::CURRENT_TIME)
|
461
|
+
(Time.now - @c[@ds.get(:t)]).should be_close(0, 1)
|
462
|
+
end
|
463
|
+
|
464
|
+
it "should have working CURRENT_TIMESTAMP" do
|
465
|
+
@db.create_table!(:constants){DateTime :ts}
|
466
|
+
@ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
|
467
|
+
(Time.now - @c[@ds.get(:ts)]).should be_close(0, 1)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
describe "Sequel::Dataset#import and #multi_insert" do
|
472
|
+
before do
|
473
|
+
@db = INTEGRATION_DB
|
474
|
+
@db.create_table!(:imp){Integer :i}
|
475
|
+
@db.create_table!(:exp2){Integer :i}
|
476
|
+
@ids = @db[:imp].order(:i)
|
477
|
+
@eds = @db[:exp2]
|
478
|
+
end
|
479
|
+
after do
|
480
|
+
@db.drop_table(:imp, :exp2)
|
481
|
+
end
|
482
|
+
|
483
|
+
it "should import with multi_insert and an array of hashes" do
|
484
|
+
@ids.multi_insert([{:i=>10}, {:i=>20}])
|
485
|
+
@ids.all.should == [{:i=>10}, {:i=>20}]
|
486
|
+
end
|
487
|
+
|
488
|
+
it "should import with an array of arrays of values" do
|
489
|
+
@ids.import([:i], [[10], [20]])
|
490
|
+
@ids.all.should == [{:i=>10}, {:i=>20}]
|
491
|
+
end
|
492
|
+
|
493
|
+
it "should import with a dataset" do
|
494
|
+
@eds.import([:i], [[10], [20]])
|
495
|
+
@ids.import([:i], @eds)
|
496
|
+
@ids.all.should == [{:i=>10}, {:i=>20}]
|
497
|
+
end
|
498
|
+
end
|
@@ -293,6 +293,23 @@ describe "Database schema modifiers" do
|
|
293
293
|
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
|
294
294
|
@ds.columns!.should == [:id]
|
295
295
|
end
|
296
|
+
|
297
|
+
specify "should remove multiple columns in a single alter_table block" do
|
298
|
+
@db.create_table!(:items) do
|
299
|
+
primary_key :id
|
300
|
+
String :name
|
301
|
+
Integer :number
|
302
|
+
end
|
303
|
+
@ds.insert(:number=>10)
|
304
|
+
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :name, :number]
|
305
|
+
@ds.columns!.should == [:id, :name, :number]
|
306
|
+
@db.alter_table(:items) do
|
307
|
+
drop_column :name
|
308
|
+
drop_column :number
|
309
|
+
end
|
310
|
+
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
|
311
|
+
@ds.columns!.should == [:id]
|
312
|
+
end
|
296
313
|
end
|
297
314
|
|
298
315
|
if INTEGRATION_DB.respond_to?(:tables)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe "Sequel timezone support" do
|
4
|
+
def test_timezone
|
5
|
+
t = Time.now
|
6
|
+
@db[:t].insert(t)
|
7
|
+
t2 = @db[:t].single_value
|
8
|
+
t2 = Sequel.database_to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
|
9
|
+
(t2 - t).should be_close(0, 2)
|
10
|
+
t2.utc_offset.should == 0 if Sequel.application_timezone == :utc
|
11
|
+
t2.utc_offset.should == t.getlocal.utc_offset if Sequel.application_timezone == :local
|
12
|
+
@db[:t].delete
|
13
|
+
|
14
|
+
dt = DateTime.now
|
15
|
+
Sequel.datetime_class = DateTime
|
16
|
+
@db[:t].insert(dt)
|
17
|
+
dt2 = @db[:t].single_value
|
18
|
+
dt2 = Sequel.database_to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
|
19
|
+
(dt2 - dt).should be_close(0, 0.00002)
|
20
|
+
dt2.offset.should == 0 if Sequel.application_timezone == :utc
|
21
|
+
dt2.offset.should == dt.offset if Sequel.application_timezone == :local
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
@db = INTEGRATION_DB
|
26
|
+
@db.create_table!(:t){DateTime :t}
|
27
|
+
end
|
28
|
+
after do
|
29
|
+
@db.drop_table(:t)
|
30
|
+
Sequel.default_timezone = nil
|
31
|
+
Sequel.datetime_class = Time
|
32
|
+
end
|
33
|
+
|
34
|
+
specify "should support using UTC for database storage and local time for the application" do
|
35
|
+
Sequel.database_timezone = :utc
|
36
|
+
Sequel.application_timezone = :local
|
37
|
+
test_timezone
|
38
|
+
end
|
39
|
+
|
40
|
+
specify "should support using local time for database storage and UTC for the application" do
|
41
|
+
Sequel.database_timezone = :local
|
42
|
+
Sequel.application_timezone = :utc
|
43
|
+
test_timezone
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "should support using UTC for both database storage and for application" do
|
47
|
+
Sequel.default_timezone = :utc
|
48
|
+
test_timezone
|
49
|
+
end
|
50
|
+
|
51
|
+
specify "should support using local time for both database storage and for application" do
|
52
|
+
Sequel.default_timezone = :local
|
53
|
+
test_timezone
|
54
|
+
end
|
55
|
+
end
|