sequel 3.28.0 → 3.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/CHANGELOG +119 -3
  2. data/Rakefile +5 -3
  3. data/bin/sequel +1 -5
  4. data/doc/model_hooks.rdoc +9 -1
  5. data/doc/opening_databases.rdoc +49 -40
  6. data/doc/prepared_statements.rdoc +27 -6
  7. data/doc/release_notes/3.28.0.txt +2 -2
  8. data/doc/release_notes/3.29.0.txt +459 -0
  9. data/doc/sharding.rdoc +7 -1
  10. data/doc/testing.rdoc +18 -9
  11. data/doc/transactions.rdoc +41 -1
  12. data/lib/sequel/adapters/ado.rb +28 -17
  13. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  14. data/lib/sequel/adapters/amalgalite.rb +11 -7
  15. data/lib/sequel/adapters/db2.rb +122 -70
  16. data/lib/sequel/adapters/dbi.rb +15 -15
  17. data/lib/sequel/adapters/do.rb +5 -36
  18. data/lib/sequel/adapters/do/mysql.rb +0 -5
  19. data/lib/sequel/adapters/do/postgres.rb +0 -5
  20. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  21. data/lib/sequel/adapters/firebird.rb +3 -6
  22. data/lib/sequel/adapters/ibmdb.rb +24 -16
  23. data/lib/sequel/adapters/informix.rb +2 -4
  24. data/lib/sequel/adapters/jdbc.rb +47 -11
  25. data/lib/sequel/adapters/jdbc/as400.rb +5 -24
  26. data/lib/sequel/adapters/jdbc/db2.rb +0 -5
  27. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  28. data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
  29. data/lib/sequel/adapters/jdbc/h2.rb +10 -12
  30. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  31. data/lib/sequel/adapters/jdbc/informix.rb +0 -5
  32. data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
  34. data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
  36. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
  38. data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
  39. data/lib/sequel/adapters/mock.rb +315 -0
  40. data/lib/sequel/adapters/mysql.rb +64 -51
  41. data/lib/sequel/adapters/mysql2.rb +15 -9
  42. data/lib/sequel/adapters/odbc.rb +13 -6
  43. data/lib/sequel/adapters/odbc/db2.rb +0 -4
  44. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  45. data/lib/sequel/adapters/openbase.rb +2 -4
  46. data/lib/sequel/adapters/oracle.rb +333 -51
  47. data/lib/sequel/adapters/postgres.rb +80 -27
  48. data/lib/sequel/adapters/shared/access.rb +0 -6
  49. data/lib/sequel/adapters/shared/db2.rb +13 -15
  50. data/lib/sequel/adapters/shared/firebird.rb +6 -6
  51. data/lib/sequel/adapters/shared/mssql.rb +23 -18
  52. data/lib/sequel/adapters/shared/mysql.rb +6 -6
  53. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  54. data/lib/sequel/adapters/shared/oracle.rb +185 -30
  55. data/lib/sequel/adapters/shared/postgres.rb +35 -18
  56. data/lib/sequel/adapters/shared/progress.rb +0 -6
  57. data/lib/sequel/adapters/shared/sqlite.rb +116 -37
  58. data/lib/sequel/adapters/sqlite.rb +16 -8
  59. data/lib/sequel/adapters/swift.rb +5 -5
  60. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  61. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  62. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  63. data/lib/sequel/adapters/tinytds.rb +13 -10
  64. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
  65. data/lib/sequel/core.rb +40 -0
  66. data/lib/sequel/database/connecting.rb +1 -2
  67. data/lib/sequel/database/dataset.rb +3 -3
  68. data/lib/sequel/database/dataset_defaults.rb +58 -0
  69. data/lib/sequel/database/misc.rb +62 -2
  70. data/lib/sequel/database/query.rb +113 -49
  71. data/lib/sequel/database/schema_methods.rb +7 -2
  72. data/lib/sequel/dataset/actions.rb +37 -19
  73. data/lib/sequel/dataset/features.rb +24 -0
  74. data/lib/sequel/dataset/graph.rb +7 -6
  75. data/lib/sequel/dataset/misc.rb +11 -3
  76. data/lib/sequel/dataset/mutation.rb +2 -3
  77. data/lib/sequel/dataset/prepared_statements.rb +6 -4
  78. data/lib/sequel/dataset/query.rb +46 -15
  79. data/lib/sequel/dataset/sql.rb +28 -4
  80. data/lib/sequel/extensions/named_timezones.rb +5 -0
  81. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  82. data/lib/sequel/model.rb +2 -1
  83. data/lib/sequel/model/associations.rb +115 -33
  84. data/lib/sequel/model/base.rb +91 -31
  85. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  86. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  87. data/lib/sequel/plugins/force_encoding.rb +6 -6
  88. data/lib/sequel/plugins/identity_map.rb +1 -1
  89. data/lib/sequel/plugins/many_through_many.rb +6 -10
  90. data/lib/sequel/plugins/prepared_statements.rb +12 -1
  91. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
  92. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  93. data/lib/sequel/plugins/serialization.rb +6 -1
  94. data/lib/sequel/plugins/sharding.rb +0 -5
  95. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  96. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  97. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  98. data/lib/sequel/timezones.rb +42 -42
  99. data/lib/sequel/version.rb +1 -1
  100. data/spec/adapters/mssql_spec.rb +29 -29
  101. data/spec/adapters/mysql_spec.rb +86 -104
  102. data/spec/adapters/oracle_spec.rb +48 -76
  103. data/spec/adapters/postgres_spec.rb +98 -33
  104. data/spec/adapters/spec_helper.rb +0 -5
  105. data/spec/adapters/sqlite_spec.rb +24 -21
  106. data/spec/core/connection_pool_spec.rb +9 -15
  107. data/spec/core/core_sql_spec.rb +20 -31
  108. data/spec/core/database_spec.rb +491 -227
  109. data/spec/core/dataset_spec.rb +638 -1051
  110. data/spec/core/expression_filters_spec.rb +0 -1
  111. data/spec/core/mock_adapter_spec.rb +378 -0
  112. data/spec/core/object_graph_spec.rb +48 -114
  113. data/spec/core/schema_generator_spec.rb +3 -3
  114. data/spec/core/schema_spec.rb +51 -114
  115. data/spec/core/spec_helper.rb +3 -90
  116. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  117. data/spec/extensions/dataset_associations_spec.rb +199 -0
  118. data/spec/extensions/instance_hooks_spec.rb +71 -0
  119. data/spec/extensions/named_timezones_spec.rb +22 -2
  120. data/spec/extensions/nested_attributes_spec.rb +3 -0
  121. data/spec/extensions/schema_spec.rb +1 -1
  122. data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
  123. data/spec/extensions/serialization_spec.rb +5 -8
  124. data/spec/extensions/spec_helper.rb +4 -0
  125. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  126. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  127. data/spec/integration/associations_test.rb +123 -12
  128. data/spec/integration/dataset_test.rb +140 -47
  129. data/spec/integration/eager_loader_test.rb +19 -21
  130. data/spec/integration/model_test.rb +80 -1
  131. data/spec/integration/plugin_test.rb +179 -128
  132. data/spec/integration/prepared_statement_test.rb +92 -91
  133. data/spec/integration/schema_test.rb +42 -23
  134. data/spec/integration/spec_helper.rb +25 -31
  135. data/spec/integration/timezone_test.rb +38 -12
  136. data/spec/integration/transaction_test.rb +161 -34
  137. data/spec/integration/type_test.rb +3 -3
  138. data/spec/model/association_reflection_spec.rb +83 -7
  139. data/spec/model/associations_spec.rb +393 -676
  140. data/spec/model/base_spec.rb +186 -116
  141. data/spec/model/dataset_methods_spec.rb +7 -27
  142. data/spec/model/eager_loading_spec.rb +343 -867
  143. data/spec/model/hooks_spec.rb +160 -79
  144. data/spec/model/model_spec.rb +118 -165
  145. data/spec/model/plugins_spec.rb +7 -13
  146. data/spec/model/record_spec.rb +138 -207
  147. data/spec/model/spec_helper.rb +10 -73
  148. metadata +14 -8
