sequel 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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