colincasey-sequel 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. data/CHANGELOG +7 -1
  2. data/doc/advanced_associations.rdoc +614 -0
  3. data/doc/cheat_sheet.rdoc +223 -0
  4. data/doc/dataset_filtering.rdoc +158 -0
  5. data/doc/prepared_statements.rdoc +104 -0
  6. data/doc/release_notes/1.0.txt +38 -0
  7. data/doc/release_notes/1.1.txt +143 -0
  8. data/doc/release_notes/1.3.txt +101 -0
  9. data/doc/release_notes/1.4.0.txt +53 -0
  10. data/doc/release_notes/1.5.0.txt +155 -0
  11. data/doc/release_notes/2.0.0.txt +298 -0
  12. data/doc/release_notes/2.1.0.txt +271 -0
  13. data/doc/release_notes/2.10.0.txt +328 -0
  14. data/doc/release_notes/2.2.0.txt +253 -0
  15. data/doc/release_notes/2.3.0.txt +88 -0
  16. data/doc/release_notes/2.4.0.txt +106 -0
  17. data/doc/release_notes/2.5.0.txt +137 -0
  18. data/doc/release_notes/2.6.0.txt +157 -0
  19. data/doc/release_notes/2.7.0.txt +166 -0
  20. data/doc/release_notes/2.8.0.txt +171 -0
  21. data/doc/release_notes/2.9.0.txt +97 -0
  22. data/doc/schema.rdoc +29 -0
  23. data/doc/sharding.rdoc +113 -0
  24. data/lib/sequel.rb +1 -0
  25. data/lib/sequel_core/adapters/ado.rb +89 -0
  26. data/lib/sequel_core/adapters/db2.rb +143 -0
  27. data/lib/sequel_core/adapters/dbi.rb +112 -0
  28. data/lib/sequel_core/adapters/do/mysql.rb +38 -0
  29. data/lib/sequel_core/adapters/do/postgres.rb +92 -0
  30. data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
  31. data/lib/sequel_core/adapters/do.rb +205 -0
  32. data/lib/sequel_core/adapters/firebird.rb +298 -0
  33. data/lib/sequel_core/adapters/informix.rb +85 -0
  34. data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
  35. data/lib/sequel_core/adapters/jdbc/mysql.rb +66 -0
  36. data/lib/sequel_core/adapters/jdbc/oracle.rb +23 -0
  37. data/lib/sequel_core/adapters/jdbc/postgresql.rb +113 -0
  38. data/lib/sequel_core/adapters/jdbc/sqlite.rb +43 -0
  39. data/lib/sequel_core/adapters/jdbc.rb +491 -0
  40. data/lib/sequel_core/adapters/mysql.rb +369 -0
  41. data/lib/sequel_core/adapters/odbc.rb +174 -0
  42. data/lib/sequel_core/adapters/openbase.rb +68 -0
  43. data/lib/sequel_core/adapters/oracle.rb +107 -0
  44. data/lib/sequel_core/adapters/postgres.rb +456 -0
  45. data/lib/sequel_core/adapters/shared/ms_access.rb +110 -0
  46. data/lib/sequel_core/adapters/shared/mssql.rb +102 -0
  47. data/lib/sequel_core/adapters/shared/mysql.rb +325 -0
  48. data/lib/sequel_core/adapters/shared/oracle.rb +61 -0
  49. data/lib/sequel_core/adapters/shared/postgres.rb +715 -0
  50. data/lib/sequel_core/adapters/shared/progress.rb +31 -0
  51. data/lib/sequel_core/adapters/shared/sqlite.rb +265 -0
  52. data/lib/sequel_core/adapters/sqlite.rb +248 -0
  53. data/lib/sequel_core/connection_pool.rb +258 -0
  54. data/lib/sequel_core/core_ext.rb +217 -0
  55. data/lib/sequel_core/core_sql.rb +202 -0
  56. data/lib/sequel_core/database/schema.rb +164 -0
  57. data/lib/sequel_core/database.rb +691 -0
  58. data/lib/sequel_core/dataset/callback.rb +13 -0
  59. data/lib/sequel_core/dataset/convenience.rb +237 -0
  60. data/lib/sequel_core/dataset/pagination.rb +96 -0
  61. data/lib/sequel_core/dataset/prepared_statements.rb +220 -0
  62. data/lib/sequel_core/dataset/query.rb +41 -0
  63. data/lib/sequel_core/dataset/schema.rb +15 -0
  64. data/lib/sequel_core/dataset/sql.rb +1010 -0
  65. data/lib/sequel_core/dataset/stored_procedures.rb +75 -0
  66. data/lib/sequel_core/dataset/unsupported.rb +43 -0
  67. data/lib/sequel_core/dataset.rb +511 -0
  68. data/lib/sequel_core/deprecated.rb +26 -0
  69. data/lib/sequel_core/exceptions.rb +44 -0
  70. data/lib/sequel_core/migration.rb +212 -0
  71. data/lib/sequel_core/object_graph.rb +230 -0
  72. data/lib/sequel_core/pretty_table.rb +71 -0
  73. data/lib/sequel_core/schema/generator.rb +320 -0
  74. data/lib/sequel_core/schema/sql.rb +325 -0
  75. data/lib/sequel_core/schema.rb +2 -0
  76. data/lib/sequel_core/sql.rb +887 -0
  77. data/lib/sequel_core/version.rb +11 -0
  78. data/lib/sequel_core.rb +172 -0
  79. data/lib/sequel_model/association_reflection.rb +267 -0
  80. data/lib/sequel_model/associations.rb +499 -0
  81. data/lib/sequel_model/base.rb +523 -0
  82. data/lib/sequel_model/caching.rb +82 -0
  83. data/lib/sequel_model/dataset_methods.rb +26 -0
  84. data/lib/sequel_model/eager_loading.rb +370 -0
  85. data/lib/sequel_model/exceptions.rb +7 -0
  86. data/lib/sequel_model/hooks.rb +101 -0
  87. data/lib/sequel_model/inflector.rb +281 -0
  88. data/lib/sequel_model/plugins.rb +62 -0
  89. data/lib/sequel_model/record.rb +568 -0
  90. data/lib/sequel_model/schema.rb +49 -0
  91. data/lib/sequel_model/validations.rb +429 -0
  92. data/lib/sequel_model.rb +91 -0
  93. data/spec/adapters/ado_spec.rb +46 -0
  94. data/spec/adapters/firebird_spec.rb +376 -0
  95. data/spec/adapters/informix_spec.rb +96 -0
  96. data/spec/adapters/mysql_spec.rb +881 -0
  97. data/spec/adapters/oracle_spec.rb +244 -0
  98. data/spec/adapters/postgres_spec.rb +687 -0
  99. data/spec/adapters/spec_helper.rb +10 -0
  100. data/spec/adapters/sqlite_spec.rb +555 -0
  101. data/spec/integration/dataset_test.rb +134 -0
  102. data/spec/integration/eager_loader_test.rb +696 -0
  103. data/spec/integration/prepared_statement_test.rb +130 -0
  104. data/spec/integration/schema_test.rb +180 -0
  105. data/spec/integration/spec_helper.rb +58 -0
  106. data/spec/integration/type_test.rb +96 -0
  107. data/spec/rcov.opts +6 -0
  108. data/spec/sequel_core/connection_pool_spec.rb +526 -0
  109. data/spec/sequel_core/core_ext_spec.rb +156 -0
  110. data/spec/sequel_core/core_sql_spec.rb +522 -0
  111. data/spec/sequel_core/database_spec.rb +1188 -0
  112. data/spec/sequel_core/dataset_spec.rb +3481 -0
  113. data/spec/sequel_core/expression_filters_spec.rb +363 -0
  114. data/spec/sequel_core/migration_spec.rb +261 -0
  115. data/spec/sequel_core/object_graph_spec.rb +272 -0
  116. data/spec/sequel_core/pretty_table_spec.rb +58 -0
  117. data/spec/sequel_core/schema_generator_spec.rb +167 -0
  118. data/spec/sequel_core/schema_spec.rb +780 -0
  119. data/spec/sequel_core/spec_helper.rb +55 -0
  120. data/spec/sequel_core/version_spec.rb +7 -0
  121. data/spec/sequel_model/association_reflection_spec.rb +93 -0
  122. data/spec/sequel_model/associations_spec.rb +1767 -0
  123. data/spec/sequel_model/base_spec.rb +419 -0
  124. data/spec/sequel_model/caching_spec.rb +215 -0
  125. data/spec/sequel_model/dataset_methods_spec.rb +78 -0
  126. data/spec/sequel_model/eager_loading_spec.rb +1165 -0
  127. data/spec/sequel_model/hooks_spec.rb +485 -0
  128. data/spec/sequel_model/inflector_spec.rb +119 -0
  129. data/spec/sequel_model/model_spec.rb +588 -0
  130. data/spec/sequel_model/plugins_spec.rb +80 -0
  131. data/spec/sequel_model/record_spec.rb +1184 -0
  132. data/spec/sequel_model/schema_spec.rb +90 -0
  133. data/spec/sequel_model/spec_helper.rb +78 -0
  134. data/spec/sequel_model/validations_spec.rb +1067 -0
  135. data/spec/spec.opts +0 -0
  136. data/spec/spec_config.rb.example +10 -0
  137. metadata +177 -3
