sequel 3.21.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.
Files changed (200) hide show
  1. data/CHANGELOG +413 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +23 -16
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +210 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/mass_assignment.rdoc +54 -0
  8. data/doc/migration.rdoc +15 -538
  9. data/doc/model_hooks.rdoc +72 -27
  10. data/doc/opening_databases.rdoc +86 -50
  11. data/doc/prepared_statements.rdoc +40 -13
  12. data/doc/reflection.rdoc +8 -2
  13. data/doc/release_notes/3.22.0.txt +39 -0
  14. data/doc/release_notes/3.23.0.txt +172 -0
  15. data/doc/release_notes/3.24.0.txt +420 -0
  16. data/doc/release_notes/3.25.0.txt +88 -0
  17. data/doc/release_notes/3.26.0.txt +88 -0
  18. data/doc/release_notes/3.27.0.txt +82 -0
  19. data/doc/release_notes/3.28.0.txt +304 -0
  20. data/doc/release_notes/3.29.0.txt +459 -0
  21. data/doc/schema_modification.rdoc +547 -0
  22. data/doc/sharding.rdoc +7 -1
  23. data/doc/testing.rdoc +115 -0
  24. data/doc/transactions.rdoc +137 -0
  25. data/doc/virtual_rows.rdoc +2 -2
  26. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  27. data/lib/sequel/adapters/ado.rb +40 -18
  28. data/lib/sequel/adapters/amalgalite.rb +15 -7
  29. data/lib/sequel/adapters/db2.rb +175 -86
  30. data/lib/sequel/adapters/dbi.rb +15 -15
  31. data/lib/sequel/adapters/do/mysql.rb +0 -5
  32. data/lib/sequel/adapters/do/postgres.rb +0 -5
  33. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  34. data/lib/sequel/adapters/do.rb +17 -36
  35. data/lib/sequel/adapters/firebird.rb +27 -208
  36. data/lib/sequel/adapters/ibmdb.rb +448 -0
  37. data/lib/sequel/adapters/informix.rb +6 -23
  38. data/lib/sequel/adapters/jdbc/as400.rb +5 -31
  39. data/lib/sequel/adapters/jdbc/db2.rb +44 -0
  40. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  41. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  42. data/lib/sequel/adapters/jdbc/h2.rb +26 -17
  43. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  44. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  45. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  46. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  47. data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
  48. data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
  49. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
  50. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  51. data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
  52. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  53. data/lib/sequel/adapters/jdbc.rb +107 -38
  54. data/lib/sequel/adapters/mock.rb +315 -0
  55. data/lib/sequel/adapters/mysql.rb +78 -182
  56. data/lib/sequel/adapters/mysql2.rb +24 -23
  57. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  58. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  59. data/lib/sequel/adapters/odbc.rb +28 -9
  60. data/lib/sequel/adapters/openbase.rb +2 -4
  61. data/lib/sequel/adapters/oracle.rb +349 -51
  62. data/lib/sequel/adapters/postgres.rb +169 -21
  63. data/lib/sequel/adapters/shared/access.rb +21 -6
  64. data/lib/sequel/adapters/shared/db2.rb +288 -0
  65. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  66. data/lib/sequel/adapters/shared/informix.rb +45 -0
  67. data/lib/sequel/adapters/shared/mssql.rb +108 -65
  68. data/lib/sequel/adapters/shared/mysql.rb +56 -13
  69. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  70. data/lib/sequel/adapters/shared/oracle.rb +185 -34
  71. data/lib/sequel/adapters/shared/postgres.rb +107 -58
  72. data/lib/sequel/adapters/shared/progress.rb +0 -6
  73. data/lib/sequel/adapters/shared/sqlite.rb +168 -41
  74. data/lib/sequel/adapters/sqlite.rb +27 -18
  75. data/lib/sequel/adapters/swift/mysql.rb +9 -5
  76. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  77. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  78. data/lib/sequel/adapters/swift.rb +5 -5
  79. data/lib/sequel/adapters/tinytds.rb +152 -17
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
  81. data/lib/sequel/ast_transformer.rb +190 -0
  82. data/lib/sequel/connection_pool/threaded.rb +3 -2
  83. data/lib/sequel/connection_pool.rb +1 -1
  84. data/lib/sequel/core.rb +46 -5
  85. data/lib/sequel/database/connecting.rb +5 -6
  86. data/lib/sequel/database/dataset.rb +4 -4
  87. data/lib/sequel/database/dataset_defaults.rb +59 -1
  88. data/lib/sequel/database/logging.rb +1 -1
  89. data/lib/sequel/database/misc.rb +100 -19
  90. data/lib/sequel/database/query.rb +153 -58
  91. data/lib/sequel/database/schema_generator.rb +8 -5
  92. data/lib/sequel/database/schema_methods.rb +59 -29
  93. data/lib/sequel/dataset/actions.rb +194 -57
  94. data/lib/sequel/dataset/features.rb +81 -8
  95. data/lib/sequel/dataset/graph.rb +8 -7
  96. data/lib/sequel/dataset/misc.rb +50 -23
  97. data/lib/sequel/dataset/mutation.rb +5 -6
  98. data/lib/sequel/dataset/prepared_statements.rb +32 -15
  99. data/lib/sequel/dataset/query.rb +223 -42
  100. data/lib/sequel/dataset/sql.rb +58 -61
  101. data/lib/sequel/dataset.rb +8 -0
  102. data/lib/sequel/exceptions.rb +4 -0
  103. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  104. data/lib/sequel/extensions/migration.rb +6 -4
  105. data/lib/sequel/extensions/named_timezones.rb +5 -0
  106. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  107. data/lib/sequel/extensions/to_dot.rb +95 -83
  108. data/lib/sequel/model/associations.rb +997 -331
  109. data/lib/sequel/model/base.rb +386 -129
  110. data/lib/sequel/model/errors.rb +1 -1
  111. data/lib/sequel/model/exceptions.rb +5 -1
  112. data/lib/sequel/model.rb +15 -8
  113. data/lib/sequel/plugins/association_pks.rb +22 -4
  114. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  115. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  116. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  117. data/lib/sequel/plugins/force_encoding.rb +6 -6
  118. data/lib/sequel/plugins/identity_map.rb +114 -7
  119. data/lib/sequel/plugins/many_through_many.rb +65 -7
  120. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  121. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  122. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  123. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  124. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  125. data/lib/sequel/plugins/serialization.rb +6 -1
  126. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  127. data/lib/sequel/plugins/sharding.rb +12 -25
  128. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  129. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  130. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  131. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  132. data/lib/sequel/sql.rb +107 -51
  133. data/lib/sequel/timezones.rb +44 -35
  134. data/lib/sequel/version.rb +1 -1
  135. data/spec/adapters/db2_spec.rb +146 -0
  136. data/spec/adapters/mssql_spec.rb +65 -29
  137. data/spec/adapters/mysql_spec.rb +122 -123
  138. data/spec/adapters/oracle_spec.rb +48 -76
  139. data/spec/adapters/postgres_spec.rb +213 -61
  140. data/spec/adapters/spec_helper.rb +6 -5
  141. data/spec/adapters/sqlite_spec.rb +35 -21
  142. data/spec/core/connection_pool_spec.rb +71 -92
  143. data/spec/core/core_sql_spec.rb +20 -31
  144. data/spec/core/database_spec.rb +729 -508
  145. data/spec/core/dataset_spec.rb +980 -1044
  146. data/spec/core/expression_filters_spec.rb +159 -42
  147. data/spec/core/mock_adapter_spec.rb +378 -0
  148. data/spec/core/object_graph_spec.rb +48 -114
  149. data/spec/core/schema_generator_spec.rb +3 -3
  150. data/spec/core/schema_spec.rb +298 -38
  151. data/spec/core/spec_helper.rb +6 -48
  152. data/spec/extensions/association_pks_spec.rb +38 -0
  153. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  154. data/spec/extensions/columns_introspection_spec.rb +91 -0
  155. data/spec/extensions/dataset_associations_spec.rb +199 -0
  156. data/spec/extensions/defaults_setter_spec.rb +64 -0
  157. data/spec/extensions/identity_map_spec.rb +162 -0
  158. data/spec/extensions/instance_hooks_spec.rb +71 -0
  159. data/spec/extensions/many_through_many_spec.rb +195 -20
  160. data/spec/extensions/migration_spec.rb +17 -17
  161. data/spec/extensions/named_timezones_spec.rb +22 -2
  162. data/spec/extensions/nested_attributes_spec.rb +4 -0
  163. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  164. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  165. data/spec/extensions/prepared_statements_spec.rb +72 -0
  166. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  167. data/spec/extensions/schema_dumper_spec.rb +2 -2
  168. data/spec/extensions/schema_spec.rb +13 -21
  169. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  170. data/spec/extensions/serialization_spec.rb +5 -8
  171. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  172. data/spec/extensions/spec_helper.rb +7 -1
  173. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  174. data/spec/extensions/to_dot_spec.rb +3 -5
  175. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  176. data/spec/extensions/xml_serializer_spec.rb +16 -4
  177. data/spec/integration/associations_test.rb +522 -21
  178. data/spec/integration/database_test.rb +4 -2
  179. data/spec/integration/dataset_test.rb +375 -62
  180. data/spec/integration/eager_loader_test.rb +19 -21
  181. data/spec/integration/model_test.rb +80 -1
  182. data/spec/integration/plugin_test.rb +304 -116
  183. data/spec/integration/prepared_statement_test.rb +200 -120
  184. data/spec/integration/schema_test.rb +161 -30
  185. data/spec/integration/spec_helper.rb +39 -30
  186. data/spec/integration/timezone_test.rb +38 -12
  187. data/spec/integration/transaction_test.rb +172 -5
  188. data/spec/integration/type_test.rb +17 -3
  189. data/spec/model/association_reflection_spec.rb +174 -7
  190. data/spec/model/associations_spec.rb +849 -661
  191. data/spec/model/base_spec.rb +255 -95
  192. data/spec/model/dataset_methods_spec.rb +7 -27
  193. data/spec/model/eager_loading_spec.rb +640 -676
  194. data/spec/model/hooks_spec.rb +309 -67
  195. data/spec/model/model_spec.rb +207 -167
  196. data/spec/model/plugins_spec.rb +24 -13
  197. data/spec/model/record_spec.rb +321 -218
  198. data/spec/model/spec_helper.rb +13 -71
  199. data/spec/model/validations_spec.rb +11 -0
  200. metadata +95 -38