@@ -125,24 +125,21 @@ describe Sequel::Model, ".plugin" do
125
125
  def self.configure(model, *args, &block)
126
126
  @args << :configure
127
127
  end
128
- im = Module.new do
128
+ self::InstanceMethods = Module.new do
129
129
  def self.included(model)
130
130
  model.plugins.last.args << :im
131
131
  end
132
132
  end
133
- cm = Module.new do
133
+ self::ClassMethods = Module.new do
134
134
  def self.extended(model)
135
135
  model.plugins.last.args << :cm
136
136
  end
137
137
  end
138
- dm = Module.new do
138
+ self::DatasetMethods = Module.new do
139
139
  def self.extended(dataset)
140
140
  dataset.model.plugins.last.args << :dm
141
141
  end
142
142
  end
143
- const_set(:InstanceMethods, im)
144
- const_set(:ClassMethods, cm)
145
- const_set(:DatasetMethods, dm)
146
143
  end
147
144
 
148
145
  b = lambda{44}
@@ -192,11 +189,10 @@ describe Sequel::Model, ".plugin" do
192
189
 
193
190
  it "should define class methods for all public instance methods in DatasetMethod" do
194
191
  m = Module.new do
195
- dm = Module.new do
192
+ self::DatasetMethods = Module.new do
196
193
  def a; 1; end
197
194
  def b; 2; end
198
195
  end
199
- const_set(:DatasetMethods, dm)
200
196
  end
201
197
  @c.plugin m
202
198
  @c.dataset.a.should == 1
@@ -205,14 +201,13 @@ describe Sequel::Model, ".plugin" do
205
201
  @c.b.should == 2
206
202
  end
207
203
 
208
- it "should define class methods for all public instance methods in DatasetMethod" do
204
+ it "should not define class methods for private instance methods in DatasetMethod" do
209
205
  m = Module.new do
210
- dm = Module.new do
206
+ self::DatasetMethods = Module.new do
211
207
  def b; 2; end
212
208
  private
213
209
  def a; 1; end
214
210
  end
215
- const_set(:DatasetMethods, dm)
216
211
  end
217
212
  @c.plugin m
218
213
  @c.dataset.b.should == 2
@@ -225,11 +220,10 @@ describe Sequel::Model, ".plugin" do
225
220
 
226
221
  it "should not raise an error if the DatasetMethod module has no public instance methods" do
227
222
  m = Module.new do
228
- dm = Module.new do
223
+ self::DatasetMethods = Module.new do
229
224
  private
230
225
  def a; 1; end
231
226
  end
232
- const_set(:DatasetMethods, dm)
233
227
  end
234
228
  lambda{@c.plugin m}.should_not raise_error
235
229
  end
@@ -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,29 +26,28 @@ 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}
55
42
  def ds.supports_insert_select?() true end
56
43
  def ds.insert_select(hash)
57
- execute("INSERT INTO items (y) VALUES (2)")
58
- {:y=>2}
44
+ execute("INSERT INTO items (y) VALUES (2) RETURNING *"){|r| return r}
59
45
  end
60
46
  o = @c.new(:x => 1)
61
47
  o.save
62
48
 
63
49
  o.values.should == {:y=>2}
64
- MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2)"]
50
+ MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2) RETURNING *"]
65
51
  end
66
52
 
67
53
  it "should not use dataset's insert_select method if specific columns are selected" do
@@ -71,7 +57,6 @@ describe "Model#save" do
71
57
  end
72
58
 
73
59
  it "should use value returned by insert as the primary key and refresh the object" do
74
- @c.dataset.meta_def(:insert){|h| super(h); 13}
75
60
  o = @c.new(:x => 11)
76
61
  o.save
77
62
  MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)",
@@ -79,14 +64,12 @@ describe "Model#save" do
79
64
  end
80
65
 
81
66
  it "should allow you to skip refreshing by overridding _save_refresh" do
82
- @c.dataset.meta_def(:insert){|h| super(h); 13}
83
67
  @c.send(:define_method, :_save_refresh){}
84
68
  @c.create(:x => 11)
85
69
  MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
86
70
  end
87
71
 
88
72
  it "should work correctly for inserting a record without a primary key" do
89
- @c.dataset.meta_def(:insert){|h| super(h); 13}
90
73
  @c.no_primary_key
91
74
  o = @c.new(:x => 11)
