sequel 3.28.0 → 3.29.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 +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
data/spec/model/hooks_spec.rb
CHANGED
|
@@ -1,55 +1,47 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
describe "Model#after_initialize" do
|
|
4
|
-
specify "should be called after initialization" do
|
|
5
|
-
$values1 = nil
|
|
6
|
-
$reached_after_initialized = false
|
|
4
|
+
specify "should be called after initialization for both new object and objects retrieved from the database" do
|
|
7
5
|
|
|
8
|
-
a = Class.new(Sequel::Model)
|
|
9
|
-
|
|
6
|
+
a = Class.new(Sequel::Model) do
|
|
7
|
+
self::Foo = []
|
|
10
8
|
columns :x, :y
|
|
11
9
|
def after_initialize
|
|
12
|
-
|
|
13
|
-
$reached_after_initialized = true
|
|
10
|
+
model::Foo << @values.clone
|
|
14
11
|
end
|
|
15
12
|
end
|
|
16
13
|
|
|
17
14
|
a.new(:x => 1, :y => 2)
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
a.call(:x => 1, :y => 3)
|
|
16
|
+
a::Foo.should == [{:x => 1, :y => 2}, {:x => 1, :y => 3}]
|
|
20
17
|
end
|
|
21
18
|
end
|
|
22
19
|
|
|
23
20
|
describe "Model#before_create && Model#after_create" do
|
|
24
21
|
before do
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@c = Class.new(Sequel::Model(:items))
|
|
28
|
-
@c.class_eval do
|
|
22
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
29
23
|
columns :x
|
|
30
|
-
|
|
24
|
+
set_primary_key :x
|
|
25
|
+
unrestrict_primary_key
|
|
31
26
|
|
|
32
27
|
def after_create
|
|
33
28
|
MODEL_DB << "BLAH after"
|
|
34
29
|
end
|
|
35
30
|
end
|
|
31
|
+
MODEL_DB.reset
|
|
36
32
|
end
|
|
37
33
|
|
|
38
34
|
specify "should be called around new record creation" do
|
|
39
35
|
@c.send(:define_method, :before_create){MODEL_DB << "BLAH before"}
|
|
40
36
|
@c.create(:x => 2)
|
|
41
|
-
MODEL_DB.sqls.should == [
|
|
42
|
-
'BLAH before',
|
|
43
|
-
'INSERT INTO items (x) VALUES (2)',
|
|
44
|
-
'BLAH after'
|
|
45
|
-
]
|
|
37
|
+
MODEL_DB.sqls.should == ['BLAH before', 'INSERT INTO items (x) VALUES (2)', 'BLAH after', 'SELECT * FROM items WHERE (x = 2) LIMIT 1']
|
|
46
38
|
end
|
|
47
39
|
|
|
48
40
|
specify ".create should cancel the save and raise an error if before_create returns false and raise_on_save_failure is true" do
|
|
49
41
|
@c.send(:define_method, :before_create){false}
|
|
50
|
-
proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
|
|
51
42
|
proc{@c.create(:x => 2)}.should raise_error(Sequel::BeforeHookFailed)
|
|
52
43
|
MODEL_DB.sqls.should == []
|
|
44
|
+
proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
|
|
53
45
|
end
|
|
54
46
|
|
|
55
47
|
specify ".create should cancel the save and return nil if before_create returns false and raise_on_save_failure is false" do
|
|
@@ -62,24 +54,20 @@ end
|
|
|
62
54
|
|
|
63
55
|
describe "Model#before_update && Model#after_update" do
|
|
64
56
|
before do
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@c = Class.new(Sequel::Model(:items))
|
|
68
|
-
@c.class_eval do
|
|
57
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
69
58
|
columns :id, :x
|
|
70
|
-
def after_update
|
|
59
|
+
def after_update
|
|
60
|
+
MODEL_DB << "BLAH after"
|
|
61
|
+
end
|
|
71
62
|
end
|
|
63
|
+
MODEL_DB.reset
|
|
72
64
|
end
|
|
73
65
|
|
|
74
66
|
specify "should be called around record update" do
|
|
75
67
|
@c.send(:define_method, :before_update){MODEL_DB << "BLAH before"}
|
|
76
68
|
m = @c.load(:id => 2233, :x=>123)
|
|
77
69
|
m.save
|
|
78
|
-
MODEL_DB.sqls.should == [
|
|
79
|
-
'BLAH before',
|
|
80
|
-
'UPDATE items SET x = 123 WHERE (id = 2233)',
|
|
81
|
-
'BLAH after'
|
|
82
|
-
]
|
|
70
|
+
MODEL_DB.sqls.should == ['BLAH before', 'UPDATE items SET x = 123 WHERE (id = 2233)', 'BLAH after']
|
|
83
71
|
end
|
|
84
72
|
|
|
85
73
|
specify "#save should cancel the save and raise an error if before_update returns false and raise_on_save_failure is true" do
|
|
@@ -107,35 +95,28 @@ end
|
|
|
107
95
|
|
|
108
96
|
describe "Model#before_save && Model#after_save" do
|
|
109
97
|
before do
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@c = Class.new(Sequel::Model(:items))
|
|
113
|
-
@c.class_eval do
|
|
98
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
114
99
|
columns :x
|
|
115
|
-
def after_save
|
|
100
|
+
def after_save
|
|
101
|
+
MODEL_DB << "BLAH after"
|
|
102
|
+
end
|
|
116
103
|
end
|
|
104
|
+
MODEL_DB.reset
|
|
117
105
|
end
|
|
118
106
|
|
|
119
107
|
specify "should be called around record update" do
|
|
120
108
|
@c.send(:define_method, :before_save){MODEL_DB << "BLAH before"}
|
|
121
109
|
m = @c.load(:id => 2233, :x=>123)
|
|
122
110
|
m.save
|
|
123
|
-
MODEL_DB.sqls.should == [
|
|
124
|
-
'BLAH before',
|
|
125
|
-
'UPDATE items SET x = 123 WHERE (id = 2233)',
|
|
126
|
-
'BLAH after'
|
|
127
|
-
]
|
|
111
|
+
MODEL_DB.sqls.should == ['BLAH before', 'UPDATE items SET x = 123 WHERE (id = 2233)', 'BLAH after']
|
|
128
112
|
end
|
|
129
113
|
|
|
130
114
|
specify "should be called around record creation" do
|
|
131
115
|
@c.send(:define_method, :before_save){MODEL_DB << "BLAH before"}
|
|
132
|
-
@c.
|
|
116
|
+
@c.set_primary_key :x
|
|
117
|
+
@c.unrestrict_primary_key
|
|
133
118
|
@c.create(:x => 2)
|
|
134
|
-
MODEL_DB.sqls.should == [
|
|
135
|
-
'BLAH before',
|
|
136
|
-
'INSERT INTO items (x) VALUES (2)',
|
|
137
|
-
'BLAH after'
|
|
138
|
-
]
|
|
119
|
+
MODEL_DB.sqls.should == ['BLAH before', 'INSERT INTO items (x) VALUES (2)', 'BLAH after', 'SELECT * FROM items WHERE (x = 2) LIMIT 1']
|
|
139
120
|
end
|
|
140
121
|
|
|
141
122
|
specify "#save should cancel the save and raise an error if before_save returns false and raise_on_save_failure is true" do
|
|
@@ -163,27 +144,19 @@ end
|
|
|
163
144
|
|
|
164
145
|
describe "Model#before_destroy && Model#after_destroy" do
|
|
165
146
|
before do
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
@c.class_eval do
|
|
170
|
-
def after_destroy; MODEL_DB << "BLAH after"; end
|
|
171
|
-
|
|
172
|
-
def delete
|
|
173
|
-
MODEL_DB << "DELETE BLAH"
|
|
147
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
148
|
+
def after_destroy
|
|
149
|
+
MODEL_DB << "BLAH after"
|
|
174
150
|
end
|
|
175
151
|
end
|
|
152
|
+
MODEL_DB.reset
|
|
176
153
|
end
|
|
177
154
|
|
|
178
155
|
specify "should be called around record destruction" do
|
|
179
156
|
@c.send(:define_method, :before_destroy){MODEL_DB << "BLAH before"}
|
|
180
157
|
m = @c.load(:id => 2233)
|
|
181
158
|
m.destroy
|
|
182
|
-
MODEL_DB.sqls.should == [
|
|
183
|
-
'BLAH before',
|
|
184
|
-
'DELETE BLAH',
|
|
185
|
-
'BLAH after'
|
|
186
|
-
]
|
|
159
|
+
MODEL_DB.sqls.should == ['BLAH before', 'DELETE FROM items WHERE (id = 2233)', 'BLAH after']
|
|
187
160
|
end
|
|
188
161
|
|
|
189
162
|
specify "#destroy should cancel the destroy and raise an error if before_destroy returns false and raise_on_save_failure is true" do
|
|
@@ -209,16 +182,15 @@ end
|
|
|
209
182
|
|
|
210
183
|
describe "Model#before_validation && Model#after_validation" do
|
|
211
184
|
before do
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
185
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
186
|
+
columns :id
|
|
187
|
+
def after_validation
|
|
188
|
+
MODEL_DB << "BLAH after"
|
|
189
|
+
end
|
|
217
190
|
|
|
218
191
|
def validate
|
|
219
192
|
errors.add(:id, 'not valid') unless id == 2233
|
|
220
193
|
end
|
|
221
|
-
columns :id
|
|
222
194
|
end
|
|
223
195
|
end
|
|
224
196
|
|
|
@@ -228,7 +200,6 @@ describe "Model#before_validation && Model#after_validation" do
|
|
|
228
200
|
m.should be_valid
|
|
229
201
|
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
|
|
230
202
|
|
|
231
|
-
MODEL_DB.sqls.clear
|
|
232
203
|
m = @c.load(:id => 22)
|
|
233
204
|
m.should_not be_valid
|
|
234
205
|
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
|
|
@@ -240,7 +211,6 @@ describe "Model#before_validation && Model#after_validation" do
|
|
|
240
211
|
m.save.should == m
|
|
241
212
|
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after', 'UPDATE items SET x = 123 WHERE (id = 2233)']
|
|
242
213
|
|
|
243
|
-
MODEL_DB.sqls.clear
|
|
244
214
|
m = @c.load(:id => 22)
|
|
245
215
|
m.raise_on_save_failure = false
|
|
246
216
|
m.save.should == nil
|
|
@@ -277,13 +247,10 @@ end
|
|
|
277
247
|
|
|
278
248
|
describe "Model around filters" do
|
|
279
249
|
before do
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
@c = Class.new(Sequel::Model(:items))
|
|
283
|
-
@c.class_eval do
|
|
250
|
+
@c = Class.new(Sequel::Model(:items)) do
|
|
284
251
|
columns :id, :x
|
|
285
|
-
def _save_refresh(*a) end
|
|
286
252
|
end
|
|
253
|
+
MODEL_DB.reset
|
|
287
254
|
end
|
|
288
255
|
|
|
289
256
|
specify "around_create should be called around new record creation" do
|
|
@@ -295,7 +262,7 @@ describe "Model around filters" do
|
|
|
295
262
|
end
|
|
296
263
|
end
|
|
297
264
|
@c.create(:x => 2)
|
|
298
|
-
MODEL_DB.sqls.should == [
|
|
265
|
+
MODEL_DB.sqls.should == ['ac_before', 'INSERT INTO items (x) VALUES (2)', 'ac_after', "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
299
266
|
end
|
|
300
267
|
|
|
301
268
|
specify "around_delete should be called around record destruction" do
|
|
@@ -307,7 +274,7 @@ describe "Model around filters" do
|
|
|
307
274
|
end
|
|
308
275
|
end
|
|
309
276
|
@c.load(:id=>1, :x => 2).destroy
|
|
310
|
-
MODEL_DB.sqls.should == [
|
|
277
|
+
MODEL_DB.sqls.should == ['ad_before', 'DELETE FROM items WHERE (id = 1)', 'ad_after']
|
|
311
278
|
end
|
|
312
279
|
|
|
313
280
|
specify "around_update should be called around updating existing records" do
|
|
@@ -319,10 +286,10 @@ describe "Model around filters" do
|
|
|
319
286
|
end
|
|
320
287
|
end
|
|
321
288
|
@c.load(:id=>1, :x => 2).save
|
|
322
|
-
MODEL_DB.sqls.should == [
|
|
289
|
+
MODEL_DB.sqls.should == ['au_before', 'UPDATE items SET x = 2 WHERE (id = 1)', 'au_after']
|
|
323
290
|
end
|
|
324
291
|
|
|
325
|
-
specify "
|
|
292
|
+
specify "around_save should be called around saving both new and existing records, around either after_create and after_update" do
|
|
326
293
|
@c.class_eval do
|
|
327
294
|
def around_update
|
|
328
295
|
MODEL_DB << 'au_before'
|
|
@@ -341,10 +308,9 @@ describe "Model around filters" do
|
|
|
341
308
|
end
|
|
342
309
|
end
|
|
343
310
|
@c.create(:x => 2)
|
|
344
|
-
MODEL_DB.sqls.should == [
|
|
345
|
-
MODEL_DB.sqls.clear
|
|
311
|
+
MODEL_DB.sqls.should == ['as_before', 'ac_before', 'INSERT INTO items (x) VALUES (2)', 'ac_after', 'as_after', "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
346
312
|
@c.load(:id=>1, :x => 2).save
|
|
347
|
-
MODEL_DB.sqls.should == [
|
|
313
|
+
MODEL_DB.sqls.should == ['as_before', 'au_before', 'UPDATE items SET x = 2 WHERE (id = 1)', 'au_after', 'as_after']
|
|
348
314
|
end
|
|
349
315
|
|
|
350
316
|
specify "around_validation should be called around validating records" do
|
|
@@ -428,5 +394,120 @@ describe "Model around filters" do
|
|
|
428
394
|
o.meta_def(:around_validation){}
|
|
429
395
|
o.save.should == nil
|
|
430
396
|
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
describe "Model#after_commit and #after_rollback" do
|
|
400
|
+
before do
|
|
401
|
+
@db = Sequel.mock(:servers=>{:test=>{}})
|
|
402
|
+
@m = Class.new(Sequel::Model(@db[:items])) do
|
|
403
|
+
attr_accessor :rb
|
|
404
|
+
def _delete
|
|
405
|
+
end
|
|
406
|
+
def after_save
|
|
407
|
+
db.execute('as')
|
|
408
|
+
raise Sequel::Rollback if rb
|
|
409
|
+
end
|
|
410
|
+
def after_commit
|
|
411
|
+
db.execute('ac')
|
|
412
|
+
end
|
|
413
|
+
def after_rollback
|
|
414
|
+
db.execute('ar')
|
|
415
|
+
end
|
|
416
|
+
def after_destroy
|
|
417
|
+
db.execute('ad')
|
|
418
|
+
raise Sequel::Rollback if rb
|
|
419
|
+
end
|
|
420
|
+
def after_destroy_commit
|
|
421
|
+
db.execute('adc')
|
|
422
|
+
end
|
|
423
|
+
def after_destroy_rollback
|
|
424
|
+
db.execute('adr')
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
@m.use_transactions = true
|
|
428
|
+
@o = @m.load({})
|
|
429
|
+
@db.sqls
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
specify "should call after_commit for save after the transaction commits if it commits" do
|
|
433
|
+
@o.save
|
|
434
|
+
@db.sqls.should == ['BEGIN', 'as', 'COMMIT', 'ac']
|
|
435
|
+
end
|
|
431
436
|
|
|
437
|
+
specify "should call after_rollback for save after the transaction rolls back if it rolls back" do
|
|
438
|
+
@o.rb = true
|
|
439
|
+
@o.save
|
|
440
|
+
@db.sqls.should == ['BEGIN', 'as', 'ROLLBACK', 'ar']
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
specify "should have after_commit respect any surrounding transactions" do
|
|
444
|
+
@db.transaction do
|
|
445
|
+
@o.save
|
|
446
|
+
end
|
|
447
|
+
@db.sqls.should == ['BEGIN', 'as', 'COMMIT', 'ac']
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
specify "should have after_rollback respect any surrounding transactions" do
|
|
451
|
+
@db.transaction do
|
|
452
|
+
@o.rb = true
|
|
453
|
+
@o.save
|
|
454
|
+
end
|
|
455
|
+
@db.sqls.should == ['BEGIN', 'as', 'ROLLBACK', 'ar']
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
specify "should have after_commit work with surrounding transactions and sharding" do
|
|
459
|
+
@db.transaction(:server=>:test) do
|
|
460
|
+
@o.save
|
|
461
|
+
end
|
|
462
|
+
@db.sqls.should == ['BEGIN -- test', 'BEGIN', 'as', 'COMMIT', 'ac', 'COMMIT -- test']
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
specify "should have after_rollback work with surrounding transactions and sharding" do
|
|
466
|
+
@db.transaction(:server=>:test) do
|
|
467
|
+
@o.rb = true
|
|
468
|
+
@o.save
|
|
469
|
+
end
|
|
470
|
+
@db.sqls.should == ['BEGIN -- test', 'BEGIN', 'as', 'ROLLBACK', 'ar', 'COMMIT -- test']
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
specify "should call after_destroy_commit for destroy after the transaction commits if it commits" do
|
|
474
|
+
@o.destroy
|
|
475
|
+
@db.sqls.should == ['BEGIN', 'ad', 'COMMIT', 'adc']
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
specify "should call after_destroy_rollback for destroy after the transaction rolls back if it rolls back" do
|
|
479
|
+
@o.rb = true
|
|
480
|
+
@o.destroy
|
|
481
|
+
@db.sqls.should == ['BEGIN', 'ad', 'ROLLBACK', 'adr']
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
specify "should have after_destroy_commit respect any surrounding transactions" do
|
|
485
|
+
@db.transaction do
|
|
486
|
+
@o.destroy
|
|
487
|
+
end
|
|
488
|
+
@db.sqls.should == ['BEGIN', 'ad', 'COMMIT', 'adc']
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
specify "should have after_destroy_rollback respect any surrounding transactions" do
|
|
492
|
+
@db.transaction do
|
|
493
|
+
@o.rb = true
|
|
494
|
+
@o.destroy
|
|
495
|
+
end
|
|
496
|
+
@db.sqls.should == ['BEGIN', 'ad', 'ROLLBACK', 'adr']
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
specify "should have after_destroy commit work with surrounding transactions and sharding" do
|
|
500
|
+
@db.transaction(:server=>:test) do
|
|
501
|
+
@o.destroy
|
|
502
|
+
end
|
|
503
|
+
@db.sqls.should == ['BEGIN -- test', 'BEGIN', 'ad', 'COMMIT', 'adc', 'COMMIT -- test']
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
specify "should have after_destroy_rollback work with surrounding transactions and sharding" do
|
|
507
|
+
@db.transaction(:server=>:test) do
|
|
508
|
+
@o.rb = true
|
|
509
|
+
@o.destroy
|
|
510
|
+
end
|
|
511
|
+
@db.sqls.should == ['BEGIN -- test', 'BEGIN', 'ad', 'ROLLBACK', 'adr', 'COMMIT -- test']
|
|
512
|
+
end
|
|
432
513
|
end
|
data/spec/model/model_spec.rb
CHANGED
|
@@ -99,6 +99,13 @@ describe "Sequel::Model()" do
|
|
|
99
99
|
end.should_not raise_error
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
+
it "should work without raising an exception with an LiteralString" do
|
|
103
|
+
proc do
|
|
104
|
+
class ::Album < Sequel::Model('table'.lit); end
|
|
105
|
+
class ::Album < Sequel::Model('table'.lit); end
|
|
106
|
+
end.should_not raise_error
|
|
107
|
+
end
|
|
108
|
+
|
|
102
109
|
it "should work without raising an exception with a database" do
|
|
103
110
|
proc do
|
|
104
111
|
class ::Album < Sequel::Model(@db); end
|
|
@@ -133,17 +140,16 @@ describe Sequel::Model do
|
|
|
133
140
|
it "should be associated with a dataset" do
|
|
134
141
|
model_a = Class.new(Sequel::Model) { set_dataset MODEL_DB[:as] }
|
|
135
142
|
|
|
136
|
-
model_a.dataset.should be_a_kind_of(
|
|
143
|
+
model_a.dataset.should be_a_kind_of(Sequel::Mock::Dataset)
|
|
137
144
|
model_a.dataset.opts[:from].should == [:as]
|
|
138
145
|
|
|
139
146
|
model_b = Class.new(Sequel::Model) { set_dataset MODEL_DB[:bs] }
|
|
140
147
|
|
|
141
|
-
model_b.dataset.should be_a_kind_of(
|
|
148
|
+
model_b.dataset.should be_a_kind_of(Sequel::Mock::Dataset)
|
|
142
149
|
model_b.dataset.opts[:from].should == [:bs]
|
|
143
150
|
|
|
144
151
|
model_a.dataset.opts[:from].should == [:as]
|
|
145
152
|
end
|
|
146
|
-
|
|
147
153
|
end
|
|
148
154
|
|
|
149
155
|
describe Sequel::Model, "dataset & schema" do
|
|
@@ -217,7 +223,7 @@ describe Sequel::Model, "dataset & schema" do
|
|
|
217
223
|
|
|
218
224
|
it "should raise an error on set_dataset if there is an error connecting to the database" do
|
|
219
225
|
@model.meta_def(:columns){raise Sequel::DatabaseConnectionError}
|
|
220
|
-
proc{@model.set_dataset(
|
|
226
|
+
proc{@model.set_dataset(Sequel::Database.new[:foo].join(:blah))}.should raise_error
|
|
221
227
|
end
|
|
222
228
|
|
|
223
229
|
it "should not raise an error if there is a problem getting the columns for a dataset" do
|
|
@@ -236,9 +242,8 @@ describe Sequel::Model, "dataset & schema" do
|
|
|
236
242
|
end
|
|
237
243
|
end
|
|
238
244
|
|
|
239
|
-
describe Sequel::Model, "
|
|
240
|
-
|
|
241
|
-
before(:each) do
|
|
245
|
+
describe Sequel::Model, "constructors" do
|
|
246
|
+
before do
|
|
242
247
|
@m = Class.new(Sequel::Model)
|
|
243
248
|
@m.columns :a, :b
|
|
244
249
|
end
|
|
@@ -257,11 +262,38 @@ describe Sequel::Model, "constructor" do
|
|
|
257
262
|
m.values[:a].should == 1
|
|
258
263
|
end
|
|
259
264
|
|
|
265
|
+
it "should have dataset row_proc create an existing object" do
|
|
266
|
+
@m.dataset = Sequel::Dataset.new(nil)
|
|
267
|
+
o = @m.dataset.row_proc.call(:a=>1)
|
|
268
|
+
o.should be_a_kind_of(@m)
|
|
269
|
+
o.values.should == {:a=>1}
|
|
270
|
+
o.new?.should be_false
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "should have .call create an existing object" do
|
|
274
|
+
o = @m.call(:a=>1)
|
|
275
|
+
o.should be_a_kind_of(@m)
|
|
276
|
+
o.values.should == {:a=>1}
|
|
277
|
+
o.new?.should be_false
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it "should have .load create an existing object" do
|
|
281
|
+
o = @m.load(:a=>1)
|
|
282
|
+
o.should be_a_kind_of(@m)
|
|
283
|
+
o.values.should == {:a=>1}
|
|
284
|
+
o.new?.should be_false
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "should have .new with a second true argument create an existing object" do
|
|
288
|
+
o = @m.new({:a=>1}, true)
|
|
289
|
+
o.should be_a_kind_of(@m)
|
|
290
|
+
o.values.should == {:a=>1}
|
|
291
|
+
o.new?.should be_false
|
|
292
|
+
end
|
|
260
293
|
end
|
|
261
294
|
|
|
262
295
|
describe Sequel::Model, "new" do
|
|
263
|
-
|
|
264
|
-
before(:each) do
|
|
296
|
+
before do
|
|
265
297
|
@m = Class.new(Sequel::Model) do
|
|
266
298
|
set_dataset MODEL_DB[:items]
|
|
267
299
|
columns :x, :id
|
|
@@ -281,15 +313,8 @@ describe Sequel::Model, "new" do
|
|
|
281
313
|
end
|
|
282
314
|
|
|
283
315
|
it "should use the last inserted id as primary key if not in values" do
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
super
|
|
287
|
-
1234
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def d.first
|
|
291
|
-
{:x => 1, :id => 1234}
|
|
292
|
-
end
|
|
316
|
+
@m.dataset._fetch = {:x => 1, :id => 1234}
|
|
317
|
+
@m.dataset.autoid = 1234
|
|
293
318
|
|
|
294
319
|
o = @m.new(:x => 1)
|
|
295
320
|
o.save
|
|
@@ -299,14 +324,12 @@ describe Sequel::Model, "new" do
|
|
|
299
324
|
o.save
|
|
300
325
|
o.id.should == 333
|
|
301
326
|
end
|
|
302
|
-
|
|
303
327
|
end
|
|
304
328
|
|
|
305
329
|
describe Sequel::Model, ".subset" do
|
|
306
330
|
before do
|
|
307
|
-
MODEL_DB.reset
|
|
308
|
-
|
|
309
331
|
@c = Class.new(Sequel::Model(:items))
|
|
332
|
+
MODEL_DB.reset
|
|
310
333
|
end
|
|
311
334
|
|
|
312
335
|
specify "should create a filter on the underlying dataset" do
|
|
@@ -334,44 +357,31 @@ describe Sequel::Model, ".subset" do
|
|
|
334
357
|
end
|
|
335
358
|
|
|
336
359
|
describe Sequel::Model, ".find" do
|
|
337
|
-
|
|
338
|
-
before(:each) do
|
|
339
|
-
MODEL_DB.reset
|
|
340
|
-
|
|
360
|
+
before do
|
|
341
361
|
@c = Class.new(Sequel::Model(:items))
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
@dataset = @c.dataset
|
|
345
|
-
$sqls = []
|
|
346
|
-
@dataset.extend(Module.new {
|
|
347
|
-
def fetch_rows(sql)
|
|
348
|
-
$sqls << sql
|
|
349
|
-
yield $cache_dataset_row
|
|
350
|
-
end
|
|
351
|
-
})
|
|
362
|
+
@c.dataset._fetch = {:name => 'sharon', :id => 1}
|
|
363
|
+
MODEL_DB.reset
|
|
352
364
|
end
|
|
353
365
|
|
|
354
366
|
it "should return the first record matching the given filter" do
|
|
355
367
|
@c.find(:name => 'sharon').should be_a_kind_of(@c)
|
|
356
|
-
|
|
368
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"]
|
|
357
369
|
|
|
358
370
|
@c.find(:name.like('abc%')).should be_a_kind_of(@c)
|
|
359
|
-
|
|
371
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (name LIKE 'abc%') LIMIT 1"]
|
|
360
372
|
end
|
|
361
373
|
|
|
362
374
|
specify "should accept filter blocks" do
|
|
363
375
|
@c.find{:id.sql_number > 1}.should be_a_kind_of(@c)
|
|
364
|
-
|
|
376
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id > 1) LIMIT 1"]
|
|
365
377
|
|
|
366
378
|
@c.find {(:x.sql_number > 1) & (:y.sql_number < 2)}.should be_a_kind_of(@c)
|
|
367
|
-
|
|
379
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"]
|
|
368
380
|
end
|
|
369
|
-
|
|
370
381
|
end
|
|
371
382
|
|
|
372
383
|
describe Sequel::Model, ".fetch" do
|
|
373
|
-
|
|
374
|
-
before(:each) do
|
|
384
|
+
before do
|
|
375
385
|
MODEL_DB.reset
|
|
376
386
|
@c = Class.new(Sequel::Model(:items))
|
|
377
387
|
end
|
|
@@ -388,80 +398,53 @@ describe Sequel::Model, ".fetch" do
|
|
|
388
398
|
end
|
|
389
399
|
|
|
390
400
|
describe Sequel::Model, ".find_or_create" do
|
|
391
|
-
|
|
392
|
-
before(:each) do
|
|
393
|
-
MODEL_DB.reset
|
|
401
|
+
before do
|
|
394
402
|
@c = Class.new(Sequel::Model(:items)) do
|
|
395
|
-
|
|
403
|
+
set_primary_key :id
|
|
396
404
|
columns :x
|
|
397
405
|
end
|
|
406
|
+
MODEL_DB.reset
|
|
398
407
|
end
|
|
399
408
|
|
|
400
409
|
it "should find the record" do
|
|
401
|
-
@c.find_or_create(:x => 1)
|
|
410
|
+
@c.find_or_create(:x => 1).should == @c.load(:x=>1, :id=>1)
|
|
402
411
|
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1"]
|
|
403
|
-
|
|
404
|
-
MODEL_DB.reset
|
|
405
412
|
end
|
|
406
413
|
|
|
407
414
|
it "should create the record if not found" do
|
|
408
|
-
@c.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
MODEL_DB.sqls.should == [
|
|
415
|
-
"SELECT * FROM items WHERE (x = 1) LIMIT 1",
|
|
416
|
-
"INSERT INTO items (x) VALUES (1)"
|
|
417
|
-
]
|
|
415
|
+
@c.dataset._fetch = [[], {:x=>1, :id=>1}]
|
|
416
|
+
@c.dataset.autoid = 1
|
|
417
|
+
@c.find_or_create(:x => 1).should == @c.load(:x=>1, :id=>1)
|
|
418
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1",
|
|
419
|
+
"INSERT INTO items (x) VALUES (1)",
|
|
420
|
+
"SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
|
418
421
|
end
|
|
419
422
|
|
|
420
423
|
it "should pass the new record to be created to the block if no record is found" do
|
|
421
|
-
@c.
|
|
422
|
-
@c.
|
|
423
|
-
|
|
424
|
+
@c.dataset._fetch = [[], {:x=>1, :id=>1}]
|
|
425
|
+
@c.dataset.autoid = 1
|
|
426
|
+
@c.find_or_create(:x => 1){|x| x[:y] = 2}.should == @c.load(:x=>1, :id=>1)
|
|
427
|
+
sqls = MODEL_DB.sqls
|
|
428
|
+
sqls.first.should == "SELECT * FROM items WHERE (x = 1) LIMIT 1"
|
|
429
|
+
["INSERT INTO items (x, y) VALUES (1, 2)", "INSERT INTO items (y, x) VALUES (2, 1)"].should include(sqls[1])
|
|
430
|
+
sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
|
|
424
431
|
end
|
|
425
432
|
end
|
|
426
433
|
|
|
427
434
|
describe Sequel::Model, ".all" do
|
|
428
|
-
|
|
429
|
-
before(:each) do
|
|
430
|
-
MODEL_DB.reset
|
|
431
|
-
@c = Class.new(Sequel::Model(:items)) do
|
|
432
|
-
no_primary_key
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
@c.dataset.meta_def(:all) {1234}
|
|
436
|
-
end
|
|
437
|
-
|
|
438
435
|
it "should return all records in the dataset" do
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
end
|
|
443
|
-
|
|
444
|
-
class DummyModelBased < Sequel::Model(:blog)
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
describe Sequel::Model, "(:tablename)" do
|
|
448
|
-
|
|
449
|
-
it "should allow reopening of descendant classes" do
|
|
450
|
-
proc do
|
|
451
|
-
eval "class DummyModelBased < Sequel::Model(:blog); end"
|
|
452
|
-
end.should_not raise_error
|
|
436
|
+
c = Class.new(Sequel::Model(:items))
|
|
437
|
+
c.all.should == [c.load(:x=>1, :id=>1)]
|
|
453
438
|
end
|
|
454
|
-
|
|
455
439
|
end
|
|
456
440
|
|
|
457
441
|
describe Sequel::Model, "A model class without a primary key" do
|
|
458
|
-
|
|
459
|
-
before(:each) do
|
|
460
|
-
MODEL_DB.reset
|
|
442
|
+
before do
|
|
461
443
|
@c = Class.new(Sequel::Model(:items)) do
|
|
462
444
|
columns :x
|
|
463
445
|
no_primary_key
|
|
464
446
|
end
|
|
447
|
+
MODEL_DB.reset
|
|
465
448
|
end
|
|
466
449
|
|
|
467
450
|
it "should be able to insert records without selecting them back" do
|
|
@@ -474,8 +457,11 @@ describe Sequel::Model, "A model class without a primary key" do
|
|
|
474
457
|
end
|
|
475
458
|
|
|
476
459
|
it "should raise when deleting" do
|
|
477
|
-
|
|
478
|
-
|
|
460
|
+
proc{@c.load(:x=>1).delete}.should raise_error
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it "should raise when updating" do
|
|
464
|
+
proc{@c.load(:x=>1).update(:x=>2)}.should raise_error
|
|
479
465
|
end
|
|
480
466
|
|
|
481
467
|
it "should insert a record when saving" do
|
|
@@ -484,24 +470,17 @@ describe Sequel::Model, "A model class without a primary key" do
|
|
|
484
470
|
o.save
|
|
485
471
|
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (2)']
|
|
486
472
|
end
|
|
487
|
-
|
|
488
473
|
end
|
|
489
474
|
|
|
490
475
|
describe Sequel::Model, "attribute accessors" do
|
|
491
476
|
before do
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
@c = Class.new(Sequel::Model) do
|
|
496
|
-
def self.db_schema
|
|
497
|
-
set_columns(Array(@columns))
|
|
498
|
-
@db_schema = {:x=>{:type=>:integer}, :y=>{:type=>:integer}}
|
|
499
|
-
end
|
|
500
|
-
def self.set_dataset(ds, opts={})
|
|
501
|
-
@columns = ds.columns
|
|
502
|
-
db_schema
|
|
503
|
-
end
|
|
477
|
+
db = Sequel.mock
|
|
478
|
+
def db.schema(*)
|
|
479
|
+
[[:x, {:type=>:integer}], [:y, {:type=>:integer}]]
|
|
504
480
|
end
|
|
481
|
+
@dataset = db[:items].columns(:x, :y)
|
|
482
|
+
@c = Class.new(Sequel::Model)
|
|
483
|
+
MODEL_DB.reset
|
|
505
484
|
end
|
|
506
485
|
|
|
507
486
|
it "should be created on set_dataset" do
|
|
@@ -533,7 +512,7 @@ describe Sequel::Model, "attribute accessors" do
|
|
|
533
512
|
end
|
|
534
513
|
|
|
535
514
|
it "should have a working typecasting setter even if the column is not selected" do
|
|
536
|
-
@c.set_dataset(@dataset.select(:y))
|
|
515
|
+
@c.set_dataset(@dataset.select(:y).columns(:y))
|
|
537
516
|
o = @c.new
|
|
538
517
|
|
|
539
518
|
o.x = '34'
|
|
@@ -541,7 +520,7 @@ describe Sequel::Model, "attribute accessors" do
|
|
|
541
520
|
end
|
|
542
521
|
|
|
543
522
|
it "should typecast if the new value is the same as the existing but has a different class" do
|
|
544
|
-
@c.set_dataset(@dataset.select(:y))
|
|
523
|
+
@c.set_dataset(@dataset.select(:y).columns(:y))
|
|
545
524
|
o = @c.new
|
|
546
525
|
|
|
547
526
|
o.x = 34
|
|
@@ -553,58 +532,51 @@ describe Sequel::Model, "attribute accessors" do
|
|
|
553
532
|
end
|
|
554
533
|
|
|
555
534
|
describe Sequel::Model, ".[]" do
|
|
556
|
-
|
|
557
|
-
before(:each) do
|
|
558
|
-
MODEL_DB.reset
|
|
559
|
-
|
|
535
|
+
before do
|
|
560
536
|
@c = Class.new(Sequel::Model(:items))
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
@dataset = @c.dataset
|
|
564
|
-
$sqls = []
|
|
565
|
-
@dataset.extend(Module.new {
|
|
566
|
-
def fetch_rows(sql)
|
|
567
|
-
$sqls << sql
|
|
568
|
-
yield $cache_dataset_row
|
|
569
|
-
end
|
|
570
|
-
})
|
|
537
|
+
@c.dataset._fetch = {:name => 'sharon', :id => 1}
|
|
538
|
+
MODEL_DB.reset
|
|
571
539
|
end
|
|
572
540
|
|
|
573
541
|
it "should return the first record for the given pk" do
|
|
574
|
-
@c[1].should
|
|
575
|
-
|
|
576
|
-
@c[9999].should
|
|
577
|
-
|
|
542
|
+
@c[1].should == @c.load(:name => 'sharon', :id => 1)
|
|
543
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 1"]
|
|
544
|
+
@c[9999].should == @c.load(:name => 'sharon', :id => 1)
|
|
545
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 9999"]
|
|
578
546
|
end
|
|
579
547
|
|
|
580
548
|
it "should work correctly for custom primary key" do
|
|
581
549
|
@c.set_primary_key :name
|
|
582
|
-
@c['sharon'].should
|
|
583
|
-
|
|
550
|
+
@c['sharon'].should == @c.load(:name => 'sharon', :id => 1)
|
|
551
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE name = 'sharon'"]
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
it "should return the first record for the given pk for a filtered dataset" do
|
|
555
|
+
@c.dataset = @c.dataset.filter(:active=>true)
|
|
556
|
+
@c[1].should == @c.load(:name => 'sharon', :id => 1)
|
|
557
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE ((active IS TRUE) AND (id = 1)) LIMIT 1"]
|
|
584
558
|
end
|
|
585
559
|
|
|
586
560
|
it "should work correctly for composite primary key specified as array" do
|
|
587
561
|
@c.set_primary_key [:node_id, :kind]
|
|
588
562
|
@c[3921, 201].should be_a_kind_of(@c)
|
|
589
|
-
|
|
590
|
-
|
|
563
|
+
sqls = MODEL_DB.sqls
|
|
564
|
+
sqls.length.should == 1
|
|
565
|
+
sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
|
|
591
566
|
end
|
|
592
567
|
|
|
593
568
|
it "should work correctly for composite primary key specified as separate arguments" do
|
|
594
569
|
@c.set_primary_key :node_id, :kind
|
|
595
570
|
@c[3921, 201].should be_a_kind_of(@c)
|
|
596
|
-
|
|
597
|
-
|
|
571
|
+
sqls = MODEL_DB.sqls
|
|
572
|
+
sqls.length.should == 1
|
|
573
|
+
sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
|
|
598
574
|
end
|
|
599
575
|
end
|
|
600
576
|
|
|
601
577
|
describe "Model#inspect" do
|
|
602
|
-
before do
|
|
603
|
-
@o = Sequel::Model.load(:x => 333)
|
|
604
|
-
end
|
|
605
|
-
|
|
606
578
|
specify "should include the class name and the values" do
|
|
607
|
-
|
|
579
|
+
Sequel::Model.load(:x => 333).inspect.should == '#<Sequel::Model @values={:x=>333}>'
|
|
608
580
|
end
|
|
609
581
|
end
|
|
610
582
|
|
|
@@ -613,16 +585,13 @@ describe "Model.db_schema" do
|
|
|
613
585
|
@c = Class.new(Sequel::Model(:items)) do
|
|
614
586
|
def self.columns; orig_columns; end
|
|
615
587
|
end
|
|
616
|
-
@
|
|
617
|
-
@dataset
|
|
618
|
-
def @dataset.naked; self; end
|
|
619
|
-
def @dataset.columns; []; end
|
|
620
|
-
def @dataset.def_mutation_method(*names); end
|
|
588
|
+
@db = Sequel.mock
|
|
589
|
+
@dataset = @db[:items]
|
|
621
590
|
end
|
|
622
591
|
|
|
623
592
|
specify "should use the database's schema_for_table and set the columns and dataset columns" do
|
|
624
593
|
d = @dataset.db
|
|
625
|
-
def
|
|
594
|
+
def @db.schema(table, opts = {})
|
|
626
595
|
[[:x, {:type=>:integer}], [:y, {:type=>:string}]]
|
|
627
596
|
end
|
|
628
597
|
@c.dataset = @dataset
|
|
@@ -632,36 +601,20 @@ describe "Model.db_schema" do
|
|
|
632
601
|
end
|
|
633
602
|
|
|
634
603
|
specify "should not restrict the schema for datasets with a :select option" do
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
def d.schema(table, opts = {})
|
|
604
|
+
def @c.columns; [:x, :z]; end
|
|
605
|
+
def @db.schema(table, opts = {})
|
|
638
606
|
[[:x, {:type=>:integer}], [:y, {:type=>:string}]]
|
|
639
607
|
end
|
|
640
|
-
|
|
641
|
-
@c.dataset = ds
|
|
608
|
+
@c.dataset = @dataset.select(:x, :y___z)
|
|
642
609
|
@c.db_schema.should == {:x=>{:type=>:integer}, :z=>{}, :y=>{:type=>:string}}
|
|
643
610
|
end
|
|
644
611
|
|
|
645
|
-
specify "should not use schema if the dataset uses multiple tables or custom sql" do
|
|
646
|
-
ds = @dataset.join(:x, :id)
|
|
647
|
-
d = ds.db
|
|
648
|
-
e = false
|
|
649
|
-
d.meta_def(:schema){|table, *opts| e = true}
|
|
650
|
-
def @c.columns; [:x]; end
|
|
651
|
-
@c.dataset = ds
|
|
652
|
-
@c.db_schema.should == {:x=>{}}
|
|
653
|
-
e.should == false
|
|
654
|
-
end
|
|
655
|
-
|
|
656
612
|
specify "should fallback to fetching records if schema raises an error" do
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
def d.schema(table, opts={})
|
|
660
|
-
raise StandardError
|
|
613
|
+
def @db.schema(table, opts={})
|
|
614
|
+
raise Sequel::Error
|
|
661
615
|
end
|
|
662
|
-
|
|
663
|
-
@c.
|
|
664
|
-
@c.db_schema.should == {:x=>{}}
|
|
616
|
+
@c.dataset = @dataset.join(:x, :id).columns(:id, :x)
|
|
617
|
+
@c.db_schema.should == {:x=>{}, :id=>{}}
|
|
665
618
|
end
|
|
666
619
|
|
|
667
620
|
specify "should automatically set a singular primary key based on the schema" do
|