@@ -1,36 +1,23 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Model#save server use" do
4
-
5
- before(:each) do
6
- @c = Class.new(Sequel::Model(:items)) do
7
- columns :id, :x, :y
8
- end
9
- @c.db = MockDatabase.new
10
- db2 = @db2 = MockDatabase.new
11
- @c.class_eval do
12
- define_method(:after_save) do
13
- model.db = db2
14
- ds = model.dataset
15
- def ds.fetch_rows(sql)
16
- yield @db.execute(sql, @opts[:server])
17
- end
18
- @this = nil
19
- end
20
- end
4
+ before do
5
+ @db = Sequel.mock(:autoid=>proc{|sql| 10}, :fetch=>{:x=>1, :id=>10}, :servers=>{:blah=>{}, :read_only=>{}})
6
+ @c = Class.new(Sequel::Model(@db[:items]))
7
+ @c.columns :id, :x, :y
8
+ @c.dataset.columns(:id, :x, :y)
9
+ @db.sqls
21
10
  end
22
11
 
23
12
  it "should use the :default server if the model doesn't have one already specified" do
24
- @c.db.should_receive(:execute).with("INSERT INTO items (x) VALUES (1)").and_return(10)
25
- @db2.should_receive(:execute).with('SELECT * FROM items WHERE (id = 10) LIMIT 1', :default).and_return(:x=>1, :id=>10)
26
- @c.new(:x=>1).save
13
+ @c.new(:x=>1).save.should == @c.load(:x=>1, :id=>10)
14
+ @db.sqls.should == ["INSERT INTO items (x) VALUES (1)", 'SELECT * FROM items WHERE (id = 10) LIMIT 1']
27
15
  end
28
16
 
29
17
  it "should use the model's server if the model has one already specified" do
30
18
  @c.dataset = @c.dataset.server(:blah)
31
- @c.db.should_receive(:execute).with("INSERT INTO items (x) VALUES (1)").and_return(10)
32
- @db2.should_receive(:execute).with('SELECT * FROM items WHERE (id = 10) LIMIT 1', :blah).and_return(:x=>1, :id=>10)
33
- @c.new(:x=>1).save
19
+ @c.new(:x=>1).save.should == @c.load(:x=>1, :id=>10)
20
+ @db.sqls.should == ["INSERT INTO items (x) VALUES (1) -- blah", 'SELECT * FROM items WHERE (id = 10) LIMIT 1 -- blah']
34
21
  end
35
22
  end
36
23
 
@@ -39,32 +26,37 @@ describe "Model#save" do
39
26
  @c = Class.new(Sequel::Model(:items)) do
40
27
  columns :id, :x, :y
41
28
  end
42
- @c.dataset.meta_def(:insert){|h| super(h); 1}
29
+ @c.dataset.autoid = 13
43
30
  MODEL_DB.reset
44
31
  end
45
32
 
46
33
  it "should insert a record for a new model instance" do
47
34
  o = @c.new(:x => 1)
48
35
  o.save
49
- MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)",
50
- "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
36
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 13) LIMIT 1"]
51
37
  end
52
38
 
53
39
  it "should use dataset's insert_select method if present" do
54
40
  ds = @c.dataset = @c.dataset.clone
41
+ ds._fetch = {:y=>2}
42
+ def ds.supports_insert_select?() true end
55
43
  def ds.insert_select(hash)
56
- execute("INSERT INTO items (y) VALUES (2)")
57
- {:y=>2}
44
+ execute("INSERT INTO items (y) VALUES (2) RETURNING *"){|r| return r}
58
45
  end
59
46
  o = @c.new(:x => 1)
60
47
  o.save
61
48
 
62
49
  o.values.should == {:y=>2}
63
- MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2)"]
50
+ MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2) RETURNING *"]
51
+ end
52
+
53
+ it "should not use dataset's insert_select method if specific columns are selected" do
54
+ ds = @c.dataset = @c.dataset.select(:y)
55
+ ds.should_not_receive(:insert_select)
56
+ @c.new(:x => 1).save
64
57
  end
65
58
 
66
59
  it "should use value returned by insert as the primary key and refresh the object" do
67
- @c.dataset.meta_def(:insert){|h| super(h); 13}
68
60
  o = @c.new(:x => 11)
69
61
  o.save
70
62
  MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)",
@@ -72,14 +64,12 @@ describe "Model#save" do
72
64
  end
73
65
 
74
66
  it "should allow you to skip refreshing by overridding _save_refresh" do
75
- @c.dataset.meta_def(:insert){|h| super(h); 13}
76
67
  @c.send(:define_method, :_save_refresh){}
77
68
  @c.create(:x => 11)
78
69
  MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
79
70
  end
80
71
 
81
72
  it "should work correctly for inserting a record without a primary key" do
82
- @c.dataset.meta_def(:insert){|h| super(h); 13}
83
73
  @c.no_primary_key
84
74
  o = @c.new(:x => 11)
85
75
  o.save
@@ -87,15 +77,15 @@ describe "Model#save" do
87
77
  end
88
78
 
89
79
  it "should set the autoincrementing_primary_key value to the value returned by insert" do
90
- @c.dataset.meta_def(:insert){|h| super(h); 13}
91
80
  @c.unrestrict_primary_key
92
81
  @c.set_primary_key [:x, :y]
93
82
  o = @c.new(:x => 11)
94
83
  o.meta_def(:autoincrementing_primary_key){:y}
95
84
  o.save
96
- MODEL_DB.sqls.length.should == 2
97
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (11)"
98
- MODEL_DB.sqls.last.should =~ %r{SELECT \* FROM items WHERE \(\([xy] = 1[13]\) AND \([xy] = 1[13]\)\) LIMIT 1}
85
+ sqls = MODEL_DB.sqls
86
+ sqls.length.should == 2
87
+ sqls.first.should == "INSERT INTO items (x) VALUES (11)"
88
+ sqls.last.should =~ %r{SELECT \* FROM items WHERE \(\([xy] = 1[13]\) AND \([xy] = 1[13]\)\) LIMIT 1}
99
89
  end