92
75
  o.save
@@ -94,15 +77,15 @@ describe "Model#save" do
94
77
  end
95
78
 
96
79
  it "should set the autoincrementing_primary_key value to the value returned by insert" do
97
- @c.dataset.meta_def(:insert){|h| super(h); 13}
98
80
  @c.unrestrict_primary_key
99
81
  @c.set_primary_key [:x, :y]
100
82
  o = @c.new(:x => 11)
101
83
  o.meta_def(:autoincrementing_primary_key){:y}
102
84
  o.save
103
- MODEL_DB.sqls.length.should == 2
104
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (11)"
105
- 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}
106
89
  end
107
90
 
108
91
  it "should update a record for an existing model instance" do
@@ -113,17 +96,18 @@ describe "Model#save" do
113
96
 
114
97
  it "should raise a NoExistingObject exception if the dataset update call doesn't return 1, unless require_modification is false" do
115
98
  o = @c.load(:id => 3, :x => 1)
116
- o.this.meta_def(:update){|*a| 0}
99
+ t = o.this
100
+ t.numrows = 0
117
101
  proc{o.save}.should raise_error(Sequel::NoExistingObject)
118
- o.this.meta_def(:update){|*a| 2}
102
+ t.numrows = 2
119
103
  proc{o.save}.should raise_error(Sequel::NoExistingObject)
120
- o.this.meta_def(:update){|*a| 1}
104
+ t.numrows = 1
121
105
  proc{o.save}.should_not raise_error
122
106
 
123
107
  o.require_modification = false
124
- o.this.meta_def(:update){|*a| 0}
108
+ t.numrows = 0
125
109
  proc{o.save}.should_not raise_error
126
- o.this.meta_def(:update){|*a| 2}
110
+ t.numrows = 2
127
111
  proc{o.save}.should_not raise_error
128
112
  end
129
113
 
@@ -192,22 +176,18 @@ describe "Model#save" do
192
176
  @c.use_transactions = true
193
177
  @c.load(:id => 3, :x => 1, :y => nil).save(:y)
194
178
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
195
- MODEL_DB.reset
196
179
  @c.use_transactions = false
197
180
  @c.load(:id => 3, :x => 1, :y => nil).save(:y)
198
181
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
199
- MODEL_DB.reset
200
182
  end
201
183
 
202
184
  it "should inherit Model's use_transactions setting" do
203
185
  @c.use_transactions = true
204
186
  Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
205
187
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
206
- MODEL_DB.reset
207
188
  @c.use_transactions = false
208
189
  Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
209
190
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
210
- MODEL_DB.reset
211
191
  end
212
192
 
213
193
  it "should use object's use_transactions setting" do
@@ -216,13 +196,11 @@ describe "Model#save" do
216
196
  @c.use_transactions = true
217
197
  o.save(:y)
218
198
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
219
- MODEL_DB.reset
220
199
  o = @c.load(:id => 3, :x => 1, :y => nil)
221
200
  o.use_transactions = true
222
201
  @c.use_transactions = false
223
202
  o.save(:y)
224
203
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
225
- MODEL_DB.reset
226
204
  end
227
205
 
228
206
  it "should use :transaction option if given" do
@@ -230,12 +208,10 @@ describe "Model#save" do
230
208
  o.use_transactions = true
231
209
  o.save(:y, :transaction=>false)
232
210
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
233
- MODEL_DB.reset
234
211
  o = @c.load(:id => 3, :x => 1, :y => nil)
235
212
  o.use_transactions = false
236
213
  o.save(:y, :transaction=>true)
237
214
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
238
- MODEL_DB.reset
239
215
  end
240
216
 
241
217
  it "should rollback if before_save returns false and raise_on_save_failure = true" do
@@ -247,7 +223,6 @@ describe "Model#save" do
247
223
  end
248
224
  proc { o.save(:y) }.should raise_error(Sequel::BeforeHookFailed)
249
225
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
250
- MODEL_DB.reset
251
226
  end
252
227
 
253
228
  it "should rollback if before_save returns false and :raise_on_failure option is true" do
@@ -259,7 +234,6 @@ describe "Model#save" do
259
234
  end
260
235
  proc { o.save(:y, :raise_on_failure => true) }.should raise_error(Sequel::BeforeHookFailed)
261
236
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
262
- MODEL_DB.reset
263
237
  end
264
238
 
265
239
  it "should not rollback outer transactions if before_save returns false and raise_on_save_failure = false" do
@@ -274,7 +248,6 @@ describe "Model#save" do
274
248
  MODEL_DB.run "BLAH"
275
249
  end
276
250
  MODEL_DB.sqls.should == ["BEGIN", "BLAH", "COMMIT"]
277
- MODEL_DB.reset
278
251
  end
279
252
 
280
253
  it "should rollback if before_save returns false and raise_on_save_failure = false" do
@@ -286,7 +259,6 @@ describe "Model#save" do
286
259
  end
287
260
  o.save(:y).should == nil
288
261
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
289
- MODEL_DB.reset
290
262
  end
291
263
 
292
264
  it "should not rollback if before_save throws Rollback and use_transactions = false" do
@@ -297,7 +269,6 @@ describe "Model#save" do
297
269
  end
298
270
  proc { o.save(:y) }.should raise_error(Sequel::Rollback)
299
271
  MODEL_DB.sqls.should == []
300
- MODEL_DB.reset
301
272
  end
302
273
  end
303
274
 
@@ -306,7 +277,6 @@ describe "Model#marshallable" do
306
277
  class ::Album < Sequel::Model
307
278
  columns :id, :x
308
279
  end
309
- Album.dataset.meta_def(:insert){|h| super(h); 1}
310
280
  end
311
281
  after do
312
282
  Object.send(:remove_const, :Album)
@@ -388,7 +358,6 @@ describe "Model#modified[!?]" do
388
358
  end
389
359
 
390
360
  describe "Model#save_changes" do
391
-
392
361
  before do
393
362
  @c = Class.new(Sequel::Model(:items)) do
394
363
  unrestrict_primary_key
@@ -433,15 +402,14 @@ describe "Model#save_changes" do
433
402
  MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
434
403
  o.save_changes
435
404
  o.save_changes
436
- MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
437
- MODEL_DB.reset
405
+ MODEL_DB.sqls.should == []
438
406
 