@@ -0,0 +1,1184 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Model#save" do
4
+
5
+ before(:each) do
6
+ MODEL_DB.reset
7
+
8
+ @c = Class.new(Sequel::Model(:items)) do
9
+ columns :id, :x, :y
10
+ end
11
+ end
12
+
13
+ it "should insert a record for a new model instance" do
14
+ o = @c.new(:x => 1)
15
+ o.save
16
+
17
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
18
+ end
19
+
20
+ it "should use dataset's insert_select method if present" do
21
+ ds = @c.dataset = @c.dataset.clone
22
+ def ds.insert_select(hash)
23
+ execute("INSERT INTO items (y) VALUES (2)")
24
+ {:y=>2}
25
+ end
26
+ o = @c.new(:x => 1)
27
+ o.save
28
+
29
+ o.values.should == {:y=>2}
30
+ MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (2)"
31
+ end
32
+
33
+ it "should update a record for an existing model instance" do
34
+ o = @c.load(:id => 3, :x => 1)
35
+ o.save
36
+
37
+ MODEL_DB.sqls.first.should =~
38
+ /UPDATE items SET (id = 3, x = 1|x = 1, id = 3) WHERE \(id = 3\)/
39
+ end
40
+
41
+ it "should update only the given columns if given" do
42
+ o = @c.load(:id => 3, :x => 1, :y => nil)
43
+ o.save(:y)
44
+
45
+ MODEL_DB.sqls.first.should == "UPDATE items SET y = NULL WHERE (id = 3)"
46
+ end
47
+
48
+ it "should mark saved columns as not changed" do
49
+ o = @c.load(:id => 3, :x => 1, :y => nil)
50
+ o[:y] = 4
51
+ o.changed_columns.should == [:y]
52
+ o.save(:x)
53
+ o.changed_columns.should == [:y]
54
+ o.save(:y)
55
+ o.changed_columns.should == []
56
+ end
57
+
58
+ it "should preserve changed_columns' and @new's value until all hook finish running" do
59
+ res = nil
60
+ @c.after_save { res = [changed_columns, @new].flatten}
61
+ o = @c.new(:x => 1, :y => nil)
62
+ o[:x] = 2
63
+ o.save
64
+ res.should == [:x,true]
65
+
66
+ res = nil
67
+ o = @c.load(:id => 23,:x => 1, :y => nil)
68
+ o[:x] = 2
69
+ o.save
70
+ res.should == [:x,false]
71
+
72
+ res = nil
73
+ o = @c.load(:id => 23,:x => 1, :y => nil)
74
+ o[:x] = 2
75
+ o[:y] = 22
76
+ o.save(:x)
77
+ res.should == [:x,:y,false]
78
+ end
79
+
80
+ end
81
+
82
+ describe "Model#save_changes" do
83
+
84
+ before(:each) do
85
+ MODEL_DB.reset
86
+
87
+ @c = Class.new(Sequel::Model(:items)) do
88
+ unrestrict_primary_key
89
+ columns :id, :x, :y
90
+ end
91
+ end
92
+
93
+ it "should do nothing if no changed columns" do
94
+ o = @c.new(:id => 3, :x => 1, :y => nil)
95
+ o.save_changes
96
+
97
+ MODEL_DB.sqls.should be_empty
98
+
99
+ o = @c.load(:id => 3, :x => 1, :y => nil)
100
+ o.save_changes
101
+
102
+ MODEL_DB.sqls.should be_empty
103
+ end
104
+
105
+ it "should update only changed columns" do
106
+ o = @c.load(:id => 3, :x => 1, :y => nil)
107
+ o.x = 2
108
+
109
+ o.save_changes
110
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
111
+ o.save_changes
112
+ o.save_changes
113
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
114
+ MODEL_DB.reset
115
+
116
+ o.y = 4
117
+ o.save_changes
118
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
119
+ o.save_changes
120
+ o.save_changes
121
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
122
+ end
123
+
124
+ it "should not consider columns changed if the values did not change" do
125
+ o = @c.load(:id => 3, :x => 1, :y => nil)
126
+ o.x = 1
127
+
128
+ o.save_changes
129
+ MODEL_DB.sqls.should == []
130
+ o.x = 3
131
+ o.save_changes
132
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
133
+ MODEL_DB.reset
134
+
135
+ o[:y] = nil
136
+ o.save_changes
137
+ MODEL_DB.sqls.should == []
138
+ o[:y] = 4
139
+ o.save_changes
140
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
141
+ end
142
+
143
+ it "should update columns changed in a before_update hook" do
144
+ o = @c.load(:id => 3, :x => 1, :y => nil)
145
+ @c.before_update{self.x += 1}
146
+ o.save_changes
147
+ MODEL_DB.sqls.should == []
148
+ o.x = 2
149
+ o.save_changes
150
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
151
+ MODEL_DB.reset
152
+ o.save_changes
153
+ MODEL_DB.sqls.should == []
154
+ o.x = 4
155
+ o.save_changes
156
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
157
+ MODEL_DB.reset
158
+ end
159
+
160
+ it "should update columns changed in a before_save hook" do
161
+ o = @c.load(:id => 3, :x => 1, :y => nil)
162
+ @c.before_save{self.x += 1}
163
+ o.save_changes
164
+ MODEL_DB.sqls.should == []
165
+ o.x = 2
166
+ o.save_changes
167
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
168
+ MODEL_DB.reset
169
+ o.save_changes
170
+ MODEL_DB.sqls.should == []
171
+ o.x = 4
172
+ o.save_changes
173
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
174
+ MODEL_DB.reset
175
+ end
176
+ end
177
+
178
+ describe "Model#update_values" do
179
+ before(:each) do
180
+ MODEL_DB.reset
181
+
182
+ @c = Class.new(Sequel::Model(:items)) do
183
+ unrestrict_primary_key
184
+ columns :id, :x, :y
185
+ end
186
+ end
187
+
188
+ it "should generate an update statement" do
189
+ o = @c.new(:id => 1)
190
+ o.update_values(:x => 1)
191
+ MODEL_DB.sqls.first.should == "UPDATE items SET x = 1 WHERE (id = 1)"
192
+ end
193
+
194
+ it "should update attribute values" do
195
+ o = @c.new(:id => 1)
196
+ o.x.should be_nil
197
+ o.update_values(:x => 1)
198
+ o.x.should == 1
199
+ end
200
+
201
+ it "should support string keys" do
202
+ o = @c.new(:id => 1)
203
+ o.x.should be_nil
204
+ o.update_values('x' => 1)
205
+ o.x.should == 1
206
+ MODEL_DB.sqls.first.should == "UPDATE items SET x = 1 WHERE (id = 1)"
207
+ end
208
+ end
209
+
210
+ describe "Model#set_values" do
211
+ before(:each) do
212
+ MODEL_DB.reset
213
+
214
+ @c = Class.new(Sequel::Model(:items)) do
215
+ unrestrict_primary_key
216
+ columns :id, :x, :y
217
+ end
218
+ end
219
+
220
+ it "should not touch the database" do
221
+ o = @c.new(:id => 1)
222
+ o.set_values(:x => 1)
223
+ MODEL_DB.sqls.should == []
224
+ end
225
+
226
+ it "should update attribute values" do
227
+ o = @c.new(:id => 1)
228
+ o.x.should be_nil
229
+ o.set_values(:x => 1)
230
+ o.x.should == 1
231
+ end
232
+
233
+ it "should support string keys" do
234
+ o = @c.new(:id => 1)
235
+ o.x.should be_nil
236
+ o.set_values('x' => 1)
237
+ o.x.should == 1
238
+ end
239
+
240
+ it "should raise an error if used with a non-String, non-Symbol key" do
241
+ proc{@c.new.set_values(1=>2)}.should raise_error(Sequel::Error)
242
+ end
243
+ end
244
+
245
+ describe "Model#new?" do
246
+
247
+ before(:each) do
248
+ MODEL_DB.reset
249
+
250
+ @c = Class.new(Sequel::Model(:items)) do
251
+ unrestrict_primary_key
252
+ columns :x
253
+ end
254
+ end
255
+
256
+ it "should be true for a new instance" do
257
+ n = @c.new(:x => 1)
258
+ n.should be_new
259
+ end
260
+
261
+ it "should be false after saving" do
262
+ n = @c.new(:x => 1)
263
+ n.save
264
+ n.should_not be_new
265
+ end
266
+ end
267
+
268
+ describe Sequel::Model, "w/ primary key" do
269
+
270
+ it "should default to ':id'" do
271
+ model_a = Class.new Sequel::Model
272
+ model_a.primary_key.should be_equal(:id)
273
+ end
274
+
275
+ it "should be changed through 'set_primary_key'" do
276
+ model_a = Class.new(Sequel::Model) { set_primary_key :a }
277
+ model_a.primary_key.should be_equal(:a)
278
+ end
279
+
280
+ it "should support multi argument composite keys" do
281
+ model_a = Class.new(Sequel::Model) { set_primary_key :a, :b }
282
+ model_a.primary_key.should be_eql([:a, :b])
283
+ end
284
+
285
+ it "should accept single argument composite keys" do
286
+ model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
287
+ model_a.primary_key.should be_eql([:a, :b])
288
+ end
289
+
290
+ end
291
+
292
+ describe Sequel::Model, "w/o primary key" do
293
+ it "should return nil for primary key" do
294
+ Class.new(Sequel::Model) { no_primary_key }.primary_key.should be_nil
295
+ end
296
+
297
+ it "should raise a Sequel::Error on 'this'" do
298
+ instance = Class.new(Sequel::Model) { no_primary_key }.new
299
+ proc { instance.this }.should raise_error(Sequel::Error)
300
+ end
301
+ end
302
+
303
+ describe Sequel::Model, "with this" do
304
+
305
+ before { @example = Class.new Sequel::Model(:examples); @example.columns :id, :a, :x, :y }
306
+
307
+ it "should return a dataset identifying the record" do
308
+ instance = @example.load :id => 3
309
+ instance.this.sql.should be_eql("SELECT * FROM examples WHERE (id = 3) LIMIT 1")
310
+ end
311
+
312
+ it "should support arbitary primary keys" do
313
+ @example.set_primary_key :a
314
+
315
+ instance = @example.load :a => 3
316
+ instance.this.sql.should be_eql("SELECT * FROM examples WHERE (a = 3) LIMIT 1")
317
+ end
318
+
319
+ it "should support composite primary keys" do
320
+ @example.set_primary_key :x, :y
321
+ instance = @example.load :x => 4, :y => 5
322
+
323
+ parts = [
324
+ 'SELECT * FROM examples WHERE %s LIMIT 1',
325
+ '((x = 4) AND (y = 5))',
326
+ '((y = 5) AND (x = 4))'
327
+ ].map { |expr| Regexp.escape expr }
328
+ regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
329
+
330
+ instance.this.sql.should match(regexp)
331
+ end
332
+
333
+ end
334
+
335
+ describe "Model#pk" do
336
+ before(:each) do
337
+ @m = Class.new(Sequel::Model)
338
+ @m.columns :id, :x, :y
339
+ end
340
+
341
+ it "should be default return the value of the :id column" do
342
+ m = @m.load(:id => 111, :x => 2, :y => 3)
343
+ m.pk.should == 111
344
+ end
345
+
346
+ it "should be return the primary key value for custom primary key" do
347
+ @m.set_primary_key :x
348
+ m = @m.load(:id => 111, :x => 2, :y => 3)
349
+ m.pk.should == 2
350
+ end
351
+
352
+ it "should be return the primary key value for composite primary key" do
353
+ @m.set_primary_key [:y, :x]
354
+ m = @m.load(:id => 111, :x => 2, :y => 3)
355
+ m.pk.should == [3, 2]
356
+ end
357
+
358
+ it "should raise if no primary key" do
359
+ @m.set_primary_key nil
360
+ m = @m.new(:id => 111, :x => 2, :y => 3)
361
+ proc {m.pk}.should raise_error(Sequel::Error)
362
+
363
+ @m.no_primary_key
364
+ m = @m.new(:id => 111, :x => 2, :y => 3)
365
+ proc {m.pk}.should raise_error(Sequel::Error)
366
+ end
367
+ end
368
+
369
+ describe "Model#pk_hash" do
370
+ before(:each) do
371
+ @m = Class.new(Sequel::Model)
372
+ @m.columns :id, :x, :y
373
+ end
374
+
375
+ it "should be default return the value of the :id column" do
376
+ m = @m.load(:id => 111, :x => 2, :y => 3)
377
+ m.pk_hash.should == {:id => 111}
378
+ end
379
+
380
+ it "should be return the primary key value for custom primary key" do
381
+ @m.set_primary_key :x
382
+ m = @m.load(:id => 111, :x => 2, :y => 3)
383
+ m.pk_hash.should == {:x => 2}
384
+ end
385
+
386
+ it "should be return the primary key value for composite primary key" do
387
+ @m.set_primary_key [:y, :x]
388
+ m = @m.load(:id => 111, :x => 2, :y => 3)
389
+ m.pk_hash.should == {:y => 3, :x => 2}
390
+ end
391
+
392
+ it "should raise if no primary key" do
393
+ @m.set_primary_key nil
394
+ m = @m.new(:id => 111, :x => 2, :y => 3)
395
+ proc {m.pk_hash}.should raise_error(Sequel::Error)
396
+
397
+ @m.no_primary_key
398
+ m = @m.new(:id => 111, :x => 2, :y => 3)
399
+ proc {m.pk_hash}.should raise_error(Sequel::Error)
400
+ end
401
+ end
402
+
403
+ describe Sequel::Model, "#set" do
404
+ before do
405
+ MODEL_DB.reset
406
+
407
+ @c = Class.new(Sequel::Model(:items)) do
408
+ set_primary_key :id
409
+ columns :x, :y, :id
410
+ end
411
+ @c.strict_param_setting = false
412
+ @c.instance_variable_set(:@columns, true)
413
+ @o1 = @c.new
414
+ @o2 = @c.load(:id => 5)
415
+ end
416
+
417
+ it "should filter the given params using the model columns" do
418
+ @o1.set(:x => 1, :z => 2)
419
+ @o1.values.should == {:x => 1}
420
+ MODEL_DB.sqls.should == []
421
+
422
+ @o2.set(:y => 1, :abc => 2)
423
+ @o2.values.should == {:y => 1, :id=> 5}
424
+ MODEL_DB.sqls.should == []
425
+ end
426
+
427
+ it "should work with both strings and symbols" do
428
+ @o1.set('x'=> 1, 'z'=> 2)
429
+ @o1.values.should == {:x => 1}
430
+ MODEL_DB.sqls.should == []
431
+
432
+ @o2.set('y'=> 1, 'abc'=> 2)
433
+ @o2.values.should == {:y => 1, :id=> 5}
434
+ MODEL_DB.sqls.should == []
435
+ end
436
+
437
+ it "should support virtual attributes" do
438
+ @c.class_def(:blah=) {|v| self.x = v}
439
+ @o1.set(:blah => 333)
440
+ @o1.values.should == {:x => 333}
441
+ MODEL_DB.sqls.should == []
442
+ @o1.set('blah'=> 334)
443
+ @o1.values.should == {:x => 334}
444
+ MODEL_DB.sqls.should == []
445
+ end
446
+
447
+ it "should not modify the primary key" do
448
+ @o1.set(:x => 1, :id => 2)
449
+ @o1.values.should == {:x => 1}
450
+ MODEL_DB.sqls.should == []
451
+ @o2.set('y'=> 1, 'id'=> 2)
452
+ @o2.values.should == {:y => 1, :id=> 5}
453
+ MODEL_DB.sqls.should == []
454
+ end
455
+
456
+ it "should be aliased as set_with_params" do
457
+ @o1.set_with_params(:x => 1, :z => 2)
458
+ @o1.values.should == {:x => 1}
459
+ MODEL_DB.sqls.should == []
460
+ end
461
+
462
+ it "should return self" do
463
+ returned_value = @o1.set_with_params(:x => 1, :z => 2)
464
+ returned_value.should == @o1
465
+ MODEL_DB.sqls.should == []
466
+ end
467
+
468
+ it "should assume it is a column if no column information is present and the key is a symbol" do
469
+ @c.instance_variable_set(:@columns, nil)
470
+ o = @c.new.set(:x123=>1)
471
+ o[:x123].should == 1
472
+ end
473
+ end
474
+
475
+ describe Sequel::Model, "#update" do
476
+ before do
477
+ MODEL_DB.reset
478
+
479
+ @c = Class.new(Sequel::Model(:items)) do
480
+ set_primary_key :id
481
+ columns :x, :y, :id
482
+ end
483
+ @c.strict_param_setting = false
484
+ @c.instance_variable_set(:@columns, true)
485
+ @o1 = @c.new
486
+ @o2 = @c.load(:id => 5)
487
+ end
488
+
489
+ it "should filter the given params using the model columns" do
490
+ @o1.update(:x => 1, :z => 2)
491
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
492
+
493
+ MODEL_DB.reset
494
+ @o2.update(:y => 1, :abc => 2)
495
+ MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
496
+ end
497
+
498
+ it "should support virtual attributes" do
499
+ @c.class_def(:blah=) {|v| self.x = v}
500
+ @o1.update(:blah => 333)
501
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
502
+ end
503
+
504
+ it "should not modify the primary key" do
505
+ @o1.update(:x => 1, :id => 2)
506
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
507
+ MODEL_DB.reset
508
+ @o2.update('y'=> 1, 'id'=> 2)
509
+ @o2.values.should == {:y => 1, :id=> 5}
510
+ MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
511
+ end
512
+
513
+ it "should be aliased as update_with_params" do
514
+ @o1.update_with_params(:x => 1, :z => 2)
515
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
516
+ end
517
+ end
518
+
519
+ describe Sequel::Model, "#(set|update)_(all|except|only)" do
520
+ before do
521
+ MODEL_DB.reset
522
+
523
+ @c = Class.new(Sequel::Model(:items)) do
524
+ set_primary_key :id
525
+ columns :x, :y, :z, :id
526
+ set_allowed_columns :x
527
+ set_restricted_columns :y
528
+ end
529
+ @c.strict_param_setting = false
530
+ @c.instance_variable_set(:@columns, true)
531
+ @o1 = @c.new
532
+ end
533
+
534
+ it "#set_all should set all attributes" do
535
+ @o1.set_all(:x => 1, :y => 2, :z=>3, :id=>4)
536
+ @o1.values.should == {:x => 1, :y => 2, :z=>3}
537
+ end
538
+
539
+ it "#set_only should only set given attributes" do
540
+ @o1.set_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
541
+ @o1.values.should == {:x => 1, :y => 2}
542
+ @o1.set_only({:x => 4, :y => 5, :z=>6, :id=>7}, :x, :y)
543
+ @o1.values.should == {:x => 4, :y => 5}
544
+ end
545
+
546
+ it "#set_except should not set given attributes" do
547
+ @o1.set_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
548
+ @o1.values.should == {:x => 1}
549
+ @o1.set_except({:x => 4, :y => 2, :z=>3, :id=>4}, :y, :z)
550
+ @o1.values.should == {:x => 4}
551
+ end
552
+
553
+ it "#update_all should update all attributes" do
554
+ @c.new.update_all(:x => 1, :id=>4)
555
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
556
+ MODEL_DB.reset
557
+ @c.new.update_all(:y => 1, :id=>4)
558
+ MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
559
+ MODEL_DB.reset
560
+ @c.new.update_all(:z => 1, :id=>4)
561
+ MODEL_DB.sqls.first.should == "INSERT INTO items (z) VALUES (1)"
562
+ end
563
+
564
+ it "#update_only should only update given attributes" do
565
+ @o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
566
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
567
+ MODEL_DB.reset
568
+ @c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
569
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
570
+ end
571
+
572
+ it "#update_except should not update given attributes" do
573
+ @o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
574
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
575
+ MODEL_DB.reset
576
+ @c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
577
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
578
+ end
579
+ end
580
+
581
+ describe Sequel::Model, "#destroy" do
582
+ before do
583
+ MODEL_DB.reset
584
+ @model = Class.new(Sequel::Model(:items))
585
+ @model.columns :id
586
+ @model.dataset.meta_def(:delete) {MODEL_DB.execute delete_sql}
587
+
588
+ @instance = @model.load(:id => 1234)
589
+ end
590
+
591
+ it "should return self" do
592
+ @model.db.should_receive(:transaction)
593
+ @model.after_destroy{3}
594
+ @instance.destroy.should == @instance
595
+ end
596
+
597
+ it "should run within a transaction" do
598
+ @model.db.should_receive(:transaction)
599
+ @instance.destroy
600
+ end
601
+
602
+ it "should run before_destroy and after_destroy hooks" do
603
+ @model.before_destroy {MODEL_DB.execute('before blah')}
604
+ @model.after_destroy {MODEL_DB.execute('after blah')}
605
+ @instance.destroy
606
+
607
+ MODEL_DB.sqls.should == [
608
+ "before blah",
609
+ "DELETE FROM items WHERE (id = 1234)",
610
+ "after blah"
611
+ ]
612
+ end
613
+ end
614
+
615
+ describe Sequel::Model, "#exists?" do
616
+ before(:each) do
617
+ @model = Class.new(Sequel::Model(:items))
618
+ @m = @model.new
619
+ end
620
+
621
+ it "should returns true when #this.count > 0" do
622
+ @m.this.meta_def(:count) {1}
623
+ @m.exists?.should be_true
624
+ end
625
+
626
+ it "should return false when #this.count == 0" do
627
+ @m.this.meta_def(:count) {0}
628
+ @m.exists?.should be_false
629
+ end
630
+ end
631
+
632
+ describe Sequel::Model, "#each" do
633
+ setup do
634
+ @model = Class.new(Sequel::Model(:items))
635
+ @model.columns :a, :b, :id
636
+ @m = @model.load(:a => 1, :b => 2, :id => 4444)
637
+ end
638
+
639
+ specify "should iterate over the values" do
640
+ h = {}
641
+ @m.each {|k, v| h[k] = v}
642
+ h.should == {:a => 1, :b => 2, :id => 4444}
643
+ end
644
+ end
645
+
646
+ describe Sequel::Model, "#keys" do
647
+ setup do
648
+ @model = Class.new(Sequel::Model(:items))
649
+ @model.columns :a, :b, :id
650
+ @m = @model.load(:a => 1, :b => 2, :id => 4444)
651
+ end
652
+
653
+ specify "should return the value keys" do
654
+ @m.keys.size.should == 3
655
+ @m.keys.should include(:a, :b, :id)
656
+
657
+ @m = @model.new()
658
+ @m.keys.should == []
659
+ end
660
+ end
661
+
662
+ describe Sequel::Model, "#==" do
663
+ specify "should compare instances by values" do
664
+ z = Class.new(Sequel::Model)
665
+ z.columns :id, :x
666
+ a = z.load(:id => 1, :x => 3)
667
+ b = z.load(:id => 1, :x => 4)
668
+ c = z.load(:id => 1, :x => 3)
669
+
670
+ a.should_not == b
671
+ a.should == c
672
+ b.should_not == c
673
+ end
674
+
675
+ specify "should be aliased to #eql?" do
676
+ z = Class.new(Sequel::Model)
677
+ z.columns :id, :x
678
+ a = z.load(:id => 1, :x => 3)
679
+ b = z.load(:id => 1, :x => 4)
680
+ c = z.load(:id => 1, :x => 3)
681
+
682
+ a.eql?(b).should == false
683
+ a.eql?(c).should == true
684
+ b.eql?(c).should == false
685
+ end
686
+ end
687
+
688
+ describe Sequel::Model, "#===" do
689
+ specify "should compare instances by class and pk if pk is not nil" do
690
+ z = Class.new(Sequel::Model)
691
+ z.columns :id, :x
692
+ y = Class.new(Sequel::Model)
693
+ y.columns :id, :x
694
+ a = z.load(:id => 1, :x => 3)
695
+ b = z.load(:id => 1, :x => 4)
696
+ c = z.load(:id => 2, :x => 3)
697
+ d = y.load(:id => 1, :x => 3)
698
+
699
+ a.should === b
700
+ a.should_not === c
701
+ a.should_not === d
702
+ end
703
+
704
+ specify "should always be false if the primary key is nil" do
705
+ z = Class.new(Sequel::Model)
706
+ z.columns :id, :x
707
+ y = Class.new(Sequel::Model)
708
+ y.columns :id, :x
709
+ a = z.new(:x => 3)
710
+ b = z.new(:x => 4)
711
+ c = z.new(:x => 3)
712
+ d = y.new(:x => 3)
713
+
714
+ a.should_not === b
715
+ a.should_not === c
716
+ a.should_not === d
717
+ end
718
+ end
719
+
720
+ describe Sequel::Model, "#hash" do
721
+ specify "should be the same only for objects with the same class and pk if the pk is not nil" do
722
+ z = Class.new(Sequel::Model)
723
+ z.columns :id, :x
724
+ y = Class.new(Sequel::Model)
725
+ y.columns :id, :x
726
+ a = z.load(:id => 1, :x => 3)
727
+ b = z.load(:id => 1, :x => 4)
728
+ c = z.load(:id => 2, :x => 3)
729
+ d = y.load(:id => 1, :x => 3)
730
+
731
+ a.hash.should == b.hash
732
+ a.hash.should_not == c.hash
733
+ a.hash.should_not == d.hash
734
+ end
735
+
736
+ specify "should be the same only for objects with the same class and values if the pk is nil" do
737
+ z = Class.new(Sequel::Model)
738
+ z.columns :id, :x
739
+ y = Class.new(Sequel::Model)
740
+ y.columns :id, :x
741
+ a = z.new(:x => 3)
742
+ b = z.new(:x => 4)
743
+ c = z.new(:x => 3)
744
+ d = y.new(:x => 3)
745
+
746
+ a.hash.should_not == b.hash
747
+ a.hash.should == c.hash
748
+ a.hash.should_not == d.hash
749
+ end
750
+ end
751
+
752
+ describe Sequel::Model, "#initialize" do
753
+ setup do
754
+ @c = Class.new(Sequel::Model) do
755
+ columns :id, :x
756
+ end
757
+ @c.strict_param_setting = false
758
+ end
759
+
760
+ specify "should accept values" do
761
+ m = @c.new(:x => 2)
762
+ m.values.should == {:x => 2}
763
+ end
764
+
765
+ specify "should not modify the primary key" do
766
+ m = @c.new(:id => 1, :x => 2)
767
+ m.values.should == {:x => 2}
768
+ end
769
+
770
+ specify "should accept no values" do
771
+ m = @c.new
772
+ m.values.should == {}
773
+ end
774
+
775
+ specify "should accept a block to execute" do
776
+ m = @c.new {|o| o[:id] = 1234}
777
+ m.id.should == 1234
778
+ end
779
+
780
+ specify "should accept virtual attributes" do
781
+ @c.class_def(:blah=) {|x| @blah = x}
782
+ @c.class_def(:blah) {@blah}
783
+
784
+ m = @c.new(:x => 2, :blah => 3)
785
+ m.values.should == {:x => 2}
786
+ m.blah.should == 3
787
+ end
788
+
789
+ specify "should convert string keys into symbol keys" do
790
+ m = @c.new('x' => 2)
791
+ m.values.should == {:x => 2}
792
+ end
793
+ end
794
+
795
+ describe Sequel::Model, ".create" do
796
+
797
+ before(:each) do
798
+ MODEL_DB.reset
799
+ @c = Class.new(Sequel::Model(:items)) do
800
+ unrestrict_primary_key
801
+ columns :x
802
+ end
803
+ end
804
+
805
+ it "should be able to create rows in the associated table" do
806
+ o = @c.create(:x => 1)
807
+ o.class.should == @c
808
+ MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (1)')) LIMIT 1"]
809
+ end
810
+
811
+ it "should be able to create rows without any values specified" do
812
+ o = @c.create
813
+ o.class.should == @c
814
+ MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id IN ('INSERT INTO items DEFAULT VALUES')) LIMIT 1"]
815
+ end
816
+
817
+ it "should accept a block and run it" do
818
+ o1, o2, o3 = nil, nil, nil
819
+ o = @c.create {|o4| o1 = o4; o3 = o4; o2 = :blah; o3.x = 333}
820
+ o.class.should == @c
821
+ o1.should === o
822
+ o3.should === o
823
+ o2.should == :blah
824
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (333)')) LIMIT 1"]
825
+ end
826
+
827
+ it "should create a row for a model with custom primary key" do
828
+ @c.set_primary_key :x
829
+ o = @c.create(:x => 30)
830
+ o.class.should == @c
831
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (30)", "SELECT * FROM items WHERE (x = 30) LIMIT 1"]
832
+ end
833
+ end
834
+
835
+ describe Sequel::Model, "#refresh" do
836
+ setup do
837
+ MODEL_DB.reset
838
+ @c = Class.new(Sequel::Model(:items)) do
839
+ unrestrict_primary_key
840
+ columns :id, :x
841
+ end
842
+ end
843
+
844
+ specify "should reload the instance values from the database" do
845
+ @m = @c.new(:id => 555)
846
+ @m[:x] = 'blah'
847
+ @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
848
+ @m.refresh
849
+ @m[:x].should == 'kaboom'
850
+ end
851
+
852
+ specify "should raise if the instance is not found" do
853
+ @m = @c.new(:id => 555)
854
+ @m.this.should_receive(:first).and_return(nil)
855
+ proc {@m.refresh}.should raise_error(Sequel::Error)
856
+ end
857
+
858
+ specify "should be aliased by #reload" do
859
+ @m = @c.new(:id => 555)
860
+ @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
861
+ @m.reload
862
+ @m[:x].should == 'kaboom'
863
+ end
864
+
865
+ specify "should remove cached associations" do
866
+ @c.many_to_one :node, :class=>@c
867
+ @m = @c.new(:id => 555)
868
+ @m.associations[:node] = 15
869
+ @m.reload
870
+ @m.associations.should == {}
871
+ end
872
+ end
873
+
874
+ describe Sequel::Model, "typecasting" do
875
+ setup do
876
+ MODEL_DB.reset
877
+ @c = Class.new(Sequel::Model(:items)) do
878
+ columns :x
879
+ end
880
+ end
881
+
882
+ teardown do
883
+ Sequel.datetime_class = Time
884
+ end
885
+
886
+ specify "should not convert if typecasting is turned off" do
887
+ @c.typecast_on_assignment = false
888
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
889
+ m = @c.new
890
+ m.x = '1'
891
+ m.x.should == '1'
892
+ end
893
+
894
+ specify "should not convert if serializing the field" do
895
+ @c.serialize :x
896
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
897
+ m = @c.new
898
+ m.x =[1, 2]
899
+ m.x.should == [1, 2]
900
+ end
901
+
902
+ specify "should convert to integer for an integer field" do
903
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
904
+ m = @c.new
905
+ m.x = '1'
906
+ m.x.should == 1
907
+ m.x = 1
908
+ m.x.should == 1
909
+ m.x = 1.3
910
+ m.x.should == 1
911
+ end
912
+
913
+ specify "should typecast '' to nil unless type is string or blob" do
914
+ [:integer, :float, :decimal, :boolean, :date, :time, :datetime].each do |x|
915
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
916
+ m = @c.new
917
+ m.x = ''
918
+ m.x.should == nil
919
+ end
920
+ [:string, :blob].each do |x|
921
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
922
+ m = @c.new
923
+ m.x = ''
924
+ m.x.should == ''
925
+ end
926
+ end
927
+
928
+ specify "should not typecast '' to nil if typecast_empty_string_to_nil is false" do
929
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
930
+ m = @c.new
931
+ m.typecast_empty_string_to_nil = false
932
+ proc{m.x = ''}.should raise_error
933
+ @c.typecast_empty_string_to_nil = false
934
+ proc{@c.new.x = ''}.should raise_error
935
+ end
936
+
937
+ specify "should not typecast nil if NULLs are allowed" do
938
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>true}})
939
+ m = @c.new
940
+ m.x = nil
941
+ m.x.should == nil
942
+ end
943
+
944
+ specify "should raise an error if attempting to typecast nil and NULLs are not allowed" do
945
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
946
+ proc{@c.new.x = nil}.should raise_error(Sequel::Error)
947
+ proc{@c.new.x = ''}.should raise_error(Sequel::Error)
948
+ end
949
+
950
+ specify "should not raise an error if NULLs are not allowed and typecasting is turned off" do
951
+ @c.typecast_on_assignment = false
952
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
953
+ m = @c.new
954
+ m.x = nil
955
+ m.x.should == nil
956
+ end
957
+
958
+ specify "should not raise when typecasting nil to NOT NULL column but raise_on_typecast_failure is off" do
959
+ @c.raise_on_typecast_failure = false
960
+ @c.typecast_on_assignment = true
961
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
962
+ m = @c.new
963
+ m.x = ''
964
+ m.x.should == nil
965
+ m.x = nil
966
+ m.x.should == nil
967
+ end
968
+
969
+ specify "should raise an error if invalid data is used in an integer field" do
970
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
971
+ proc{@c.new.x = 'a'}.should raise_error(Sequel::Error::InvalidValue)
972
+ end
973
+
974
+ specify "should assign value if raise_on_typecast_failure is off and assigning invalid integer" do
975
+ @c.raise_on_typecast_failure = false
976
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
977
+ model = @c.new
978
+ model.x = '1d'
979
+ model.x.should == '1d'
980
+ end
981
+
982
+ specify "should convert to float for a float field" do
983
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
984
+ m = @c.new
985
+ m.x = '1.3'
986
+ m.x.should == 1.3
987
+ m.x = 1
988
+ m.x.should == 1.0
989
+ m.x = 1.3
990
+ m.x.should == 1.3
991
+ end
992
+
993
+ specify "should raise an error if invalid data is used in an float field" do
994
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
995
+ proc{@c.new.x = 'a'}.should raise_error(Sequel::Error::InvalidValue)
996
+ end
997
+
998
+ specify "should assign value if raise_on_typecast_failure is off and assigning invalid float" do
999
+ @c.raise_on_typecast_failure = false
1000
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1001
+ model = @c.new
1002
+ model.x = '1d'
1003
+ model.x.should == '1d'
1004
+ end
1005
+
1006
+ specify "should convert to BigDecimal for a decimal field" do
1007
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1008
+ m = @c.new
1009
+ bd = '1.0'.to_d
1010
+ m.x = '1.0'
1011
+ m.x.should == bd
1012
+ m.x = 1.0
1013
+ m.x.should == bd
1014
+ m.x = 1
1015
+ m.x.should == bd
1016
+ m.x = bd
1017
+ m.x.should == bd
1018
+ end
1019
+
1020
+ specify "should raise an error if invalid data is used in an decimal field" do
1021
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1022
+ proc{@c.new.x = Date.today}.should raise_error(Sequel::Error::InvalidValue)
1023
+ end
1024
+
1025
+ specify "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1026
+ @c.raise_on_typecast_failure = false
1027
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1028
+ model = @c.new
1029
+ time = Time.now
1030
+ model.x = time
1031
+ model.x.should == time
1032
+ end
1033
+
1034
+ specify "should convert to string for a string field" do
1035
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
1036
+ m = @c.new
1037
+ m.x = '1.3'
1038
+ m.x.should == '1.3'
1039
+ m.x = 1
1040
+ m.x.should == '1'
1041
+ m.x = 1.3
1042
+ m.x.should == '1.3'
1043
+ end
1044
+
1045
+ specify "should convert to boolean for a boolean field" do
1046
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:boolean}})
1047
+ m = @c.new
1048
+ m.x = '1.3'
1049
+ m.x.should == true
1050
+ m.x = 1
1051
+ m.x.should == true
1052
+ m.x = 1.3
1053
+ m.x.should == true
1054
+ m.x = 't'
1055
+ m.x.should == true
1056
+ m.x = 'T'
1057
+ m.x.should == true
1058
+ m.x = true
1059
+ m.x.should == true
1060
+ m.x = nil
1061
+ m.x.should == nil
1062
+ m.x = ''
1063
+ m.x.should == nil
1064
+ m.x = []
1065
+ m.x.should == nil
1066
+ m.x = 'f'
1067
+ m.x.should == false
1068
+ m.x = 'F'
1069
+ m.x.should == false
1070
+ m.x = 'false'
1071
+ m.x.should == false
1072
+ m.x = 'FALSE'
1073
+ m.x.should == false
1074
+ m.x = '0'
1075
+ m.x.should == false
1076
+ m.x = 0
1077
+ m.x.should == false
1078
+ m.x = false
1079
+ m.x.should == false
1080
+ end
1081
+
1082
+ specify "should convert to date for a date field" do
1083
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1084
+ m = @c.new
1085
+ y = Date.new(2007,10,21)
1086
+ m.x = '2007-10-21'
1087
+ m.x.should == y
1088
+ m.x = '2007-10-21'.to_date
1089
+ m.x.should == y
1090
+ m.x = '2007-10-21'.to_time
1091
+ m.x.should == y
1092
+ m.x = '2007-10-21'.to_datetime
1093
+ m.x.should == y
1094
+ end
1095
+
1096
+ specify "should raise an error if invalid data is used in a date field" do
1097
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1098
+ proc{@c.new.x = 'a'}.should raise_error(Sequel::Error::InvalidValue)
1099
+ proc{@c.new.x = 100}.should raise_error(Sequel::Error::InvalidValue)
1100
+ end
1101
+
1102
+ specify "should assign value if raise_on_typecast_failure is off and assigning invalid date" do
1103
+ @c.raise_on_typecast_failure = false
1104
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1105
+ model = @c.new
1106
+ model.x = 4
1107
+ model.x.should == 4
1108
+ end
1109
+
1110
+ specify "should convert to time for a time field" do
1111
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1112
+ m = @c.new
1113
+ x = '10:20:30'
1114
+ y = x.to_time
1115
+ m.x = x
1116
+ m.x.should == y
1117
+ m.x = y
1118
+ m.x.should == y
1119
+ end
1120
+
1121
+ specify "should raise an error if invalid data is used in a time field" do
1122
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1123
+ proc{@c.new.x = '0000'}.should raise_error
1124
+ proc{@c.new.x = 'a'}.should_not raise_error # Valid Time
1125
+ proc{@c.new.x = '2008-10-21'.to_date}.should raise_error(Sequel::Error::InvalidValue)
1126
+ proc{@c.new.x = '2008-10-21'.to_datetime}.should raise_error(Sequel::Error::InvalidValue)
1127
+ end
1128
+
1129
+ specify "should assign value if raise_on_typecast_failure is off and assigning invalid time" do
1130
+ @c.raise_on_typecast_failure = false
1131
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1132
+ model = @c.new
1133
+ model.x = '0000'
1134
+ model.x.should == '0000'
1135
+ end
1136
+
1137
+ specify "should convert to the Sequel.datetime_class for a datetime field" do
1138
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1139
+ m = @c.new
1140
+ x = '2007-10-21T10:20:30-07:00'
1141
+ y = x.to_time
1142
+ m.x = x
1143
+ m.x.should == y
1144
+ m.x = x.to_datetime
1145
+ m.x.should == y
1146
+ m.x = x.to_time
1147
+ m.x.should == y
1148
+ m.x = '2007-10-21'.to_date
1149
+ m.x.should == '2007-10-21'.to_time
1150
+ Sequel.datetime_class = DateTime
1151
+ y = x.to_datetime
1152
+ m.x = x
1153
+ m.x.should == y
1154
+ m.x = x.to_datetime
1155
+ m.x.should == y
1156
+ m.x = x.to_time
1157
+ m.x.should == y
1158
+ m.x = '2007-10-21'.to_date
1159
+ m.x.should == '2007-10-21'.to_datetime
1160
+ end
1161
+
1162
+ specify "should raise an error if invalid data is used in a datetime field" do
1163
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1164
+ proc{@c.new.x = '0000'}.should raise_error(Sequel::Error::InvalidValue)
1165
+ proc{@c.new.x = 'a'}.should_not raise_error # Valid Time
1166
+ Sequel.datetime_class = DateTime
1167
+ proc{@c.new.x = '0000'}.should raise_error(Sequel::Error::InvalidValue)
1168
+ proc{@c.new.x = 'a'}.should raise_error(Sequel::Error::InvalidValue)
1169
+ end
1170
+
1171
+ specify "should assign value if raise_on_typecast_failure is off and assigning invalid datetime" do
1172
+ @c.raise_on_typecast_failure = false
1173
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1174
+ model = @c.new
1175
+ model.x = '0000'
1176
+ model.x.should == '0000'
1177
+ Sequel.datetime_class = DateTime
1178
+ model = @c.new
1179
+ model.x = '0000'
1180
+ model.x.should == '0000'
1181
+ model.x = 'a'
1182
+ model.x.should == 'a'
1183
+ end
1184
+ end