100
90
 
101
91
  it "should update a record for an existing model instance" do
@@ -106,17 +96,18 @@ describe "Model#save" do
106
96
 
107
97
  it "should raise a NoExistingObject exception if the dataset update call doesn't return 1, unless require_modification is false" do
108
98
  o = @c.load(:id => 3, :x => 1)
109
- o.this.meta_def(:update){|*a| 0}
99
+ t = o.this
100
+ t.numrows = 0
110
101
  proc{o.save}.should raise_error(Sequel::NoExistingObject)
111
- o.this.meta_def(:update){|*a| 2}
102
+ t.numrows = 2
112
103
  proc{o.save}.should raise_error(Sequel::NoExistingObject)
113
- o.this.meta_def(:update){|*a| 1}
104
+ t.numrows = 1
114
105
  proc{o.save}.should_not raise_error
115
106
 
116
107
  o.require_modification = false
117
- o.this.meta_def(:update){|*a| 0}
108
+ t.numrows = 0
118
109
  proc{o.save}.should_not raise_error
119
- o.this.meta_def(:update){|*a| 2}
110
+ t.numrows = 2
120
111
  proc{o.save}.should_not raise_error
121
112
  end
122
113
 
@@ -185,22 +176,18 @@ describe "Model#save" do
185
176
  @c.use_transactions = true
186
177
  @c.load(:id => 3, :x => 1, :y => nil).save(:y)
187
178
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
188
- MODEL_DB.reset
189
179
  @c.use_transactions = false
190
180
  @c.load(:id => 3, :x => 1, :y => nil).save(:y)
191
181
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
192
- MODEL_DB.reset
193
182
  end
194
183
 
195
184
  it "should inherit Model's use_transactions setting" do
196
185
  @c.use_transactions = true
197
186
  Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
198
187
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
199
- MODEL_DB.reset
200
188
  @c.use_transactions = false
201
189
  Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
202
190
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
203
- MODEL_DB.reset
204
191
  end
205
192
 
206
193
  it "should use object's use_transactions setting" do
@@ -209,13 +196,11 @@ describe "Model#save" do
209
196
  @c.use_transactions = true
210
197
  o.save(:y)
211
198
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
212
- MODEL_DB.reset
213
199
  o = @c.load(:id => 3, :x => 1, :y => nil)
214
200
  o.use_transactions = true
215
201
  @c.use_transactions = false
216
202
  o.save(:y)
217
203
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
218
- MODEL_DB.reset
219
204
  end
220
205
 
221
206
  it "should use :transaction option if given" do
@@ -223,12 +208,10 @@ describe "Model#save" do
223
208
  o.use_transactions = true
224
209
  o.save(:y, :transaction=>false)
225
210
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
226
- MODEL_DB.reset
227
211
  o = @c.load(:id => 3, :x => 1, :y => nil)
228
212
  o.use_transactions = false
229
213
  o.save(:y, :transaction=>true)
230
214
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
231
- MODEL_DB.reset
232
215
  end
233
216
 
234
217
  it "should rollback if before_save returns false and raise_on_save_failure = true" do
@@ -240,7 +223,6 @@ describe "Model#save" do
240
223
  end
241
224
  proc { o.save(:y) }.should raise_error(Sequel::BeforeHookFailed)
242
225
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
243
- MODEL_DB.reset
244
226
  end
245
227
 
246
228
  it "should rollback if before_save returns false and :raise_on_failure option is true" do
@@ -252,7 +234,6 @@ describe "Model#save" do
252
234
  end
253
235
  proc { o.save(:y, :raise_on_failure => true) }.should raise_error(Sequel::BeforeHookFailed)
254
236
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
255
- MODEL_DB.reset
256
237
  end
257
238
 
258
239
  it "should not rollback outer transactions if before_save returns false and raise_on_save_failure = false" do
@@ -267,7 +248,6 @@ describe "Model#save" do
267
248
  MODEL_DB.run "BLAH"
268
249
  end
269
250
  MODEL_DB.sqls.should == ["BEGIN", "BLAH", "COMMIT"]
270
- MODEL_DB.reset
271
251
  end
272
252
 
273
253
  it "should rollback if before_save returns false and raise_on_save_failure = false" do
@@ -279,7 +259,6 @@ describe "Model#save" do
279
259
  end
280
260
  o.save(:y).should == nil
281
261
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
282
- MODEL_DB.reset
283
262
  end
284
263
 
285
264
  it "should not rollback if before_save throws Rollback and use_transactions = false" do
@@ -290,7 +269,6 @@ describe "Model#save" do
290
269
  end
291
270
  proc { o.save(:y) }.should raise_error(Sequel::Rollback)
292
271
  MODEL_DB.sqls.should == []
293
- MODEL_DB.reset
294
272
  end
295
273
  end
296
274
 
@@ -299,7 +277,6 @@ describe "Model#marshallable" do
299
277
  class ::Album < Sequel::Model
300
278
  columns :id, :x
301
279
  end
302
- Album.dataset.meta_def(:insert){|h| super(h); 1}
303
280
  end
304
281
  after do
305
282
  Object.send(:remove_const, :Album)
@@ -381,7 +358,6 @@ describe "Model#modified[!?]" do
381
358
  end
382
359
 
383
360
  describe "Model#save_changes" do
384
-
385
361
  before do
386
362
  @c = Class.new(Sequel::Model(:items)) do
387
363
  unrestrict_primary_key
@@ -426,15 +402,14 @@ describe "Model#save_changes" do
426
402
  MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
427
403
  o.save_changes
428
404
  o.save_changes
429
- MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
430
- MODEL_DB.reset
405
+ MODEL_DB.sqls.should == []
431
406
 
432
407
  o.y = 4
433
408
  o.save_changes
434
409
  MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
435
410
  o.save_changes
436
411
  o.save_changes
437
- MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
412
+ MODEL_DB.sqls.should == []
438
413
  end
439
414
 
440
415
  it "should not consider columns changed if the values did not change" do
@@ -446,7 +421,6 @@ describe "Model#save_changes" do
446
421
  o.x = 3
447
422
  o.save_changes
448
423
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
449
- MODEL_DB.reset
450
424
 
451
425
  o[:y] = nil
452
426
  o.save_changes
@@ -472,13 +446,11 @@ describe "Model#save_changes" do
472
446
  o.x = 2
473
447
  o.save_changes
474
448
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
475
- MODEL_DB.reset
476
449
  o.save_changes
477
450
  MODEL_DB.sqls.should == []
478
451
  o.x = 4
479
452
  o.save_changes
480
453
  MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
481
- MODEL_DB.reset
482
454
  end
483
455
 
484
456
  it "should update columns changed in a before_save hook" do
@@ -489,25 +461,21 @@ describe "Model#save_changes" do
489
461
  o.x = 2
490
462
  o.save_changes
491
463
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
492
- MODEL_DB.reset
493
464
  o.save_changes
494
465
  MODEL_DB.sqls.should == []
495
466
  o.x = 4
496
467
  o.save_changes
497
468
  MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
498
- MODEL_DB.reset
499
469
  end
500
470
  end
501
471
 
502
472
  describe "Model#new?" do
503
-
504
- before(:each) do
505
- MODEL_DB.reset
506
-
473
+ before do
507
474
  @c = Class.new(Sequel::Model(:items)) do
508
475
  unrestrict_primary_key
509
476
  columns :x
510
477
  end
478
+ MODEL_DB.reset
511
479
  end
512
480
 
513
481
  it "should be true for a new instance" do
@@ -523,74 +491,65 @@ describe "Model#new?" do
523
491
  end
524
492
 
525
493
  describe Sequel::Model, "w/ primary key" do
526
-
527
494
  it "should default to ':id'" do
528
495
  model_a = Class.new Sequel::Model
529
- model_a.primary_key.should be_equal(:id)
496
+ model_a.primary_key.should == :id
530
497
  end
531
498
 
532
499
  it "should be changed through 'set_primary_key'" do
533
- model_a = Class.new(Sequel::Model) { set_primary_key :a }
534
- model_a.primary_key.should be_equal(:a)
500
+ model_a = Class.new(Sequel::Model){ set_primary_key :a }
501
+ model_a.primary_key.should == :a
535
502
  end
536
503
 
537
504
  it "should support multi argument composite keys" do