439
407
  o.y = 4
440
408
  o.save_changes
441
409
  MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
442
410
  o.save_changes
443
411
  o.save_changes
444
- MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
412
+ MODEL_DB.sqls.should == []
445
413
  end
446
414
 
447
415
  it "should not consider columns changed if the values did not change" do
@@ -453,7 +421,6 @@ describe "Model#save_changes" do
453
421
  o.x = 3
454
422
  o.save_changes
455
423
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
456
- MODEL_DB.reset
457
424
 
458
425
  o[:y] = nil
459
426
  o.save_changes
@@ -479,13 +446,11 @@ describe "Model#save_changes" do
479
446
  o.x = 2
480
447
  o.save_changes
481
448
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
482
- MODEL_DB.reset
483
449
  o.save_changes
484
450
  MODEL_DB.sqls.should == []
485
451
  o.x = 4
486
452
  o.save_changes
487
453
  MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
488
- MODEL_DB.reset
489
454
  end
490
455
 
491
456
  it "should update columns changed in a before_save hook" do
@@ -496,25 +461,21 @@ describe "Model#save_changes" do
496
461
  o.x = 2
497
462
  o.save_changes
498
463
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
499
- MODEL_DB.reset
500
464
  o.save_changes
501
465
  MODEL_DB.sqls.should == []
502
466
  o.x = 4
503
467
  o.save_changes
504
468
  MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
505
- MODEL_DB.reset
506
469
  end
507
470
  end
508
471
 
509
472
  describe "Model#new?" do
510
-
511
- before(:each) do
512
- MODEL_DB.reset
513
-
473
+ before do
514
474
  @c = Class.new(Sequel::Model(:items)) do
515
475
  unrestrict_primary_key
516
476
  columns :x
517
477
  end
478
+ MODEL_DB.reset
518
479
  end
519
480
 
520
481
  it "should be true for a new instance" do
@@ -530,74 +491,65 @@ describe "Model#new?" do
530
491
  end
531
492
 
532
493
  describe Sequel::Model, "w/ primary key" do
533
-
534
494
  it "should default to ':id'" do
535
495
  model_a = Class.new Sequel::Model
536
- model_a.primary_key.should be_equal(:id)
496
+ model_a.primary_key.should == :id
537
497
  end
538
498
 
539
499
  it "should be changed through 'set_primary_key'" do
540
- model_a = Class.new(Sequel::Model) { set_primary_key :a }
541
- 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
542
502
  end
543
503
 
544
504
  it "should support multi argument composite keys" do
545
- model_a = Class.new(Sequel::Model) { set_primary_key :a, :b }
546
- 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]
547
507
  end
548
508
 
549
509
  it "should accept single argument composite keys" do
550
- model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
551
- 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]
552
512
  end
553
-
554
513
  end
555
514
 
556
515
  describe Sequel::Model, "w/o primary key" do
557
516
  it "should return nil for primary key" do
558
- 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
559
518
  end
560
519
 
561
520
  it "should raise a Sequel::Error on 'this'" do
562
- instance = Class.new(Sequel::Model) { no_primary_key }.new
563
- 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)
564
523
  end
565
524
  end
566
525
 
567
526
  describe Sequel::Model, "with this" do
568
-
569
- 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
570
531
 
571
532
  it "should return a dataset identifying the record" do
572
- instance = @example.load :id => 3
573
- 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"
574
535
  end
575
536
 
576
537
  it "should support arbitary primary keys" do
577
538
  @example.set_primary_key :a
578
539
 
579
- instance = @example.load :a => 3
580
- 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"
581
542
  end
582
543
 
583
544
  it "should support composite primary keys" do
584
545
  @example.set_primary_key :x, :y
585
- instance = @example.load :x => 4, :y => 5
586
-
587
- parts = [
588
- 'SELECT * FROM examples WHERE %s LIMIT 1',
589
- '((x = 4) AND (y = 5))',
590
- '((y = 5) AND (x = 4))'
591
- ].map { |expr| Regexp.escape expr }
592
- regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
593
-
594
- 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/
595
548
  end
596
-
597
549
  end
598
550
 
599
551
  describe "Model#pk" do
600
- before(:each) do
552
+ before do
601
553
  @m = Class.new(Sequel::Model)
602
554
  @m.columns :id, :x, :y
603
555
  end
@@ -631,7 +583,7 @@ describe "Model#pk" do
631
583
  end
632
584
 
633
585
  describe "Model#pk_or_nil" do
634
- before(:each) do
586
+ before do
635
587
  @m = Class.new(Sequel::Model)
636
588
  @m.columns :id, :x, :y
637
589
  end
@@ -665,7 +617,7 @@ describe "Model#pk_or_nil" do
665
617
  end
666
618
 
667
619
  describe "Model#pk_hash" do
668
- before(:each) do
620
+ before do
669
621
  @m = Class.new(Sequel::Model)
670
622
  @m.columns :id, :x, :y
671
623
  end
@@ -700,16 +652,14 @@ end
700
652
 
701
653
  describe Sequel::Model, "#set" do
702
654
  before do
703
- MODEL_DB.reset
704
-
705
655
  @c = Class.new(Sequel::Model(:items)) do
706
656
  set_primary_key :id
707
657
  columns :x, :y, :id
708
658
  end
709
659
  @c.strict_param_setting = false
710
- @c.instance_variable_set(:@columns, true)
711
660
  @o1 = @c.new
712
661
  @o2 = @c.load(:id => 5)
662
+ MODEL_DB.reset
713
663
  end
714
664
 
715
665
  it "should filter the given params using the model columns" do
@@ -833,47 +783,44 @@ end
833
783
 
834
784
  describe Sequel::Model, "#update" do
835
785
  before do
836
- MODEL_DB.reset
837
-
838
786
  @c = Class.new(Sequel::Model(:items)) do
839
787
  set_primary_key :id
840
788
  columns :x, :y, :id
841
789
  end
842
790
  @c.strict_param_setting = false
843
- @c.instance_variable_set(:@columns, true)
844
791
  @o1 = @c.new
845
792
  @o2 = @c.load(:id => 5)
793
+ MODEL_DB.reset
846
794
  end
847
795
 
848
796
  it "should filter the given params using the model columns" do