538
- model_a = Class.new(Sequel::Model) { set_primary_key :a, :b }
539
- model_a.primary_key.should be_eql([:a, :b])
505
+ model_a = Class.new(Sequel::Model){ set_primary_key :a, :b }
506
+ model_a.primary_key.should == [:a, :b]
540
507
  end
541
508
 
542
509
  it "should accept single argument composite keys" do
543
- model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
544
- model_a.primary_key.should be_eql([:a, :b])
510
+ model_a = Class.new(Sequel::Model){ set_primary_key [:a, :b] }
511
+ model_a.primary_key.should == [:a, :b]
545
512
  end
546
-
547
513
  end
548
514
 
549
515
  describe Sequel::Model, "w/o primary key" do
550
516
  it "should return nil for primary key" do
551
- Class.new(Sequel::Model) { no_primary_key }.primary_key.should be_nil
517
+ Class.new(Sequel::Model){no_primary_key}.primary_key.should be_nil
552
518
  end
553
519
 
554
520
  it "should raise a Sequel::Error on 'this'" do
555
- instance = Class.new(Sequel::Model) { no_primary_key }.new
556
- proc { instance.this }.should raise_error(Sequel::Error)
521
+ instance = Class.new(Sequel::Model){no_primary_key}.new
522
+ proc{instance.this}.should raise_error(Sequel::Error)
557
523
  end
558
524
  end
559
525
 
560
526
  describe Sequel::Model, "with this" do
561
-
562
- before { @example = Class.new Sequel::Model(:examples); @example.columns :id, :a, :x, :y }
527
+ before do
528
+ @example = Class.new(Sequel::Model(:examples))
529
+ @example.columns :id, :a, :x, :y
530
+ end
563
531
 
564
532
  it "should return a dataset identifying the record" do
565
- instance = @example.load :id => 3
566
- instance.this.sql.should be_eql("SELECT * FROM examples WHERE (id = 3) LIMIT 1")
533
+ instance = @example.load(:id => 3)
534
+ instance.this.sql.should == "SELECT * FROM examples WHERE (id = 3) LIMIT 1"
567
535
  end
568
536
 
569
537
  it "should support arbitary primary keys" do
570
538
  @example.set_primary_key :a
571
539
 
572
- instance = @example.load :a => 3
573
- instance.this.sql.should be_eql("SELECT * FROM examples WHERE (a = 3) LIMIT 1")
540
+ instance = @example.load(:a => 3)
541
+ instance.this.sql.should == "SELECT * FROM examples WHERE (a = 3) LIMIT 1"
574
542
  end
575
543
 
576
544
  it "should support composite primary keys" do
577
545
  @example.set_primary_key :x, :y
578
- instance = @example.load :x => 4, :y => 5
579
-
580
- parts = [
581
- 'SELECT * FROM examples WHERE %s LIMIT 1',
582
- '((x = 4) AND (y = 5))',
583
- '((y = 5) AND (x = 4))'
584
- ].map { |expr| Regexp.escape expr }
585
- regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
586
-
587
- instance.this.sql.should match(regexp)
546
+ instance = @example.load(:x => 4, :y => 5)
547
+ instance.this.sql.should =~ /SELECT \* FROM examples WHERE \(\([xy] = [45]\) AND \([xy] = [45]\)\) LIMIT 1/
588
548
  end
589
-
590
549
  end
591
550
 
592
551
  describe "Model#pk" do
593
- before(:each) do
552
+ before do
594
553
  @m = Class.new(Sequel::Model)
595
554
  @m.columns :id, :x, :y
596
555
  end
@@ -623,8 +582,42 @@ describe "Model#pk" do
623
582
  end
624
583
  end
625
584
 
585
+ describe "Model#pk_or_nil" do
586
+ before do
587
+ @m = Class.new(Sequel::Model)
588
+ @m.columns :id, :x, :y
589
+ end
590
+
591
+ it "should be default return the value of the :id column" do
592
+ m = @m.load(:id => 111, :x => 2, :y => 3)
593
+ m.pk_or_nil.should == 111
594
+ end
595
+
596
+ it "should be return the primary key value for custom primary key" do
597
+ @m.set_primary_key :x
598
+ m = @m.load(:id => 111, :x => 2, :y => 3)
599
+ m.pk_or_nil.should == 2
600
+ end
601
+
602
+ it "should be return the primary key value for composite primary key" do
603
+ @m.set_primary_key [:y, :x]
604
+ m = @m.load(:id => 111, :x => 2, :y => 3)
605
+ m.pk_or_nil.should == [3, 2]
606
+ end
607
+
608
+ it "should raise if no primary key" do
609
+ @m.set_primary_key nil
610
+ m = @m.new(:id => 111, :x => 2, :y => 3)
611
+ m.pk_or_nil.should be_nil
612
+
613
+ @m.no_primary_key
614
+ m = @m.new(:id => 111, :x => 2, :y => 3)
615
+ m.pk_or_nil.should be_nil
616
+ end
617
+ end
618
+
626
619
  describe "Model#pk_hash" do
627
- before(:each) do
620
+ before do
628
621
  @m = Class.new(Sequel::Model)
629
622
  @m.columns :id, :x, :y
630
623
  end
@@ -659,16 +652,14 @@ end
659
652
 
660
653
  describe Sequel::Model, "#set" do
661
654
  before do
662
- MODEL_DB.reset
663
-
664
655
  @c = Class.new(Sequel::Model(:items)) do
665
656
  set_primary_key :id
666
657
  columns :x, :y, :id
667
658
  end
668
659
  @c.strict_param_setting = false
669
- @c.instance_variable_set(:@columns, true)
670
660
  @o1 = @c.new
671
661
  @o2 = @c.load(:id => 5)
662
+ MODEL_DB.reset
672
663
  end
673
664
 
674
665
  it "should filter the given params using the model columns" do
@@ -716,6 +707,29 @@ describe Sequel::Model, "#set" do
716
707
  MODEL_DB.sqls.should == []
717
708
  end
718
709
 
710
+ it "should raise error if strict_param_setting is true and method does not exist" do
711
+ @o1.strict_param_setting = true
712
+ proc{@o1.set('foo' => 1)}.should raise_error(Sequel::Error)
713
+ end
714
+
715
+ it "should raise error if strict_param_setting is true and column is a primary key" do
716
+ @o1.strict_param_setting = true
717
+ proc{@o1.set('id' => 1)}.should raise_error(Sequel::Error)
718
+ end
719
+
720
+ it "should raise error if strict_param_setting is true and column is restricted" do
721
+ @o1.strict_param_setting = true
722
+ @c.set_restricted_columns :x
723
+ proc{@o1.set('x' => 1)}.should raise_error(Sequel::Error)
724
+ end
725
+
726
+ it "should not create a symbol if strict_param_setting is true and string is given" do
727
+ @o1.strict_param_setting = true
728
+ l = Symbol.all_symbols.length
729
+ proc{@o1.set('sadojafdso' => 1)}.should raise_error(Sequel::Error)
730
+ Symbol.all_symbols.length.should == l
731
+ end
732
+
719
733
  it "#set should correctly handle cases where an instance method is added to the class" do
720
734
  @o1.set(:x => 1)
721
735
  @o1.values.should == {:x => 1}
@@ -739,51 +753,74 @@ describe Sequel::Model, "#set" do
739
753
  @o1.set(:x => 2, :z => 3)
740
754
  @o1.values.should == {:x => 2, :z=>3}
741
755
  end
756
+
757
+ it "#set should correctly handle cases where a module with a setter method is included in the class" do
758
+ @o1.set(:x => 1)
759
+ @o1.values.should == {:x => 1}
760
+
761
+ @c.send(:include, Module.new do
762
+ def z=(v)
763
+ self[:z] = v
764
+ end
765
+ end)
766
+ @o1.set(:x => 2, :z => 3)
767
+ @o1.values.should == {:x => 2, :z=>3}
768
+ end
769
+
770
+ it "#set should correctly handle cases where the object extends a module with a setter method " do
771
+ @o1.set(:x => 1)
772
+ @o1.values.should == {:x => 1}
773
+
774
+ @o1.extend(Module.new do
775
+ def z=(v)
776
+ self[:z] = v
777
+ end
778
+ end)
779
+ @o1.set(:x => 2, :z => 3)
780
+ @o1.values.should == {:x => 2, :z=>3}
781
+ end
742
782
  end
743
783
 
744
784
  describe Sequel::Model, "#update" do
745
785
  before do
746
- MODEL_DB.reset
747
-
748
786
  @c = Class.new(Sequel::Model(:items)) do
749
787
  set_primary_key :id
750
788
  columns :x, :y, :id
751
789
  end
752
790
  @c.strict_param_setting = false
753
- @c.instance_variable_set(:@columns, true)
754
791
  @o1 = @c.new
755
792
  @o2 = @c.load(:id => 5)
793
+ MODEL_DB.reset
756
794
  end
757
795
 
758
796
  it "should filter the given params using the model columns" do
759
797
  @o1.update(:x => 1, :z => 2)
760
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
798
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
761
799
 
762
800
  MODEL_DB.reset
763
801
  @o2.update(:y => 1, :abc => 2)
764
- MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
802
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
765
803
  end
766
804
 
767
805
  it "should support virtual attributes" do
768
806
  @c.send(:define_method, :blah=){|v| self.x = v}
769
807
  @o1.update(:blah => 333)
770
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
808
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
771
809
  end
772
810
 
773
811
  it "should not modify the primary key" do
774
812
  @o1.update(:x => 1, :id => 2)
775
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
813
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
776
814
  MODEL_DB.reset
777
815
  @o2.update('y'=> 1, 'id'=> 2)
778
816
  @o2.values.should == {:y => 1, :id=> 5}
779
- MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
817
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
780
818
  end
781
819
  end
782
820
 
783
821
  describe Sequel::Model, "#set_fields" do
784
822
  before do
785
- @c = Class.new(Sequel::Model(:items))
786
- @c.class_eval do
823
+ @c = Class.new(Sequel::Model(:items)) do
787
824
  set_primary_key :id
788
825
  columns :x, :y, :z, :id
789
826
  end
@@ -803,11 +840,9 @@ end
803
840
 
804
841
  describe Sequel::Model, "#update_fields" do
805
842
  before do
806
- @c = Class.new(Sequel::Model(:items))
807
- @c.class_eval do
843
+ @c = Class.new(Sequel::Model(:items)) do
808
844
  set_primary_key :id
809
845
  columns :x, :y, :z, :id
810
- def _refresh(ds); end
811
846
  end
812
847
  @c.strict_param_setting = true
813
848
  @o1 = @c.load(:id=>1)
@@ -817,21 +852,18 @@ describe Sequel::Model, "#update_fields" do
817
852
  it "should set only the given fields, and then save the changes to the record" do
818
853
  @o1.update_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
819
854
  @o1.values.should == {:x => 1, :y => 2, :id=>1}
820
- MODEL_DB.sqls.first.should =~ /UPDATE items SET [xy] = [12], [xy] = [12] WHERE \(id = 1\)/
821
- MODEL_DB.sqls.length.should == 1
822
- MODEL_DB.reset
855
+ sqls = MODEL_DB.sqls
856
+ sqls.pop.should =~ /UPDATE items SET [xy] = [12], [xy] = [12] WHERE \(id = 1\)/
857
+ sqls.should == []
823
858
 
824
859
  @o1.update_fields({:x => 1, :y => 5, :z=>6, :id=>7}, [:x, :y])
825
860
  @o1.values.should == {:x => 1, :y => 5, :id=>1}
826
861
  MODEL_DB.sqls.should == ["UPDATE items SET y = 5 WHERE (id = 1)"]
827
- MODEL_DB.reset
828
862
  end
829
863
  end
830
864
 
831
865
  describe Sequel::Model, "#(set|update)_(all|except|only)" do
832
866
  before do
833
- MODEL_DB.reset
834
-
835
867
  @c = Class.new(Sequel::Model(:items)) do
836
868
  set_primary_key :id
837
869
  columns :x, :y, :z, :id
@@ -839,8 +871,8 @@ describe Sequel::Model, "#(set|update)_(all|except|only)" do
839
871
  set_restricted_columns :y
840
872
  end
841
873
  @c.strict_param_setting = false
842
- @c.instance_variable_set(:@columns, true)
843
874
  @o1 = @c.new
875
+ MODEL_DB.reset
844
876
  end
845
877
 
846
878
  it "should raise errors if not all hash fields can be set and strict_param_setting is true" do
@@ -884,40 +916,34 @@ describe Sequel::Model, "#(set|update)_(all|except|only)" do
884
916
 
885
917
  it "#update_all should update all attributes" do
886
918
  @c.new.update_all(:x => 1, :id=>4)
887
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
888
- MODEL_DB.reset
919
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
889
920
  @c.new.update_all(:y => 1, :id=>4)
890
- MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
891
- MODEL_DB.reset
921
+ MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
892
922
  @c.new.update_all(:z => 1, :id=>4)