849
797
  @o1.update(:x => 1, :z => 2)
850
- 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"]
851
799
 
852
800
  MODEL_DB.reset
853
801
  @o2.update(:y => 1, :abc => 2)
854
- 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)"]
855
803
  end
856
804
 
857
805
  it "should support virtual attributes" do
858
806
  @c.send(:define_method, :blah=){|v| self.x = v}
859
807
  @o1.update(:blah => 333)
860
- 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"]
861
809
  end
862
810
 
863
811
  it "should not modify the primary key" do
864
812
  @o1.update(:x => 1, :id => 2)
865
- 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"]
866
814
  MODEL_DB.reset
867
815
  @o2.update('y'=> 1, 'id'=> 2)
868
816
  @o2.values.should == {:y => 1, :id=> 5}
869
- 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)"]
870
818
  end
871
819
  end
872
820
 
873
821
  describe Sequel::Model, "#set_fields" do
874
822
  before do
875
- @c = Class.new(Sequel::Model(:items))
876
- @c.class_eval do
823
+ @c = Class.new(Sequel::Model(:items)) do
877
824
  set_primary_key :id
878
825
  columns :x, :y, :z, :id
879
826
  end
@@ -893,11 +840,9 @@ end
893
840
 
894
841
  describe Sequel::Model, "#update_fields" do
895
842
  before do
896
- @c = Class.new(Sequel::Model(:items))
897
- @c.class_eval do
843
+ @c = Class.new(Sequel::Model(:items)) do
898
844
  set_primary_key :id
899
845
  columns :x, :y, :z, :id
900
- def _refresh(ds); end
901
846
  end
902
847
  @c.strict_param_setting = true
903
848
  @o1 = @c.load(:id=>1)
@@ -907,21 +852,18 @@ describe Sequel::Model, "#update_fields" do
907
852
  it "should set only the given fields, and then save the changes to the record" do
908
853
  @o1.update_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
909
854
  @o1.values.should == {:x => 1, :y => 2, :id=>1}
910
- MODEL_DB.sqls.first.should =~ /UPDATE items SET [xy] = [12], [xy] = [12] WHERE \(id = 1\)/
911
- MODEL_DB.sqls.length.should == 1
912
- 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 == []
913
858
 
914
859
  @o1.update_fields({:x => 1, :y => 5, :z=>6, :id=>7}, [:x, :y])
915
860
  @o1.values.should == {:x => 1, :y => 5, :id=>1}
916
861
  MODEL_DB.sqls.should == ["UPDATE items SET y = 5 WHERE (id = 1)"]
917
- MODEL_DB.reset
918
862
  end
919
863
  end
920
864
 
921
865
  describe Sequel::Model, "#(set|update)_(all|except|only)" do
922
866
  before do
923
- MODEL_DB.reset
924
-
925
867
  @c = Class.new(Sequel::Model(:items)) do
926
868
  set_primary_key :id
927
869
  columns :x, :y, :z, :id
@@ -929,8 +871,8 @@ describe Sequel::Model, "#(set|update)_(all|except|only)" do
929
871
  set_restricted_columns :y
930
872
  end
931
873
  @c.strict_param_setting = false
932
- @c.instance_variable_set(:@columns, true)
933
874
  @o1 = @c.new
875
+ MODEL_DB.reset
934
876
  end
935
877
 
936
878
  it "should raise errors if not all hash fields can be set and strict_param_setting is true" do
@@ -974,40 +916,34 @@ describe Sequel::Model, "#(set|update)_(all|except|only)" do
974
916
 
975
917
  it "#update_all should update all attributes" do
976
918
  @c.new.update_all(:x => 1, :id=>4)
977
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
978
- MODEL_DB.reset
919
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
979
920
  @c.new.update_all(:y => 1, :id=>4)
980
- MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
981
- MODEL_DB.reset
921
+ MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
982
922
  @c.new.update_all(:z => 1, :id=>4)
983
- 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"]
984
924
  end
985
925
 
986
926
  it "#update_only should only update given attributes" do
987
927
  @o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
988
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
989
- MODEL_DB.reset
928
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
990
929
  @c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
991
- 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"]
992
931
  end
993
932
 
994
933
  it "#update_except should not update given attributes" do
995
934
  @o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
996
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
997
- MODEL_DB.reset
935
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
998
936
  @c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
999
- 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"]
1000
938
  end
1001
939
  end
1002
940
 
1003
941
  describe Sequel::Model, "#destroy" do
1004
942
  before do
1005
- MODEL_DB.reset
1006
943
  @model = Class.new(Sequel::Model(:items))
1007
944
  @model.columns :id
1008
- @model.dataset.meta_def(:delete){MODEL_DB.execute delete_sql;1}
1009
-
1010
945
  @instance = @model.load(:id => 1234)
946
+ MODEL_DB.reset
1011
947
  end
1012
948
 
1013
949
  it "should return self" do
@@ -1032,49 +968,40 @@ describe Sequel::Model, "#destroy" do
1032
968
 
1033
969
  it "should run within a transaction if use_transactions is true" do
1034
970
  @instance.use_transactions = true
1035
- @model.db.should_receive(:transaction)
1036
971
  @instance.destroy
972
+ MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE (id = 1234)", "COMMIT"]
1037
973
  end
1038
974
 
1039
975
  it "should not run within a transaction if use_transactions is false" do
1040
976
  @instance.use_transactions = false
1041
- @model.db.should_not_receive(:transaction)
1042
977
  @instance.destroy
978
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE (id = 1234)"]
1043
979
  end
1044
980
 
1045
981
  it "should run within a transaction if :transaction option is true" do
1046
982
  @instance.use_transactions = false
1047
- @model.db.should_receive(:transaction)
1048
983
  @instance.destroy(:transaction => true)
984
+ MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE (id = 1234)", "COMMIT"]
1049
985
  end
1050
986
 
1051
987
  it "should not run within a transaction if :transaction option is false" do
1052
988
  @instance.use_transactions = true
1053
- @model.db.should_not_receive(:transaction)
1054
989
  @instance.destroy(:transaction => false)
990
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE (id = 1234)"]
1055
991
  end
1056
992
 
1057
993
  it "should run before_destroy and after_destroy hooks" do
1058
994
  @model.send(:define_method, :before_destroy){MODEL_DB.execute('before blah')}
1059
995
  @model.send(:define_method, :after_destroy){MODEL_DB.execute('after blah')}
1060
996
  @instance.destroy
1061
-
1062
- MODEL_DB.sqls.should == [
1063
- "before blah",
1064
- "DELETE FROM items WHERE (id = 1234)",
1065
- "after blah"
1066
- ]
997
+ MODEL_DB.sqls.should == ["before blah", "DELETE FROM items WHERE (id = 1234)", "after blah"]
1067
998
  end
1068
999
  end
1069
1000
 
1070
1001
  describe Sequel::Model, "#exists?" do
1071
- before(:each) do
1002
+ before do
1072
1003
  @model = Class.new(Sequel::Model(:items))
1073
- @ds = @model.dataset
1074
- def @ds.fetch_rows(sql)
1075
- db.execute(sql)
1076
- yield(:x=>1) if sql =~ /id = 1/
1077
- end
1004
+ @model.dataset._fetch = proc{|sql| {:x=>1} if sql =~ /id = 1/}
1078
1005
  MODEL_DB.reset
1079
1006
  end
1080
1007
 
@@ -1103,7 +1030,7 @@ describe Sequel::Model, "#each" do
1103
1030
 
1104
1031
  specify "should iterate over the values" do
1105
1032
  h = {}
1106
- @m.each {|k, v| h[k] = v}
1033
+ @m.each{|k, v| h[k] = v}
1107
1034
  h.should == {:a => 1, :b => 2, :id => 4444}
1108
1035
  end
1109
1036
  end
@@ -1116,11 +1043,8 @@ describe Sequel::Model, "#keys" do
1116
1043
  end
1117
1044
 
1118
1045
  specify "should return the value keys" do
1119
- @m.keys.size.should == 3
1120
- @m.keys.should include(:a, :b, :id)
1121
-
1122
- @m = @model.new()
1123
- @m.keys.should == []
1046
+ @m.keys.sort_by{|k| k.to_s}.should == [:a, :b, :id]
1047
+ @model.new.keys.should == []
1124
1048
  end
1125
1049
  end
1126
1050
 
@@ -1335,8 +1259,7 @@ describe Sequel::Model, "#initialize_set" do
1335
1259
  end
1336
1260
 
1337
1261
  describe Sequel::Model, ".create" do
1338
-
1339
- before(:each) do
1262
+ before do
1340
1263
  MODEL_DB.reset
1341
1264
  @c = Class.new(Sequel::Model(:items)) do
1342
1265
  unrestrict_primary_key
@@ -1347,13 +1270,13 @@ describe Sequel::Model, ".create" do
1347
1270
  it "should be able to create rows in the associated table" do
1348
1271
  o = @c.create(:x => 1)
1349
1272
  o.class.should == @c
1350
- 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"]
1351
1274
  end
1352
1275
 
1353
1276
  it "should be able to create rows without any values specified" do
1354
1277
  o = @c.create
1355
1278
  o.class.should == @c
1356
- 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"]
1357
1280
  end
1358
1281
 
1359
1282
  it "should accept a block and run it" do
@@ -1363,7 +1286,7 @@ describe Sequel::Model, ".create" do
1363
1286
  o1.should === o
1364
1287
  o3.should === o
1365
1288
  o2.should == :blah
1366
- 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"]
1367
1290
  end
1368
1291
 
1369
1292
  it "should create a row for a model with custom primary key" do
@@ -1376,32 +1299,35 @@ end
1376
1299
 
1377
1300
  describe Sequel::Model, "#refresh" do
1378
1301
  before do
1379
- MODEL_DB.reset
1380
1302
  @c = Class.new(Sequel::Model(:items)) do
1381
1303
  unrestrict_primary_key
1382
1304
  columns :id, :x
1383
1305
  end
1306
+ MODEL_DB.reset
1384
1307
  end
1385
1308
 
1386
1309
  specify "should reload the instance values from the database" do
1387
1310
  @m = @c.new(:id => 555)
1388
1311
  @m[:x] = 'blah'
1389
- @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
1312
+ @c.dataset._fetch = {:x => 'kaboom', :id => 555}
1390
1313
  @m.refresh
1391
1314
  @m[:x].should == 'kaboom'
1315
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1392
1316
  end
1393
1317
 
1394
1318
  specify "should raise if the instance is not found" do
1395
1319
  @m = @c.new(:id => 555)
1396
- @m.this.should_receive(:first).and_return(nil)
1320
+ @c.dataset._fetch = []
1397
1321
  proc {@m.refresh}.should raise_error(Sequel::Error)
1322
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1398
1323
  end
1399
1324
 
1400
1325
  specify "should be aliased by #reload" do
1401
1326
  @m = @c.new(:id => 555)
1402
- @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
1327
+ @c.dataset._fetch = {:x => 'kaboom', :id => 555}
1403
1328
  @m.reload
1404
1329
  @m[:x].should == 'kaboom'
1330
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1405
1331
  end
1406
1332
 
1407
1333
  specify "should remove cached associations" do
@@ -1415,10 +1341,11 @@ end
1415
1341
 
1416
1342
  describe Sequel::Model, "typecasting" do
1417
1343
  before do
1418
- MODEL_DB.reset
1419
1344
  @c = Class.new(Sequel::Model(:items)) do
1420
1345
  columns :x
1421
1346
  end
1347
+ @c.db_schema = {:x=>{:type=>:integer}}
1348
+ MODEL_DB.reset
1422
1349
  end
1423
1350
 
1424
1351
  after do
@@ -1427,14 +1354,13 @@ describe Sequel::Model, "typecasting" do
1427
1354
 
1428
1355
  specify "should not convert if typecasting is turned off" do
1429
1356
  @c.typecast_on_assignment = false
1430
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1431
1357
  m = @c.new
1432
1358
  m.x = '1'
1433
1359
  m.x.should == '1'
1434
1360
  end
1435
1361
 
1436
1362
  specify "should convert to integer for an integer field" do
1437
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1363
+ @c.db_schema = {:x=>{:type=>:integer}}
1438
1364
  m = @c.new
1439
1365
  m.x = '1'
1440
1366
  m.x.should == 1