893
- MODEL_DB.sqls.first.should == "INSERT INTO items (z) VALUES (1)"
923
+ MODEL_DB.sqls.should == ["INSERT INTO items (z) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
894
924
  end
895
925
 
896
926
  it "#update_only should only update given attributes" do
897
927
  @o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
898
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
899
- MODEL_DB.reset
928
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
900
929
  @c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
901
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
930
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
902
931
  end
903
932
 
904
933
  it "#update_except should not update given attributes" do
905
934
  @o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
906
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
907
- MODEL_DB.reset
935
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
908
936
  @c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
909
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
937
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
910
938
  end
911
939
  end
912
940
 
913
941
  describe Sequel::Model, "#destroy" do
914
942
  before do
915
- MODEL_DB.reset
916
943
  @model = Class.new(Sequel::Model(:items))
917
944
  @model.columns :id
918
- @model.dataset.meta_def(:delete){MODEL_DB.execute delete_sql;1}
919
-
920
945
  @instance = @model.load(:id => 1234)
946
+ MODEL_DB.reset
921
947
  end
922
948
 
923
949
  it "should return self" do
@@ -942,49 +968,40 @@ describe Sequel::Model, "#destroy" do
942
968
 
943
969
  it "should run within a transaction if use_transactions is true" do
944
970
  @instance.use_transactions = true
945
- @model.db.should_receive(:transaction)
946
971
  @instance.destroy
972
+ MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE (id = 1234)", "COMMIT"]
947
973
  end
948
974
 
949
975
  it "should not run within a transaction if use_transactions is false" do
950
976
  @instance.use_transactions = false
951
- @model.db.should_not_receive(:transaction)
952
977
  @instance.destroy
978
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE (id = 1234)"]
953
979
  end
954
980
 
955
981
  it "should run within a transaction if :transaction option is true" do
956
982
  @instance.use_transactions = false
957
- @model.db.should_receive(:transaction)
958
983
  @instance.destroy(:transaction => true)
984
+ MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE (id = 1234)", "COMMIT"]
959
985
  end
960
986
 
961
987
  it "should not run within a transaction if :transaction option is false" do
962
988
  @instance.use_transactions = true
963
- @model.db.should_not_receive(:transaction)
964
989
  @instance.destroy(:transaction => false)
990
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE (id = 1234)"]
965
991
  end
966
992
 
967
993
  it "should run before_destroy and after_destroy hooks" do
968
994
  @model.send(:define_method, :before_destroy){MODEL_DB.execute('before blah')}
969
995
  @model.send(:define_method, :after_destroy){MODEL_DB.execute('after blah')}
970
996
  @instance.destroy
971
-
972
- MODEL_DB.sqls.should == [
973
- "before blah",
974
- "DELETE FROM items WHERE (id = 1234)",
975
- "after blah"
976
- ]
997
+ MODEL_DB.sqls.should == ["before blah", "DELETE FROM items WHERE (id = 1234)", "after blah"]
977
998
  end
978
999
  end
979
1000
 
980
1001
  describe Sequel::Model, "#exists?" do
981
- before(:each) do
1002
+ before do
982
1003
  @model = Class.new(Sequel::Model(:items))
983
- @ds = @model.dataset
984
- def @ds.fetch_rows(sql)
985
- db.execute(sql)
986
- yield(:x=>1) if sql =~ /id = 1/
987
- end
1004
+ @model.dataset._fetch = proc{|sql| {:x=>1} if sql =~ /id = 1/}
988
1005
  MODEL_DB.reset
989
1006
  end
990
1007
 
@@ -997,6 +1014,11 @@ describe Sequel::Model, "#exists?" do
997
1014
  @model.load(:id=>2).exists?.should be_false
998
1015
  MODEL_DB.sqls.should == ['SELECT 1 FROM items WHERE (id = 2) LIMIT 1']
999
1016
  end
1017
+
1018
+ it "should return false without issuing a query if the model object is new" do
1019
+ @model.new.exists?.should be_false
1020
+ MODEL_DB.sqls.should == []
1021
+ end
1000
1022
  end
1001
1023
 
1002
1024
  describe Sequel::Model, "#each" do
@@ -1008,7 +1030,7 @@ describe Sequel::Model, "#each" do
1008
1030
 
1009
1031
  specify "should iterate over the values" do
1010
1032
  h = {}
1011
- @m.each {|k, v| h[k] = v}
1033
+ @m.each{|k, v| h[k] = v}
1012
1034
  h.should == {:a => 1, :b => 2, :id => 4444}
1013
1035
  end
1014
1036
  end
@@ -1021,11 +1043,8 @@ describe Sequel::Model, "#keys" do
1021
1043
  end
1022
1044
 
1023
1045
  specify "should return the value keys" do
1024
- @m.keys.size.should == 3
1025
- @m.keys.should include(:a, :b, :id)
1026
-
1027
- @m = @model.new()
1028
- @m.keys.should == []
1046
+ @m.keys.sort_by{|k| k.to_s}.should == [:a, :b, :id]
1047
+ @model.new.keys.should == []
1029
1048
  end
1030
1049
  end
1031
1050
 
@@ -1094,13 +1113,10 @@ describe Sequel::Model, "#hash" do
1094
1113
  y = Class.new(Sequel::Model)
1095
1114
  y.columns :id, :x
1096
1115
  a = z.load(:id => 1, :x => 3)
1097
- b = z.load(:id => 1, :x => 4)
1098
- c = z.load(:id => 2, :x => 3)
1099
- d = y.load(:id => 1, :x => 3)
1100
1116
 
1101
- a.hash.should == b.hash
1102
- a.hash.should_not == c.hash
1103
- a.hash.should_not == d.hash
1117
+ a.hash.should == z.load(:id => 1, :x => 4).hash
1118
+ a.hash.should_not == z.load(:id => 2, :x => 3).hash
1119
+ a.hash.should_not == y.load(:id => 1, :x => 3).hash
1104
1120
  end
1105
1121
 
1106
1122
  specify "should be the same only for objects with the same class and values if the pk is nil" do
@@ -1109,14 +1125,71 @@ describe Sequel::Model, "#hash" do
1109
1125
  y = Class.new(Sequel::Model)
1110
1126
  y.columns :id, :x
1111
1127
  a = z.new(:x => 3)
1112
- b = z.new(:x => 4)
1113
- c = z.new(:x => 3)
1114
- d = y.new(:x => 3)
1115
1128
 
1116
- a.hash.should_not == b.hash
1117
- a.hash.should == c.hash
1118
- a.hash.should_not == d.hash
1129
+ a.hash.should_not == z.new(:x => 4).hash
1130
+ a.hash.should == z.new(:x => 3).hash
1131
+ a.hash.should_not == y.new(:x => 3).hash
1132
+ end
1133
+
1134
+ specify "should be the same only for objects with the same class and pk if pk is composite and all values are non-NULL" do
1135
+ z = Class.new(Sequel::Model)
1136
+ z.columns :id, :id2, :x
1137
+ z.set_primary_key(:id, :id2)
1138
+ y = Class.new(Sequel::Model)
1139
+ y.columns :id, :id2, :x
1140
+ y.set_primary_key(:id, :id2)
1141
+ a = z.load(:id => 1, :id2=>2, :x => 3)
1142
+
1143
+ a.hash.should == z.load(:id => 1, :id2=>2, :x => 4).hash
1144
+ a.hash.should_not == z.load(:id => 2, :id2=>1, :x => 3).hash
1145
+ a.hash.should_not == y.load(:id => 1, :id2=>1, :x => 3).hash
1119
1146
  end
1147
+
1148
+ specify "should be the same only for objects with the same class and value if pk is composite and one values is NULL" do
1149
+ z = Class.new(Sequel::Model)
1150
+ z.columns :id, :id2, :x
1151
+ z.set_primary_key(:id, :id2)
1152
+ y = Class.new(Sequel::Model)
1153
+ y.columns :id, :id2, :x
1154
+ y.set_primary_key(:id, :id2)
1155
+
1156
+ a = z.load(:id => 1, :id2 => nil, :x => 3)
1157
+ a.hash.should == z.load(:id => 1, :id2=>nil, :x => 3).hash
1158
+ a.hash.should_not == z.load(:id => 1, :id2=>nil, :x => 4).hash
1159
+ a.hash.should_not == y.load(:id => 1, :id2=>nil, :x => 3).hash
1160
+
1161
+ a = z.load(:id =>nil, :id2 => nil, :x => 3)
1162
+ a.hash.should == z.load(:id => nil, :id2=>nil, :x => 3).hash
1163
+ a.hash.should_not == z.load(:id => nil, :id2=>nil, :x => 4).hash
1164
+ a.hash.should_not == y.load(:id => nil, :id2=>nil, :x => 3).hash
1165
+
1166
+ a = z.load(:id => 1, :x => 3)
1167
+ a.hash.should == z.load(:id => 1, :x => 3).hash
1168
+ a.hash.should_not == z.load(:id => 1, :id2=>nil, :x => 3).hash
1169
+ a.hash.should_not == z.load(:id => 1, :x => 4).hash
1170
+ a.hash.should_not == y.load(:id => 1, :x => 3).hash
1171
+
1172
+ a = z.load(:x => 3)
1173
+ a.hash.should == z.load(:x => 3).hash
1174
+ a.hash.should_not == z.load(:id => nil, :id2=>nil, :x => 3).hash
1175
+ a.hash.should_not == z.load(:x => 4).hash
1176
+ a.hash.should_not == y.load(:x => 3).hash
1177
+ end
1178
+
1179
+ specify "should be the same only for objects with the same class and values if the no primary key" do
1180
+ z = Class.new(Sequel::Model)
1181
+ z.columns :id, :x
1182
+ z.no_primary_key
1183
+ y = Class.new(Sequel::Model)
1184
+ y.columns :id, :x
1185
+ y.no_primary_key
1186
+ a = z.new(:x => 3)
1187
+
1188
+ a.hash.should_not == z.new(:x => 4).hash
1189
+ a.hash.should == z.new(:x => 3).hash
1190
+ a.hash.should_not == y.new(:x => 3).hash
1191
+ end
1192
+
1120
1193
  end
1121
1194
 
1122
1195
  describe Sequel::Model, "#initialize" do
@@ -1161,10 +1234,32 @@ describe Sequel::Model, "#initialize" do
1161
1234
  m.values.should == {:x => 2}
1162
1235
  end
1163
1236
  end
1237
+
1238
+ describe Sequel::Model, "#initialize_set" do
1239
+ before do
1240
+ @c = Class.new(Sequel::Model){columns :id, :x, :y}
1241
+ end
1164
1242
 
1165
- describe Sequel::Model, ".create" do
1243
+ specify "should be called by initialize to set the column values" do
1244
+ @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1245
+ @c.new(:x => 2).values.should == {:y => 3}
1246
+ end
1247
+
1248
+ specify "should be called with the hash given to initialize " do
1249
+ x = nil
1250
+ @c.send(:define_method, :initialize_set){|y| x = y}
1251
+ @c.new(:x => 2)
1252
+ x.should == {:x => 2}
1253
+ end
1254
+
1255
+ specify "should not cause columns modified by the method to be considered as changed" do
1256
+ @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1257
+ @c.new(:x => 2).changed_columns.should == []
1258
+ end
1259
+ end
1166
1260
 
1167
- before(:each) do
1261
+ describe Sequel::Model, ".create" do
1262
+ before do
1168
1263
  MODEL_DB.reset
1169
1264
  @c = Class.new(Sequel::Model(:items)) do
1170
1265
  unrestrict_primary_key
@@ -1175,13 +1270,13 @@ describe Sequel::Model, ".create" do
1175
1270
  it "should be able to create rows in the associated table" do
1176
1271
  o = @c.create(:x => 1)
1177
1272
  o.class.should == @c
1178
- MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (1)')) LIMIT 1"]
1273
+ MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1179
1274
  end
1180
1275
 
1181
1276
  it "should be able to create rows without any values specified" do
1182
1277
  o = @c.create
1183
1278
  o.class.should == @c
1184
- MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id IN ('INSERT INTO items DEFAULT VALUES')) LIMIT 1"]
1279
+ MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1185
1280
  end