@@ -1446,13 +1372,13 @@ describe Sequel::Model, "typecasting" do
1446
1372
 
1447
1373
  specify "should typecast '' to nil unless type is string or blob" do
1448
1374
  [:integer, :float, :decimal, :boolean, :date, :time, :datetime].each do |x|
1449
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
1375
+ @c.db_schema = {:x=>{:type=>x}}
1450
1376
  m = @c.new
1451
1377
  m.x = ''
1452
1378
  m.x.should == nil
1453
1379
  end
1454
1380
  [:string, :blob].each do |x|
1455
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
1381
+ @c.db_schema = {:x=>{:type=>x}}
1456
1382
  m = @c.new
1457
1383
  m.x = ''
1458
1384
  m.x.should == ''
@@ -1460,7 +1386,6 @@ describe Sequel::Model, "typecasting" do
1460
1386
  end
1461
1387
 
1462
1388
  specify "should not typecast '' to nil if typecast_empty_string_to_nil is false" do
1463
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1464
1389
  m = @c.new
1465
1390
  m.typecast_empty_string_to_nil = false
1466
1391
  proc{m.x = ''}.should raise_error
@@ -1469,21 +1394,21 @@ describe Sequel::Model, "typecasting" do
1469
1394
  end
1470
1395
 
1471
1396
  specify "should not typecast nil if NULLs are allowed" do
1472
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>true}})
1397
+ @c.db_schema[:x][:allow_null] = true
1473
1398
  m = @c.new
1474
1399
  m.x = nil
1475
1400
  m.x.should == nil
1476
1401
  end
1477
1402
 
1478
1403
  specify "should raise an error if attempting to typecast nil and NULLs are not allowed" do
1479
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1404
+ @c.db_schema[:x][:allow_null] = false
1480
1405
  proc{@c.new.x = nil}.should raise_error(Sequel::Error)
1481
1406
  proc{@c.new.x = ''}.should raise_error(Sequel::Error)
1482
1407
  end
1483
1408
 
1484
1409
  specify "should not raise an error if NULLs are not allowed and typecasting is turned off" do
1485
1410
  @c.typecast_on_assignment = false
1486
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1411
+ @c.db_schema[:x][:allow_null] = false
1487
1412
  m = @c.new
1488
1413
  m.x = nil
1489
1414
  m.x.should == nil
@@ -1492,7 +1417,6 @@ describe Sequel::Model, "typecasting" do
1492
1417
  specify "should not raise when typecasting nil to NOT NULL column but raise_on_typecast_failure is off" do
1493
1418
  @c.raise_on_typecast_failure = false
1494
1419
  @c.typecast_on_assignment = true
1495
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1496
1420
  m = @c.new
1497
1421
  m.x = ''
1498
1422
  m.x.should == nil
@@ -1501,20 +1425,18 @@ describe Sequel::Model, "typecasting" do
1501
1425
  end
1502
1426
 
1503
1427
  specify "should raise an error if invalid data is used in an integer field" do
1504
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1505
1428
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1506
1429
  end
1507
1430
 
1508
1431
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid integer" do
1509
1432
  @c.raise_on_typecast_failure = false
1510
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1511
1433
  model = @c.new
1512
1434
  model.x = '1d'
1513
1435
  model.x.should == '1d'
1514
1436
  end
1515
1437
 
1516
1438
  specify "should convert to float for a float field" do
1517
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1439
+ @c.db_schema = {:x=>{:type=>:float}}
1518
1440
  m = @c.new
1519
1441
  m.x = '1.3'
1520
1442
  m.x.should == 1.3
@@ -1525,20 +1447,20 @@ describe Sequel::Model, "typecasting" do
1525
1447
  end
1526
1448
 
1527
1449
  specify "should raise an error if invalid data is used in an float field" do
1528
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1450
+ @c.db_schema = {:x=>{:type=>:float}}
1529
1451
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1530
1452
  end
1531
1453
 
1532
1454
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid float" do
1533
1455
  @c.raise_on_typecast_failure = false
1534
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1456
+ @c.db_schema = {:x=>{:type=>:float}}
1535
1457
  model = @c.new
1536
1458
  model.x = '1d'
1537
1459
  model.x.should == '1d'
1538
1460
  end
1539
1461
 
1540
1462
  specify "should convert to BigDecimal for a decimal field" do
1541
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1463
+ @c.db_schema = {:x=>{:type=>:decimal}}
1542
1464
  m = @c.new
1543
1465
  bd = BigDecimal.new('1.0')
1544
1466
  m.x = '1.0'
@@ -1552,13 +1474,13 @@ describe Sequel::Model, "typecasting" do
1552
1474
  end
1553
1475
 
1554
1476
  specify "should raise an error if invalid data is used in an decimal field" do
1555
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1477
+ @c.db_schema = {:x=>{:type=>:decimal}}
1556
1478
  proc{@c.new.x = Date.today}.should raise_error(Sequel::InvalidValue)
1557
1479
  end
1558
1480
 
1559
1481
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1560
1482
  @c.raise_on_typecast_failure = false
1561
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1483
+ @c.db_schema = {:x=>{:type=>:decimal}}
1562
1484
  model = @c.new
1563
1485
  time = Time.now
1564
1486
  model.x = time
@@ -1566,7 +1488,7 @@ describe Sequel::Model, "typecasting" do
1566
1488
  end
1567
1489
 
1568
1490
  specify "should convert to string for a string field" do
1569
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
1491
+ @c.db_schema = {:x=>{:type=>:string}}
1570
1492
  m = @c.new
1571
1493
  m.x = '1.3'
1572
1494
  m.x.should == '1.3'
@@ -1577,7 +1499,7 @@ describe Sequel::Model, "typecasting" do
1577
1499
  end
1578
1500
 
1579
1501
  specify "should convert to boolean for a boolean field" do
1580
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:boolean}})
1502
+ @c.db_schema = {:x=>{:type=>:boolean}}
1581
1503
  m = @c.new
1582
1504
  m.x = '1.3'
1583
1505
  m.x.should == true
@@ -1589,6 +1511,10 @@ describe Sequel::Model, "typecasting" do
1589
1511
  m.x.should == true
1590
1512
  m.x = 'T'
1591
1513
  m.x.should == true
1514
+ m.x = 'y'
1515
+ m.x.should == true
1516
+ m.x = 'Y'
1517
+ m.x.should == true
1592
1518
  m.x = true
1593
1519
  m.x.should == true
1594
1520
  m.x = nil
@@ -1605,6 +1531,14 @@ describe Sequel::Model, "typecasting" do
1605
1531
  m.x.should == false
1606
1532
  m.x = 'FALSE'
1607
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
1608
1542
  m.x = '0'
1609
1543
  m.x.should == false
1610
1544
  m.x = 0
@@ -1614,7 +1548,7 @@ describe Sequel::Model, "typecasting" do
1614
1548
  end
1615
1549
 
1616
1550
  specify "should convert to date for a date field" do
1617
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1551
+ @c.db_schema = {:x=>{:type=>:date}}
1618
1552
  m = @c.new
1619
1553
  y = Date.new(2007,10,21)
1620
1554
  m.x = '2007-10-21'
@@ -1628,7 +1562,7 @@ describe Sequel::Model, "typecasting" do
1628
1562
  end
1629
1563
 
1630
1564
  specify "should accept a hash with symbol or string keys for a date field" do
1631
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1565
+ @c.db_schema = {:x=>{:type=>:date}}
1632
1566
  m = @c.new
1633
1567
  y = Date.new(2007,10,21)
1634
1568
  m.x = {:year=>2007, :month=>10, :day=>21}
@@ -1638,32 +1572,33 @@ describe Sequel::Model, "typecasting" do
1638
1572
  end
1639
1573
 
1640
1574
  specify "should raise an error if invalid data is used in a date field" do
1641
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1575
+ @c.db_schema = {:x=>{:type=>:date}}
1642
1576
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1643
1577
  proc{@c.new.x = 100}.should raise_error(Sequel::InvalidValue)
1644
1578
  end
1645
1579
 
1646
1580
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid date" do
1647
1581
  @c.raise_on_typecast_failure = false
1648
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1582
+ @c.db_schema = {:x=>{:type=>:date}}
1649
1583
  model = @c.new
1650
1584
  model.x = 4
1651
1585
  model.x.should == 4
1652
1586
  end
1653
1587
 
1654
- specify "should convert to time for a time field" do
1655
- @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}}
1656
1590
  m = @c.new
1657
1591
  x = '10:20:30'
1658
- y = Time.parse(x)
1592
+ y = Sequel::SQLTime.parse(x)
1659
1593
  m.x = x
1660
1594
  m.x.should == y
1661
1595
  m.x = y
1662
1596
  m.x.should == y
1597
+ m.x.should be_a_kind_of(Sequel::SQLTime)
1663
1598
  end
1664
1599
 
1665
1600
  specify "should accept a hash with symbol or string keys for a time field" do
1666
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1601
+ @c.db_schema = {:x=>{:type=>:time}}
1667
1602
  m = @c.new
1668
1603
  y = Time.parse('10:20:30')
1669
1604
  m.x = {:hour=>10, :minute=>20, :second=>30}
@@ -1673,7 +1608,7 @@ describe Sequel::Model, "typecasting" do
1673
1608
  end
1674
1609
 
1675
1610
  specify "should raise an error if invalid data is used in a time field" do
1676
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1611
+ @c.db_schema = {:x=>{:type=>:time}}
1677
1612
  proc{@c.new.x = '0000'}.should raise_error
1678
1613
  proc{@c.new.x = Date.parse('2008-10-21')}.should raise_error(Sequel::InvalidValue)
1679
1614
  proc{@c.new.x = DateTime.parse('2008-10-21')}.should raise_error(Sequel::InvalidValue)
@@ -1681,14 +1616,14 @@ describe Sequel::Model, "typecasting" do
1681
1616
 
1682
1617
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid time" do
1683
1618
  @c.raise_on_typecast_failure = false
1684
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1619
+ @c.db_schema = {:x=>{:type=>:time}}
1685
1620
  model = @c.new
1686
1621
  model.x = '0000'
1687
1622
  model.x.should == '0000'
1688
1623
  end
1689
1624
 
1690
1625
  specify "should convert to the Sequel.datetime_class for a datetime field" do
1691
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1626
+ @c.db_schema = {:x=>{:type=>:datetime}}
1692
1627
  m = @c.new
1693
1628
  x = '2007-10-21T10:20:30-07:00'
1694
1629
  y = Time.parse(x)
@@ -1713,7 +1648,7 @@ describe Sequel::Model, "typecasting" do
1713
1648
  end
1714
1649
 
1715
1650
  specify "should accept a hash with symbol or string keys for a datetime field" do
1716
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1651
+ @c.db_schema = {:x=>{:type=>:datetime}}
1717
1652
  m = @c.new
1718
1653
  y = Time.parse('2007-10-21 10:20:30')
1719
1654
  m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
@@ -1729,7 +1664,7 @@ describe Sequel::Model, "typecasting" do
1729
1664
  end
1730
1665
 
1731
1666
  specify "should raise an error if invalid data is used in a datetime field" do
1732
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1667
+ @c.db_schema = {:x=>{:type=>:datetime}}
1733
1668
  proc{@c.new.x = '0000'}.should raise_error(Sequel::InvalidValue)
1734
1669
  Sequel.datetime_class = DateTime
1735
1670
  proc{@c.new.x = '0000'}.should raise_error(Sequel::InvalidValue)
@@ -1738,7 +1673,7 @@ describe Sequel::Model, "typecasting" do
1738
1673
 
1739
1674
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid datetime" do
1740
1675
  @c.raise_on_typecast_failure = false
1741
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1676
+ @c.db_schema = {:x=>{:type=>:datetime}}
1742
1677
  model = @c.new
1743
1678
  model.x = '0000'
1744
1679
  model.x.should == '0000'
@@ -1756,11 +1691,7 @@ describe "Model#lock!" do
1756
1691
  @c = Class.new(Sequel::Model(:items)) do
1757
1692
  columns :id
1758
1693
  end
1759
- ds = @c.dataset
1760
- def ds.fetch_rows(sql)
1761
- db.execute(sql)
1762
- yield({:id=>1})
1763
- end
1694
+ @c.dataset._fetch = {:id=>1}
1764
1695
  MODEL_DB.reset
1765
1696
  end
1766
1697