1186
1281
 
1187
1282
  it "should accept a block and run it" do
@@ -1191,7 +1286,7 @@ describe Sequel::Model, ".create" do
1191
1286
  o1.should === o
1192
1287
  o3.should === o
1193
1288
  o2.should == :blah
1194
- MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (333)')) LIMIT 1"]
1289
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1195
1290
  end
1196
1291
 
1197
1292
  it "should create a row for a model with custom primary key" do
@@ -1204,32 +1299,35 @@ end
1204
1299
 
1205
1300
  describe Sequel::Model, "#refresh" do
1206
1301
  before do
1207
- MODEL_DB.reset
1208
1302
  @c = Class.new(Sequel::Model(:items)) do
1209
1303
  unrestrict_primary_key
1210
1304
  columns :id, :x
1211
1305
  end
1306
+ MODEL_DB.reset
1212
1307
  end
1213
1308
 
1214
1309
  specify "should reload the instance values from the database" do
1215
1310
  @m = @c.new(:id => 555)
1216
1311
  @m[:x] = 'blah'
1217
- @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
1312
+ @c.dataset._fetch = {:x => 'kaboom', :id => 555}
1218
1313
  @m.refresh
1219
1314
  @m[:x].should == 'kaboom'
1315
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1220
1316
  end
1221
1317
 
1222
1318
  specify "should raise if the instance is not found" do
1223
1319
  @m = @c.new(:id => 555)
1224
- @m.this.should_receive(:first).and_return(nil)
1320
+ @c.dataset._fetch = []
1225
1321
  proc {@m.refresh}.should raise_error(Sequel::Error)
1322
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1226
1323
  end
1227
1324
 
1228
1325
  specify "should be aliased by #reload" do
1229
1326
  @m = @c.new(:id => 555)
1230
- @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
1327
+ @c.dataset._fetch = {:x => 'kaboom', :id => 555}
1231
1328
  @m.reload
1232
1329
  @m[:x].should == 'kaboom'
1330
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1233
1331
  end
1234
1332
 
1235
1333
  specify "should remove cached associations" do
@@ -1243,10 +1341,11 @@ end
1243
1341
 
1244
1342
  describe Sequel::Model, "typecasting" do
1245
1343
  before do
1246
- MODEL_DB.reset
1247
1344
  @c = Class.new(Sequel::Model(:items)) do
1248
1345
  columns :x
1249
1346
  end
1347
+ @c.db_schema = {:x=>{:type=>:integer}}
1348
+ MODEL_DB.reset
1250
1349
  end
1251
1350
 
1252
1351
  after do
@@ -1255,14 +1354,13 @@ describe Sequel::Model, "typecasting" do
1255
1354
 
1256
1355
  specify "should not convert if typecasting is turned off" do
1257
1356
  @c.typecast_on_assignment = false
1258
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1259
1357
  m = @c.new
1260
1358
  m.x = '1'
1261
1359
  m.x.should == '1'
1262
1360
  end
1263
1361
 
1264
1362
  specify "should convert to integer for an integer field" do
1265
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1363
+ @c.db_schema = {:x=>{:type=>:integer}}
1266
1364
  m = @c.new
1267
1365
  m.x = '1'
1268
1366
  m.x.should == 1
@@ -1274,13 +1372,13 @@ describe Sequel::Model, "typecasting" do
1274
1372
 
1275
1373
  specify "should typecast '' to nil unless type is string or blob" do
1276
1374
  [:integer, :float, :decimal, :boolean, :date, :time, :datetime].each do |x|
1277
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
1375
+ @c.db_schema = {:x=>{:type=>x}}
1278
1376
  m = @c.new
1279
1377
  m.x = ''
1280
1378
  m.x.should == nil
1281
1379
  end
1282
1380
  [:string, :blob].each do |x|
1283
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
1381
+ @c.db_schema = {:x=>{:type=>x}}
1284
1382
  m = @c.new
1285
1383
  m.x = ''
1286
1384
  m.x.should == ''
@@ -1288,7 +1386,6 @@ describe Sequel::Model, "typecasting" do
1288
1386
  end
1289
1387
 
1290
1388
  specify "should not typecast '' to nil if typecast_empty_string_to_nil is false" do
1291
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1292
1389
  m = @c.new
1293
1390
  m.typecast_empty_string_to_nil = false
1294
1391
  proc{m.x = ''}.should raise_error
@@ -1297,21 +1394,21 @@ describe Sequel::Model, "typecasting" do
1297
1394
  end
1298
1395
 
1299
1396
  specify "should not typecast nil if NULLs are allowed" do
1300
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>true}})
1397
+ @c.db_schema[:x][:allow_null] = true
1301
1398
  m = @c.new
1302
1399
  m.x = nil
1303
1400
  m.x.should == nil
1304
1401
  end
1305
1402
 
1306
1403
  specify "should raise an error if attempting to typecast nil and NULLs are not allowed" do
1307
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1404
+ @c.db_schema[:x][:allow_null] = false
1308
1405
  proc{@c.new.x = nil}.should raise_error(Sequel::Error)
1309
1406
  proc{@c.new.x = ''}.should raise_error(Sequel::Error)
1310
1407
  end
1311
1408
 
1312
1409
  specify "should not raise an error if NULLs are not allowed and typecasting is turned off" do
1313
1410
  @c.typecast_on_assignment = false
1314
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1411
+ @c.db_schema[:x][:allow_null] = false
1315
1412
  m = @c.new
1316
1413
  m.x = nil
1317
1414
  m.x.should == nil
@@ -1320,7 +1417,6 @@ describe Sequel::Model, "typecasting" do
1320
1417
  specify "should not raise when typecasting nil to NOT NULL column but raise_on_typecast_failure is off" do
1321
1418
  @c.raise_on_typecast_failure = false
1322
1419
  @c.typecast_on_assignment = true
1323
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1324
1420
  m = @c.new
1325
1421
  m.x = ''
1326
1422
  m.x.should == nil
@@ -1329,20 +1425,18 @@ describe Sequel::Model, "typecasting" do
1329
1425
  end
1330
1426
 
1331
1427
  specify "should raise an error if invalid data is used in an integer field" do
1332
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1333
1428
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1334
1429
  end
1335
1430
 
1336
1431
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid integer" do
1337
1432
  @c.raise_on_typecast_failure = false
1338
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1339
1433
  model = @c.new
1340
1434
  model.x = '1d'
1341
1435
  model.x.should == '1d'
1342
1436
  end
1343
1437
 
1344
1438
  specify "should convert to float for a float field" do
1345
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1439
+ @c.db_schema = {:x=>{:type=>:float}}
1346
1440
  m = @c.new
1347
1441
  m.x = '1.3'
1348
1442
  m.x.should == 1.3
@@ -1353,20 +1447,20 @@ describe Sequel::Model, "typecasting" do
1353
1447
  end
1354
1448
 
1355
1449
  specify "should raise an error if invalid data is used in an float field" do
1356
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1450
+ @c.db_schema = {:x=>{:type=>:float}}
1357
1451
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1358
1452
  end
1359
1453
 
1360
1454
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid float" do
1361
1455
  @c.raise_on_typecast_failure = false
1362
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1456
+ @c.db_schema = {:x=>{:type=>:float}}
1363
1457
  model = @c.new
1364
1458
  model.x = '1d'
1365
1459
  model.x.should == '1d'
1366
1460
  end
1367
1461
 
1368
1462
  specify "should convert to BigDecimal for a decimal field" do
1369
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1463
+ @c.db_schema = {:x=>{:type=>:decimal}}
1370
1464
  m = @c.new
1371
1465
  bd = BigDecimal.new('1.0')
1372
1466
  m.x = '1.0'
@@ -1380,13 +1474,13 @@ describe Sequel::Model, "typecasting" do
1380
1474
  end
1381
1475
 
1382
1476
  specify "should raise an error if invalid data is used in an decimal field" do
1383
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1477
+ @c.db_schema = {:x=>{:type=>:decimal}}
1384
1478
  proc{@c.new.x = Date.today}.should raise_error(Sequel::InvalidValue)
1385
1479
  end
1386
1480
 
1387
1481
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1388
1482
  @c.raise_on_typecast_failure = false
1389
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1483
+ @c.db_schema = {:x=>{:type=>:decimal}}
1390
1484
  model = @c.new
1391
1485
  time = Time.now
1392
1486
  model.x = time
@@ -1394,7 +1488,7 @@ describe Sequel::Model, "typecasting" do
1394
1488
  end
1395
1489
 
1396
1490
  specify "should convert to string for a string field" do
1397
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
1491
+ @c.db_schema = {:x=>{:type=>:string}}
1398
1492
  m = @c.new
1399
1493
  m.x = '1.3'
1400
1494
  m.x.should == '1.3'
@@ -1405,7 +1499,7 @@ describe Sequel::Model, "typecasting" do
1405
1499
  end
1406
1500
 
1407
1501
  specify "should convert to boolean for a boolean field" do
1408
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:boolean}})
1502
+ @c.db_schema = {:x=>{:type=>:boolean}}
1409
1503
  m = @c.new
1410
1504
  m.x = '1.3'
1411
1505
  m.x.should == true
@@ -1417,6 +1511,10 @@ describe Sequel::Model, "typecasting" do
1417
1511
  m.x.should == true
1418
1512
  m.x = 'T'
1419
1513
  m.x.should == true
1514
+ m.x = 'y'
1515
+ m.x.should == true
1516
+ m.x = 'Y'
1517
+ m.x.should == true
1420
1518
  m.x = true
1421
1519
  m.x.should == true
1422
1520
  m.x = nil
@@ -1433,6 +1531,14 @@ describe Sequel::Model, "typecasting" do
1433
1531
  m.x.should == false
1434
1532
  m.x = 'FALSE'
1435
1533
  m.x.should == false
1534
+ m.x = 'n'
1535
+ m.x.should == false
1536
+ m.x = 'N'
1537
+ m.x.should == false
1538
+ m.x = 'no'
1539
+ m.x.should == false
1540
+ m.x = 'NO'
1541
+ m.x.should == false
1436
1542
  m.x = '0'
1437
1543
  m.x.should == false
1438
1544
  m.x = 0
@@ -1442,7 +1548,7 @@ describe Sequel::Model, "typecasting" do
1442
1548
  end
1443
1549
 
1444
1550
  specify "should convert to date for a date field" do
1445
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1551
+ @c.db_schema = {:x=>{:type=>:date}}
1446
1552
  m = @c.new
1447
1553
  y = Date.new(2007,10,21)
1448
1554
  m.x = '2007-10-21'
@@ -1456,7 +1562,7 @@ describe Sequel::Model, "typecasting" do
1456
1562
  end
1457
1563
 
1458
1564
  specify "should accept a hash with symbol or string keys for a date field" do
1459
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1565
+ @c.db_schema = {:x=>{:type=>:date}}
1460
1566
  m = @c.new
1461
1567
  y = Date.new(2007,10,21)
1462
1568
  m.x = {:year=>2007, :month=>10, :day=>21}
@@ -1466,32 +1572,33 @@ describe Sequel::Model, "typecasting" do
1466
1572
  end
1467
1573
 
1468
1574
  specify "should raise an error if invalid data is used in a date field" do
1469
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1575
+ @c.db_schema = {:x=>{:type=>:date}}
1470
1576
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1471
1577
  proc{@c.new.x = 100}.should raise_error(Sequel::InvalidValue)
1472
1578
  end
1473
1579
 
1474
1580
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid date" do
1475
1581
  @c.raise_on_typecast_failure = false
1476
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1582
+ @c.db_schema = {:x=>{:type=>:date}}
1477
1583
  model = @c.new
1478
1584
  model.x = 4
1479
1585
  model.x.should == 4
1480
1586
  end
1481
1587
 
1482
- specify "should convert to time for a time field" do
1483
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1588
+ specify "should convert to Sequel::SQLTime for a time field" do
1589
+ @c.db_schema = {:x=>{:type=>:time}}
1484
1590
  m = @c.new
1485
1591
  x = '10:20:30'
1486
- y = Time.parse(x)
1592
+ y = Sequel::SQLTime.parse(x)
1487
1593
  m.x = x
1488
1594
  m.x.should == y
1489
1595
  m.x = y
1490
1596
  m.x.should == y
1597
+ m.x.should be_a_kind_of(Sequel::SQLTime)
1491
1598
  end
1492
1599
 
1493
1600
  specify "should accept a hash with symbol or string keys for a time field" do
1494
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1601
+ @c.db_schema = {:x=>{:type=>:time}}
1495
1602
  m = @c.new
1496
1603
  y = Time.parse('10:20:30')
1497
1604
  m.x = {:hour=>10, :minute=>20, :second=>30}
@@ -1501,7 +1608,7 @@ describe Sequel::Model, "typecasting" do
1501
1608
  end
1502
1609
 
1503
1610
  specify "should raise an error if invalid data is used in a time field" do
1504
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1611
+ @c.db_schema = {:x=>{:type=>:time}}
1505
1612
  proc{@c.new.x = '0000'}.should raise_error
1506
1613
  proc{@c.new.x = Date.parse('2008-10-21')}.should raise_error(Sequel::InvalidValue)
1507
1614
  proc{@c.new.x = DateTime.parse('2008-10-21')}.should raise_error(Sequel::InvalidValue)
@@ -1509,14 +1616,14 @@ describe Sequel::Model, "typecasting" do
1509
1616
 
1510
1617
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid time" do
1511
1618
  @c.raise_on_typecast_failure = false
1512
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1619
+ @c.db_schema = {:x=>{:type=>:time}}
1513
1620
  model = @c.new
1514
1621
  model.x = '0000'
1515
1622
  model.x.should == '0000'
1516
1623
  end
1517
1624
 
1518
1625
  specify "should convert to the Sequel.datetime_class for a datetime field" do
1519
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1626
+ @c.db_schema = {:x=>{:type=>:datetime}}
1520
1627
  m = @c.new
1521
1628
  x = '2007-10-21T10:20:30-07:00'
1522
1629
  y = Time.parse(x)
@@ -1541,7 +1648,7 @@ describe Sequel::Model, "typecasting" do
1541
1648
  end
1542
1649
 
1543
1650
  specify "should accept a hash with symbol or string keys for a datetime field" do
1544
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1651
+ @c.db_schema = {:x=>{:type=>:datetime}}
1545
1652
  m = @c.new
1546
1653
  y = Time.parse('2007-10-21 10:20:30')
1547
1654
  m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
@@ -1557,7 +1664,7 @@ describe Sequel::Model, "typecasting" do
1557
1664
  end
1558
1665
 
1559
1666
  specify "should raise an error if invalid data is used in a datetime field" do
1560
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1667
+ @c.db_schema = {:x=>{:type=>:datetime}}
1561
1668
  proc{@c.new.x = '0000'}.should raise_error(Sequel::InvalidValue)
1562
1669
  Sequel.datetime_class = DateTime
1563
1670
  proc{@c.new.x = '0000'}.should raise_error(Sequel::InvalidValue)
@@ -1566,7 +1673,7 @@ describe Sequel::Model, "typecasting" do
1566
1673
 
1567
1674
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid datetime" do
1568
1675
  @c.raise_on_typecast_failure = false
1569
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1676
+ @c.db_schema = {:x=>{:type=>:datetime}}
1570
1677
  model = @c.new
1571
1678
  model.x = '0000'
1572
1679
  model.x.should == '0000'
@@ -1584,11 +1691,7 @@ describe "Model#lock!" do
1584
1691
  @c = Class.new(Sequel::Model(:items)) do
1585
1692
  columns :id
1586
1693
  end
1587
- ds = @c.dataset
1588
- def ds.fetch_rows(sql)
1589
- db.execute(sql)
1590
- yield({:id=>1})
1591
- end
1694
+ @c.dataset._fetch = {:id=>1}
1592
1695
  MODEL_DB.reset
1593
1696
  end
1594
1697