~ubuntu-branches/ubuntu/vivid/ruby-sequel/vivid

« back to all changes in this revision

Viewing changes to spec/model/record_spec.rb

  • Committer: Package Import Robot
  • Author(s): Dmitry Borodaenko, Dmitry Borodaenko, Cédric Boutillier
  • Date: 2013-08-10 18:38:17 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20130810183817-iqanz804j32i5myi
Tags: 4.1.1-1
[ Dmitry Borodaenko ]
* New upstream release.
* Standards-Version upgraded to 3.9.4 (no changes).
* Added Build-Depend on ruby-sqlite3.

[ Cédric Boutillier ]
* debian/control: remove obsolete DM-Upload-Allowed flag.
* use canonical URI in Vcs-* fields.
* debian/copyright: use DEP5 copyright-format/1.0 official URL for Format
  field.
* Update debian/watch. Thanks Bart Martens.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
 
3
describe "Model#values" do
 
4
  before do
 
5
    @c = Class.new(Sequel::Model(:items))
 
6
  end
 
7
 
 
8
  it "should return the hash of model values" do
 
9
    hash = {:x=>1}
 
10
    @c.load(hash).values.should equal(hash)
 
11
  end
 
12
 
 
13
  it "should be aliased as to_hash" do
 
14
    hash = {:x=>1}
 
15
    @c.load(hash).to_hash.should equal(hash)
 
16
  end
 
17
end
 
18
 
3
19
describe "Model#save server use" do
4
20
  before do
5
21
    @db = Sequel.mock(:autoid=>proc{|sql| 10}, :fetch=>{:x=>1, :id=>10}, :servers=>{:blah=>{}, :read_only=>{}})
27
43
      columns :id, :x, :y
28
44
    end
29
45
    @c.instance_dataset.autoid = @c.dataset.autoid = 13
30
 
    MODEL_DB.reset
 
46
    DB.reset
31
47
  end
32
48
  
33
49
  it "should insert a record for a new model instance" do
34
50
    o = @c.new(:x => 1)
35
51
    o.save
36
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 13) LIMIT 1"]
 
52
    DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 13) LIMIT 1"]
37
53
  end
38
54
 
39
55
  it "should use dataset's insert_select method if present" do
47
63
    o.save
48
64
    
49
65
    o.values.should == {:y=>2}
50
 
    MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2) RETURNING *"]
 
66
    DB.sqls.should == ["INSERT INTO items (y) VALUES (2) RETURNING *"]
51
67
  end
52
68
 
53
69
  it "should not use dataset's insert_select method if specific columns are selected" do
59
75
  it "should use value returned by insert as the primary key and refresh the object" do
60
76
    o = @c.new(:x => 11)
61
77
    o.save
62
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)",
 
78
    DB.sqls.should == ["INSERT INTO items (x) VALUES (11)",
63
79
      "SELECT * FROM items WHERE (id = 13) LIMIT 1"]
64
80
  end
65
81
 
66
82
  it "should allow you to skip refreshing by overridding _save_refresh" do
67
83
    @c.send(:define_method, :_save_refresh){}
68
84
    @c.create(:x => 11)
69
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
 
85
    DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
70
86
  end
71
87
 
72
88
  it "should work correctly for inserting a record without a primary key" do
73
89
    @c.no_primary_key
74
90
    o = @c.new(:x => 11)
75
91
    o.save
76
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
 
92
    DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
77
93
  end
78
94
 
79
95
  it "should set the autoincrementing_primary_key value to the value returned by insert" do
80
96
    @c.unrestrict_primary_key
81
97
    @c.set_primary_key [:x, :y]
82
98
    o = @c.new(:x => 11)
83
 
    o.meta_def(:autoincrementing_primary_key){:y}
 
99
    def o.autoincrementing_primary_key() :y end
84
100
    o.save
85
 
    sqls = MODEL_DB.sqls
 
101
    sqls = DB.sqls
86
102
    sqls.length.should == 2
87
103
    sqls.first.should == "INSERT INTO items (x) VALUES (11)"
88
104
    sqls.last.should =~ %r{SELECT \* FROM items WHERE \(\([xy] = 1[13]\) AND \([xy] = 1[13]\)\) LIMIT 1}
91
107
  it "should update a record for an existing model instance" do
92
108
    o = @c.load(:id => 3, :x => 1)
93
109
    o.save
94
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 1 WHERE (id = 3)"]
 
110
    DB.sqls.should == ["UPDATE items SET x = 1 WHERE (id = 3)"]
95
111
  end
96
112
  
97
113
  it "should raise a NoExistingObject exception if the dataset update call doesn't return 1, unless require_modification is false" do
111
127
    proc{o.save}.should_not raise_error
112
128
  end
113
129
  
114
 
  it "should update only the given columns if given" do
 
130
  it "should respect the :columns option to specify the columns to save" do
115
131
    o = @c.load(:id => 3, :x => 1, :y => nil)
116
 
    o.save(:y)
117
 
    MODEL_DB.sqls.first.should == "UPDATE items SET y = NULL WHERE (id = 3)"
 
132
    o.save(:columns=>:y)
 
133
    DB.sqls.first.should == "UPDATE items SET y = NULL WHERE (id = 3)"
118
134
  end
119
135
  
120
136
  it "should mark saved columns as not changed" do
121
137
    o = @c.load(:id => 3, :x => 1, :y => nil)
122
138
    o[:y] = 4
123
139
    o.changed_columns.should == [:y]
124
 
    o.save(:x)
 
140
    o.save(:columns=>:x)
125
141
    o.changed_columns.should == [:y]
126
 
    o.save(:y)
 
142
    o.save(:columns=>:y)
127
143
    o.changed_columns.should == []
128
144
  end
129
145
  
136
152
  end
137
153
  
138
154
  it "should mark all columns as not changed if this is a new record and insert_select was used" do
139
 
    @c.dataset.meta_def(:insert_select){|h| h.merge(:id=>1)}
 
155
    def (@c.dataset).insert_select(h) h.merge(:id=>1) end
140
156
    o = @c.new(:x => 1, :y => nil)
141
157
    o.x = 4
142
158
    o.changed_columns.should == [:x]
166
182
    o = @c.load(:id => 23,:x => 2, :y => nil)
167
183
    o[:x] = 2
168
184
    o[:y] = 22
169
 
    o.save(:x)
 
185
    o.save(:columns=>:x)
170
186
    res.should == [{:x=>2},nil]
171
187
    o.after_save
172
188
    res.should == [nil, nil]
174
190
  
175
191
  it "should use Model's use_transactions setting by default" do
176
192
    @c.use_transactions = true
177
 
    @c.load(:id => 3, :x => 1, :y => nil).save(:y)
178
 
    MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
 
193
    @c.load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
 
194
    DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
179
195
    @c.use_transactions = false
180
 
    @c.load(:id => 3, :x => 1, :y => nil).save(:y)
181
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
 
196
    @c.load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
 
197
    DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
182
198
  end
183
199
 
184
200
  it "should inherit Model's use_transactions setting" do
185
201
    @c.use_transactions = true
186
 
    Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
187
 
    MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
 
202
    Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
 
203
    DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
188
204
    @c.use_transactions = false
189
 
    Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
190
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
 
205
    Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
 
206
    DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
191
207
  end
192
208
 
193
209
  it "should use object's use_transactions setting" do
194
210
    o = @c.load(:id => 3, :x => 1, :y => nil)
195
211
    o.use_transactions = false
196
212
    @c.use_transactions = true
197
 
    o.save(:y)
198
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
 
213
    o.save(:columns=>:y)
 
214
    DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
199
215
    o = @c.load(:id => 3, :x => 1, :y => nil)
200
216
    o.use_transactions = true
201
217
    @c.use_transactions = false 
202
 
    o.save(:y)
203
 
    MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
 
218
    o.save(:columns=>:y)
 
219
    DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
204
220
  end
205
221
 
206
222
  it "should use :transaction option if given" do
207
223
    o = @c.load(:id => 3, :x => 1, :y => nil)
208
224
    o.use_transactions = true
209
 
    o.save(:y, :transaction=>false)
210
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
 
225
    o.save(:columns=>:y, :transaction=>false)
 
226
    DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
211
227
    o = @c.load(:id => 3, :x => 1, :y => nil)
212
228
    o.use_transactions = false
213
 
    o.save(:y, :transaction=>true)
214
 
    MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
 
229
    o.save(:columns=>:y, :transaction=>true)
 
230
    DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
215
231
  end
216
232
 
217
233
  it "should rollback if before_save returns false and raise_on_save_failure = true" do
221
237
    def o.before_save
222
238
      false
223
239
    end
224
 
    proc { o.save(:y) }.should raise_error(Sequel::BeforeHookFailed)
225
 
    MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
 
240
    proc { o.save(:columns=>:y) }.should raise_error(Sequel::BeforeHookFailed)
 
241
    DB.sqls.should == ["BEGIN", "ROLLBACK"]
226
242
  end
227
243
 
228
244
  it "should rollback if before_save returns false and :raise_on_failure option is true" do
232
248
    def o.before_save
233
249
      false
234
250
    end
235
 
    proc { o.save(:y, :raise_on_failure => true) }.should raise_error(Sequel::BeforeHookFailed)
236
 
    MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
 
251
    proc { o.save(:columns=>:y, :raise_on_failure => true) }.should raise_error(Sequel::BeforeHookFailed)
 
252
    DB.sqls.should == ["BEGIN", "ROLLBACK"]
237
253
  end
238
254
 
239
255
  it "should not rollback outer transactions if before_save returns false and raise_on_save_failure = false" do
243
259
    def o.before_save
244
260
      false
245
261
    end
246
 
    MODEL_DB.transaction do
247
 
      o.save(:y).should == nil
248
 
      MODEL_DB.run "BLAH"
 
262
    DB.transaction do
 
263
      o.save(:columns=>:y).should == nil
 
264
      DB.run "BLAH"
249
265
    end
250
 
    MODEL_DB.sqls.should == ["BEGIN", "BLAH", "COMMIT"]
 
266
    DB.sqls.should == ["BEGIN", "BLAH", "COMMIT"]
251
267
  end
252
268
 
253
269
  it "should rollback if before_save returns false and raise_on_save_failure = false" do
257
273
    def o.before_save
258
274
      false
259
275
    end
260
 
    o.save(:y).should == nil
261
 
    MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
 
276
    o.save(:columns=>:y).should == nil
 
277
    DB.sqls.should == ["BEGIN", "ROLLBACK"]
262
278
  end
263
279
 
264
280
  it "should not rollback if before_save throws Rollback and use_transactions = false" do
267
283
    def o.before_save
268
284
      raise Sequel::Rollback
269
285
    end
270
 
    proc { o.save(:y) }.should raise_error(Sequel::Rollback)
271
 
    MODEL_DB.sqls.should == []
 
286
    proc { o.save(:columns=>:y) }.should raise_error(Sequel::Rollback)
 
287
    DB.sqls.should == []
272
288
  end
273
289
 
274
290
  it "should support a :server option to set the server/shard to use" do
341
357
      end
342
358
    end
343
359
    @o = Album.load(:id=>1).freeze
344
 
    MODEL_DB.sqls
 
360
    DB.sqls
345
361
  end
346
362
  after do
347
363
    Object.send(:remove_const, :Album)
351
367
    @o.frozen?.should be_true
352
368
  end
353
369
 
 
370
  it "should freeze the object if the model doesn't have a primary key" do
 
371
    Album.no_primary_key
 
372
    @o = Album.load(:id=>1).freeze
 
373
    @o.frozen?.should be_true
 
374
  end
 
375
 
354
376
  it "should freeze the object's values, associations, changed_columns, errors, and this" do
355
377
    @o.values.frozen?.should be_true
356
378
    @o.changed_columns.frozen?.should be_true
417
439
  end
418
440
end
419
441
 
420
 
describe "Model#modified[!?]" do
 
442
describe "Model#modified?" do
421
443
  before do
422
444
    @c = Class.new(Sequel::Model(:items))
423
445
    @c.class_eval do
424
446
      columns :id, :x
425
447
      @db_schema = {:x => {:type => :integer}}
426
448
    end
427
 
    MODEL_DB.reset
 
449
    DB.reset
428
450
  end
429
451
  
430
452
  it "should be true if the object is new" do
467
489
    o.x = '2'
468
490
    o.modified?.should == true
469
491
  end
470
 
end
471
 
 
 
492
 
 
493
  it "should be true if given a column argument and the column has been changed" do
 
494
    o = @c.new
 
495
    o.modified?(:id).should be_false
 
496
    o.id = 1
 
497
    o.modified?(:id).should be_true
 
498
  end
 
499
end
 
500
 
 
501
describe "Model#modified!" do
 
502
  before do
 
503
    @c = Class.new(Sequel::Model(:items))
 
504
    @c.class_eval do
 
505
      columns :id, :x
 
506
    end
 
507
    DB.reset
 
508
  end
 
509
 
 
510
  it "should mark the object as modified so that save_changes still runs the callbacks" do
 
511
    o = @c.load(:id=>1, :x=>2)
 
512
    def o.after_save
 
513
      values[:x] = 3
 
514
    end
 
515
    o.update({})
 
516
    o.x.should == 2
 
517
 
 
518
    o.modified!
 
519
    o.update({})
 
520
    o.x.should == 3
 
521
    o.db.sqls.should == []
 
522
  end
 
523
 
 
524
  it "should mark given column argument as modified" do
 
525
    o = @c.load(:id=>1, :x=>2)
 
526
    o.modified!(:x)
 
527
    o.changed_columns.should == [:x]
 
528
    o.save
 
529
    o.db.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 1)"]
 
530
  end
 
531
end
 
532
  
472
533
describe "Model#save_changes" do
473
534
  before do
474
535
    @c = Class.new(Sequel::Model(:items)) do
475
536
      unrestrict_primary_key
476
537
      columns :id, :x, :y
477
538
    end
478
 
    MODEL_DB.reset
 
539
    DB.reset
479
540
  end
480
541
  
481
542
  it "should always save if the object is new" do
482
543
    o = @c.new(:x => 1)
483
544
    o.save_changes
484
 
    MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
 
545
    DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
485
546
  end
486
547
 
487
548
  it "should take options passed to save" do
488
549
    o = @c.new(:x => 1)
489
550
    def o.before_validation; false; end
490
551
    proc{o.save_changes}.should raise_error(Sequel::Error)
491
 
    MODEL_DB.sqls.should == []
 
552
    DB.sqls.should == []
492
553
    o.save_changes(:validate=>false)
493
 
    MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
 
554
    DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
494
555
  end
495
556
 
496
557
  it "should do nothing if no changed columns" do
497
558
    o = @c.load(:id => 3, :x => 1, :y => nil)
498
559
    o.save_changes
499
 
    MODEL_DB.sqls.should == []
 
560
    DB.sqls.should == []
500
561
  end
501
562
  
502
563
  it "should do nothing if modified? is false" do
503
564
    o = @c.load(:id => 3, :x => 1, :y => nil)
504
565
    def o.modified?; false; end
505
566
    o.save_changes
506
 
    MODEL_DB.sqls.should == []
 
567
    DB.sqls.should == []
507
568
  end
508
569
  
509
570
  it "should update only changed columns" do
511
572
    o.x = 2
512
573
 
513
574
    o.save_changes
514
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
515
 
    o.save_changes
516
 
    o.save_changes
517
 
    MODEL_DB.sqls.should == []
 
575
    DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
 
576
    o.save_changes
 
577
    o.save_changes
 
578
    DB.sqls.should == []
518
579
 
519
580
    o.y = 4
520
581
    o.save_changes
521
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
522
 
    o.save_changes
523
 
    o.save_changes
524
 
    MODEL_DB.sqls.should == []
 
582
    DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
 
583
    o.save_changes
 
584
    o.save_changes
 
585
    DB.sqls.should == []
525
586
  end
526
587
  
527
588
  it "should not consider columns changed if the values did not change" do
529
590
    o.x = 1
530
591
 
531
592
    o.save_changes
532
 
    MODEL_DB.sqls.should == []
 
593
    DB.sqls.should == []
533
594
    o.x = 3
534
595
    o.save_changes
535
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
 
596
    DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
536
597
 
537
598
    o[:y] = nil
538
599
    o.save_changes
539
 
    MODEL_DB.sqls.should == []
 
600
    DB.sqls.should == []
540
601
    o[:y] = 4
541
602
    o.save_changes
542
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
 
603
    DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
543
604
  end
544
605
  
545
606
  it "should clear changed_columns" do
554
615
    o = @c.load(:id => 3, :x => 1, :y => nil)
555
616
    @c.send(:define_method, :before_update){self.x += 1}
556
617
    o.save_changes
557
 
    MODEL_DB.sqls.should == []
 
618
    DB.sqls.should == []
558
619
    o.x = 2
559
620
    o.save_changes
560
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
 
621
    DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
561
622
    o.save_changes
562
 
    MODEL_DB.sqls.should == []
 
623
    DB.sqls.should == []
563
624
    o.x = 4
564
625
    o.save_changes
565
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
 
626
    DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
566
627
  end
567
628
 
568
629
  it "should update columns changed in a before_save hook" do
569
630
    o = @c.load(:id => 3, :x => 1, :y => nil)
570
631
    @c.send(:define_method, :before_update){self.x += 1}
571
632
    o.save_changes
572
 
    MODEL_DB.sqls.should == []
 
633
    DB.sqls.should == []
573
634
    o.x = 2
574
635
    o.save_changes
575
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
 
636
    DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
576
637
    o.save_changes
577
 
    MODEL_DB.sqls.should == []
 
638
    DB.sqls.should == []
578
639
    o.x = 4
579
640
    o.save_changes
580
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
 
641
    DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
581
642
  end
582
643
end
583
644
 
587
648
      unrestrict_primary_key
588
649
      columns :x
589
650
    end
590
 
    MODEL_DB.reset
 
651
    DB.reset
591
652
  end
592
653
  
593
654
  it "should be true for a new instance" do
602
663
  end
603
664
end
604
665
 
605
 
describe Sequel::Model, "w/ primary key" do
606
 
  it "should default to ':id'" do
 
666
describe Sequel::Model, "with a primary key" do
 
667
  it "should default to :id" do
607
668
    model_a = Class.new Sequel::Model
608
669
    model_a.primary_key.should == :id
609
670
  end
613
674
    model_a.primary_key.should == :a
614
675
  end
615
676
 
616
 
  it "should support multi argument composite keys" do
617
 
    model_a = Class.new(Sequel::Model){ set_primary_key :a, :b }
618
 
    model_a.primary_key.should == [:a, :b]
619
 
  end
620
 
 
621
677
  it "should accept single argument composite keys" do
622
678
    model_a = Class.new(Sequel::Model){ set_primary_key [:a, :b] }
623
679
    model_a.primary_key.should == [:a, :b]
624
680
  end
625
681
end
626
682
 
627
 
describe Sequel::Model, "w/o primary key" do
 
683
describe Sequel::Model, "without a primary key" do
628
684
  it "should return nil for primary key" do
629
685
    Class.new(Sequel::Model){no_primary_key}.primary_key.should be_nil
630
686
  end
635
691
  end
636
692
end
637
693
 
638
 
describe Sequel::Model, "with this" do
 
694
describe Sequel::Model, "#this" do
639
695
  before do
640
696
    @example = Class.new(Sequel::Model(:examples))
641
697
    @example.columns :id, :a, :x, :y
654
710
  end
655
711
 
656
712
  it "should support composite primary keys" do
657
 
    @example.set_primary_key :x, :y
 
713
    @example.set_primary_key [:x, :y]
658
714
    instance = @example.load(:x => 4, :y => 5)
659
715
    instance.this.sql.should =~ /SELECT \* FROM examples WHERE \(\([xy] = [45]\) AND \([xy] = [45]\)\) LIMIT 1/
660
716
  end
666
722
    @m.columns :id, :x, :y
667
723
  end
668
724
  
669
 
  it "should be default return the value of the :id column" do
 
725
  it "should by default return the value of the :id column" do
670
726
    m = @m.load(:id => 111, :x => 2, :y => 3)
671
727
    m.pk.should == 111
672
728
  end
673
729
 
674
 
  it "should be return the primary key value for custom primary key" do
 
730
  it "should return the primary key value for custom primary key" do
675
731
    @m.set_primary_key :x
676
732
    m = @m.load(:id => 111, :x => 2, :y => 3)
677
733
    m.pk.should == 2
678
734
  end
679
735
 
680
 
  it "should be return the primary key value for composite primary key" do
 
736
  it "should return the primary key value for composite primary key" do
681
737
    @m.set_primary_key [:y, :x]
682
738
    m = @m.load(:id => 111, :x => 2, :y => 3)
683
739
    m.pk.should == [3, 2]
700
756
    @m.columns :id, :x, :y
701
757
  end
702
758
  
703
 
  it "should be default return the value of the :id column" do
 
759
  it "should by default return a hash with the value of the :id column" do
704
760
    m = @m.load(:id => 111, :x => 2, :y => 3)
705
761
    m.pk_hash.should == {:id => 111}
706
762
  end
707
763
 
708
 
  it "should be return the primary key value for custom primary key" do
 
764
  it "should return a hash with the primary key value for custom primary key" do
709
765
    @m.set_primary_key :x
710
766
    m = @m.load(:id => 111, :x => 2, :y => 3)
711
767
    m.pk_hash.should == {:x => 2}
712
768
  end
713
769
 
714
 
  it "should be return the primary key value for composite primary key" do
 
770
  it "should return a hash with the primary key values for composite primary key" do
715
771
    @m.set_primary_key [:y, :x]
716
772
    m = @m.load(:id => 111, :x => 2, :y => 3)
717
773
    m.pk_hash.should == {:y => 3, :x => 2}
737
793
    @c.strict_param_setting = false
738
794
    @o1 = @c.new
739
795
    @o2 = @c.load(:id => 5)
740
 
    MODEL_DB.reset
 
796
    DB.reset
741
797
  end
742
798
 
743
799
  it "should filter the given params using the model columns" do
744
800
    @o1.set(:x => 1, :z => 2)
745
801
    @o1.values.should == {:x => 1}
746
 
    MODEL_DB.sqls.should == []
 
802
    DB.sqls.should == []
747
803
 
748
804
    @o2.set(:y => 1, :abc => 2)
749
805
    @o2.values.should == {:y => 1, :id=> 5}
750
 
    MODEL_DB.sqls.should == []
 
806
    DB.sqls.should == []
751
807
  end
752
808
  
753
809
  it "should work with both strings and symbols" do
754
810
    @o1.set('x'=> 1, 'z'=> 2)
755
811
    @o1.values.should == {:x => 1}
756
 
    MODEL_DB.sqls.should == []
 
812
    DB.sqls.should == []
757
813
 
758
814
    @o2.set('y'=> 1, 'abc'=> 2)
759
815
    @o2.values.should == {:y => 1, :id=> 5}
760
 
    MODEL_DB.sqls.should == []
 
816
    DB.sqls.should == []
761
817
  end
762
818
  
763
819
  it "should support virtual attributes" do
764
820
    @c.send(:define_method, :blah=){|v| self.x = v}
765
821
    @o1.set(:blah => 333)
766
822
    @o1.values.should == {:x => 333}
767
 
    MODEL_DB.sqls.should == []
 
823
    DB.sqls.should == []
768
824
    @o1.set('blah'=> 334)
769
825
    @o1.values.should == {:x => 334}
770
 
    MODEL_DB.sqls.should == []
 
826
    DB.sqls.should == []
771
827
  end
772
828
  
773
829
  it "should not modify the primary key" do
774
830
    @o1.set(:x => 1, :id => 2)
775
831
    @o1.values.should == {:x => 1}
776
 
    MODEL_DB.sqls.should == []
 
832
    DB.sqls.should == []
777
833
    @o2.set('y'=> 1, 'id'=> 2)
778
834
    @o2.values.should == {:y => 1, :id=> 5}
779
 
    MODEL_DB.sqls.should == []
 
835
    DB.sqls.should == []
780
836
  end
781
837
 
782
838
  it "should return self" do
783
839
    returned_value = @o1.set(:x => 1, :z => 2)
784
840
    returned_value.should == @o1
785
 
    MODEL_DB.sqls.should == []
 
841
    DB.sqls.should == []
786
842
  end
787
843
 
788
844
  it "should raise error if strict_param_setting is true and method does not exist" do
797
853
 
798
854
  it "should raise error if strict_param_setting is true and column is restricted" do
799
855
    @o1.strict_param_setting = true
800
 
    @c.set_restricted_columns :x
 
856
    @c.set_allowed_columns
801
857
    proc{@o1.set('x' => 1)}.should raise_error(Sequel::Error)
802
858
  end
803
859
 
868
924
    @c.strict_param_setting = false
869
925
    @o1 = @c.new
870
926
    @o2 = @c.load(:id => 5)
871
 
    MODEL_DB.reset
 
927
    DB.reset
872
928
  end
873
929
  
874
930
  it "should filter the given params using the model columns" do
875
931
    @o1.update(:x => 1, :z => 2)
876
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
932
    DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
877
933
 
878
 
    MODEL_DB.reset
 
934
    DB.reset
879
935
    @o2.update(:y => 1, :abc => 2)
880
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
 
936
    DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
881
937
  end
882
938
  
883
939
  it "should support virtual attributes" do
884
940
    @c.send(:define_method, :blah=){|v| self.x = v}
885
941
    @o1.update(:blah => 333)
886
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
942
    DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
887
943
  end
888
944
  
889
945
  it "should not modify the primary key" do
890
946
    @o1.update(:x => 1, :id => 2)
891
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
892
 
    MODEL_DB.reset
 
947
    DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
948
    DB.reset
893
949
    @o2.update('y'=> 1, 'id'=> 2)
894
950
    @o2.values.should == {:y => 1, :id=> 5}
895
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
 
951
    DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
896
952
  end
897
953
end
898
954
 
902
958
      set_primary_key :id
903
959
      columns :x, :y, :z, :id
904
960
    end
905
 
    @c.strict_param_setting = true 
906
961
    @o1 = @c.new
907
 
    MODEL_DB.reset
 
962
    DB.reset
908
963
  end
909
964
 
910
965
  it "should set only the given fields" do
912
967
    @o1.values.should == {:x => 1, :y => 2}
913
968
    @o1.set_fields({:x => 9, :y => 8, :z=>6, :id=>7}, [:x, :y, :id])
914
969
    @o1.values.should == {:x => 9, :y => 8, :id=>7}
915
 
    MODEL_DB.sqls.should == []
 
970
    DB.sqls.should == []
916
971
  end
917
972
 
918
973
  it "should lookup into the hash without checking if the entry exists" do
948
1003
    @o1.values.should == {:x => 1, :y => 2}
949
1004
    @o1.set_fields({:x => 9, :y => 8, :z=>6, :id=>7}, [:x, :y, :id], :missing=>:foo)
950
1005
    @o1.values.should == {:x => 9, :y => 8, :id=>7}
951
 
    MODEL_DB.sqls.should == []
952
 
  end
953
 
 
 
1006
    DB.sqls.should == []
 
1007
  end
 
1008
 
 
1009
  it "should respect model's default_set_fields_options" do
 
1010
    @c.default_set_fields_options = {:missing=>:skip}
 
1011
    @o1.set_fields({:x => 3}, [:x, :y])
 
1012
    @o1.values.should == {:x => 3}
 
1013
    @o1.set_fields({:x => 4}, [:x, :y], {})
 
1014
    @o1.values.should == {:x => 4}
 
1015
    proc{@o1.set_fields({:x => 3}, [:x, :y], :missing=>:raise)}.should raise_error(Sequel::Error)
 
1016
    @c.default_set_fields_options = {:missing=>:raise}
 
1017
    proc{@o1.set_fields({:x => 3}, [:x, :y])}.should raise_error(Sequel::Error)
 
1018
    proc{@o1.set_fields({:x => 3}, [:x, :y], {})}.should raise_error(Sequel::Error)
 
1019
    @o1.set_fields({:x => 5}, [:x, :y], :missing=>:skip)
 
1020
    @o1.values.should == {:x => 5}
 
1021
    @o1.set_fields({:x => 5}, [:x, :y], :missing=>nil)
 
1022
    @o1.values.should == {:x => 5, :y=>nil}
 
1023
    DB.sqls.should == []
 
1024
  end
 
1025
 
 
1026
  it "should respect model's default_set_fields_options in a subclass" do
 
1027
    @c.default_set_fields_options = {:missing=>:skip}
 
1028
    o = Class.new(@c).new
 
1029
    o.set_fields({:x => 3}, [:x, :y])
 
1030
    o.values.should == {:x => 3}
 
1031
  end
954
1032
end
955
1033
 
956
1034
describe Sequel::Model, "#update_fields" do
961
1039
    end
962
1040
    @c.strict_param_setting = true 
963
1041
    @o1 = @c.load(:id=>1)
964
 
    MODEL_DB.reset
 
1042
    DB.reset
965
1043
  end
966
1044
 
967
1045
  it "should set only the given fields, and then save the changes to the record" do
968
1046
    @o1.update_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
969
1047
    @o1.values.should == {:x => 1, :y => 2, :id=>1}
970
 
    sqls = MODEL_DB.sqls
 
1048
    sqls = DB.sqls
971
1049
    sqls.pop.should =~ /UPDATE items SET [xy] = [12], [xy] = [12] WHERE \(id = 1\)/
972
1050
    sqls.should == []
973
1051
 
974
1052
    @o1.update_fields({:x => 1, :y => 5, :z=>6, :id=>7}, [:x, :y])
975
1053
    @o1.values.should == {:x => 1, :y => 5, :id=>1}
976
 
    MODEL_DB.sqls.should == ["UPDATE items SET y = 5 WHERE (id = 1)"]
 
1054
    DB.sqls.should == ["UPDATE items SET y = 5 WHERE (id = 1)"]
977
1055
  end
978
1056
 
979
1057
  it "should support :missing=>:skip option" do
980
1058
    @o1.update_fields({:x => 1, :z=>3, :id=>4}, [:x, :y], :missing=>:skip)
981
1059
    @o1.values.should == {:x => 1, :id=>1}
982
 
    MODEL_DB.sqls.should == ["UPDATE items SET x = 1 WHERE (id = 1)"]
 
1060
    DB.sqls.should == ["UPDATE items SET x = 1 WHERE (id = 1)"]
983
1061
  end
984
1062
 
985
1063
  it "should support :missing=>:raise option" do
986
1064
    proc{@o1.update_fields({:x => 1}, [:x, :y], :missing=>:raise)}.should raise_error(Sequel::Error)
987
1065
  end
 
1066
 
 
1067
  it "should respect model's default_set_fields_options" do
 
1068
    @c.default_set_fields_options = {:missing=>:skip}
 
1069
    @o1.update_fields({:x => 3}, [:x, :y])
 
1070
    @o1.values.should == {:x => 3, :id=>1}
 
1071
    DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 1)"]
 
1072
 
 
1073
    @c.default_set_fields_options = {:missing=>:raise}
 
1074
    proc{@o1.update_fields({:x => 3}, [:x, :y])}.should raise_error(Sequel::Error)
 
1075
    DB.sqls.should == []
 
1076
  end
988
1077
end
989
1078
 
990
 
describe Sequel::Model, "#(set|update)_(all|except|only)" do
 
1079
describe Sequel::Model, "#(set|update)_(all|only)" do
991
1080
  before do
992
1081
    @c = Class.new(Sequel::Model(:items)) do
993
1082
      set_primary_key :id
994
1083
      columns :x, :y, :z, :id
995
1084
      set_allowed_columns :x
996
 
      set_restricted_columns :y
997
1085
    end
998
1086
    @c.strict_param_setting = false
999
1087
    @o1 = @c.new
1000
 
    MODEL_DB.reset
 
1088
    DB.reset
1001
1089
  end
1002
1090
 
1003
1091
  it "should raise errors if not all hash fields can be set and strict_param_setting is true" do
1004
1092
    @c.strict_param_setting = true
1005
1093
 
1006
 
    proc{@c.new.set_all(:x => 1, :y => 2, :z=>3, :id=>4)}.should raise_error(Sequel::Error)
 
1094
    proc{@c.new.set_all(:x => 1, :y => 2, :z=>3, :use_after_commit_rollback => false)}.should raise_error(Sequel::Error)
1007
1095
    (o = @c.new).set_all(:x => 1, :y => 2, :z=>3)
1008
1096
    o.values.should == {:x => 1, :y => 2, :z=>3}
1009
1097
 
1011
1099
    proc{@c.new.set_only({:x => 1, :y => 2, :z=>3}, :x, :y)}.should raise_error(Sequel::Error)
1012
1100
    (o = @c.new).set_only({:x => 1, :y => 2}, :x, :y)
1013
1101
    o.values.should == {:x => 1, :y => 2}
1014
 
 
1015
 
    proc{@c.new.set_except({:x => 1, :y => 2, :z=>3, :id=>4}, :x, :y)}.should raise_error(Sequel::Error)
1016
 
    proc{@c.new.set_except({:x => 1, :y => 2, :z=>3}, :x, :y)}.should raise_error(Sequel::Error)
1017
 
    (o = @c.new).set_except({:z => 3}, :x, :y)
1018
 
    o.values.should == {:z=>3}
1019
1102
  end
1020
1103
 
1021
 
  it "#set_all should set all attributes except the primary key" do
 
1104
  it "#set_all should set all attributes including the primary key" do
1022
1105
    @o1.set_all(:x => 1, :y => 2, :z=>3, :id=>4)
1023
 
    @o1.values.should == {:x => 1, :y => 2, :z=>3}
 
1106
    @o1.values.should == {:id =>4, :x => 1, :y => 2, :z=>3}
 
1107
  end
 
1108
 
 
1109
  it "#set_all should set not set restricted fields" do
 
1110
    @o1.set_all(:x => 1, :use_after_commit_rollback => false)
 
1111
    @o1.use_after_commit_rollback.should be_true
 
1112
    @o1.values.should == {:x => 1}
1024
1113
  end
1025
1114
 
1026
1115
  it "#set_only should only set given attributes" do
1032
1121
    @o1.values.should == {:x => 9, :y => 8, :id=>7}
1033
1122
  end
1034
1123
 
1035
 
  it "#set_except should not set given attributes or the primary key" do
1036
 
    @o1.set_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
1037
 
    @o1.values.should == {:x => 1}
1038
 
    @o1.set_except({:x => 4, :y => 2, :z=>3, :id=>4}, :y, :z)
1039
 
    @o1.values.should == {:x => 4}
1040
 
  end
1041
 
 
1042
1124
  it "#update_all should update all attributes" do
1043
 
    @c.new.update_all(:x => 1, :id=>4)
1044
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1045
 
    @c.new.update_all(:y => 1, :id=>4)
1046
 
    MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1047
 
    @c.new.update_all(:z => 1, :id=>4)
1048
 
    MODEL_DB.sqls.should == ["INSERT INTO items (z) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1125
    @c.new.update_all(:x => 1)
 
1126
    DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1127
    @c.new.update_all(:y => 1)
 
1128
    DB.sqls.should == ["INSERT INTO items (y) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1129
    @c.new.update_all(:z => 1)
 
1130
    DB.sqls.should == ["INSERT INTO items (z) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1049
1131
  end
1050
1132
 
1051
1133
  it "#update_only should only update given attributes" do
1052
1134
    @o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
1053
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1135
    DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1054
1136
    @c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
1055
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1056
 
  end
1057
 
 
1058
 
  it "#update_except should not update given attributes" do
1059
 
    @o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
1060
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1061
 
    @c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
1062
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1137
    DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1063
1138
  end
1064
1139
end
1065
1140
 
1066
1141
describe Sequel::Model, "#destroy with filtered dataset" do
1067
1142
  before do
1068
 
    @model = Class.new(Sequel::Model(MODEL_DB[:items].where(:a=>1)))
 
1143
    @model = Class.new(Sequel::Model(DB[:items].where(:a=>1)))
1069
1144
    @model.columns :id, :a
1070
1145
    @instance = @model.load(:id => 1234)
1071
 
    MODEL_DB.reset
 
1146
    DB.reset
1072
1147
  end
1073
1148
 
1074
1149
  it "should raise a NoExistingObject exception if the dataset delete call doesn't return 1" do
1075
 
    @instance.this.meta_def(:execute_dui){|*a| 0}
1076
 
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
1077
 
    @instance.this.meta_def(:execute_dui){|*a| 2}
1078
 
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
1079
 
    @instance.this.meta_def(:execute_dui){|*a| 1}
 
1150
    def (@instance.this).execute_dui(*a) 0 end
 
1151
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
 
1152
    def (@instance.this).execute_dui(*a) 2 end
 
1153
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
 
1154
    def (@instance.this).execute_dui(*a) 1 end
1080
1155
    proc{@instance.delete}.should_not raise_error
1081
1156
    
1082
1157
    @instance.require_modification = false
1083
 
    @instance.this.meta_def(:execute_dui){|*a| 0}
 
1158
    def (@instance.this).execute_dui(*a) 0 end
1084
1159
    proc{@instance.delete}.should_not raise_error
1085
 
    @instance.this.meta_def(:execute_dui){|*a| 2}
 
1160
    def (@instance.this).execute_dui(*a) 2 end
1086
1161
    proc{@instance.delete}.should_not raise_error
1087
1162
  end
1088
1163
 
1089
1164
  it "should include WHERE clause when deleting" do
1090
1165
    @instance.destroy
1091
 
    MODEL_DB.sqls.should == ["DELETE FROM items WHERE ((a = 1) AND (id = 1234))"]
 
1166
    DB.sqls.should == ["DELETE FROM items WHERE ((a = 1) AND (id = 1234))"]
1092
1167
  end
1093
1168
end
1094
1169
 
1097
1172
    @model = Class.new(Sequel::Model(:items))
1098
1173
    @model.columns :id
1099
1174
    @instance = @model.load(:id => 1234)
1100
 
    MODEL_DB.reset
 
1175
    DB.reset
1101
1176
  end
1102
1177
 
1103
1178
  it "should return self" do
1106
1181
  end
1107
1182
  
1108
1183
  it "should raise a NoExistingObject exception if the dataset delete call doesn't return 1" do
1109
 
    @model.dataset.meta_def(:execute_dui){|*a| 0}
1110
 
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
1111
 
    @model.dataset.meta_def(:execute_dui){|*a| 2}
1112
 
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
1113
 
    @model.dataset.meta_def(:execute_dui){|*a| 1}
 
1184
    def (@model.dataset).execute_dui(*a) 0 end
 
1185
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
 
1186
    def (@model.dataset).execute_dui(*a) 2 end
 
1187
    proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
 
1188
    def (@model.dataset).execute_dui(*a) 1 end
1114
1189
    proc{@instance.delete}.should_not raise_error
1115
1190
    
1116
1191
    @instance.require_modification = false
1117
 
    @model.dataset.meta_def(:execute_dui){|*a| 0}
 
1192
    def (@model.dataset).execute_dui(*a) 0 end
1118
1193
    proc{@instance.delete}.should_not raise_error
1119
 
    @model.dataset.meta_def(:execute_dui){|*a| 2}
 
1194
    def (@model.dataset).execute_dui(*a) 2 end
1120
1195
    proc{@instance.delete}.should_not raise_error
1121
1196
  end
1122
1197
 
1123
1198
  it "should run within a transaction if use_transactions is true" do
1124
1199
    @instance.use_transactions = true
1125
1200
    @instance.destroy
1126
 
    MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
 
1201
    DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
1127
1202
  end
1128
1203
 
1129
1204
  it "should not run within a transaction if use_transactions is false" do
1130
1205
    @instance.use_transactions = false
1131
1206
    @instance.destroy
1132
 
    MODEL_DB.sqls.should == ["DELETE FROM items WHERE id = 1234"]
 
1207
    DB.sqls.should == ["DELETE FROM items WHERE id = 1234"]
1133
1208
  end
1134
1209
 
1135
1210
  it "should run within a transaction if :transaction option is true" do
1136
1211
    @instance.use_transactions = false
1137
1212
    @instance.destroy(:transaction => true)
1138
 
    MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
 
1213
    DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
1139
1214
  end
1140
1215
 
1141
1216
  it "should not run within a transaction if :transaction option is false" do
1142
1217
    @instance.use_transactions = true
1143
1218
    @instance.destroy(:transaction => false)
1144
 
    MODEL_DB.sqls.should == ["DELETE FROM items WHERE id = 1234"]
 
1219
    DB.sqls.should == ["DELETE FROM items WHERE id = 1234"]
1145
1220
  end
1146
1221
 
1147
1222
  it "should run before_destroy and after_destroy hooks" do
1148
 
    @model.send(:define_method, :before_destroy){MODEL_DB.execute('before blah')}
1149
 
    @model.send(:define_method, :after_destroy){MODEL_DB.execute('after blah')}
 
1223
    @model.send(:define_method, :before_destroy){DB.execute('before blah')}
 
1224
    @model.send(:define_method, :after_destroy){DB.execute('after blah')}
1150
1225
    @instance.destroy
1151
 
    MODEL_DB.sqls.should == ["before blah", "DELETE FROM items WHERE id = 1234", "after blah"]
 
1226
    DB.sqls.should == ["before blah", "DELETE FROM items WHERE id = 1234", "after blah"]
1152
1227
  end
1153
1228
end
1154
1229
 
1156
1231
  before do
1157
1232
    @model = Class.new(Sequel::Model(:items))
1158
1233
    @model.instance_dataset._fetch = @model.dataset._fetch = proc{|sql| {:x=>1} if sql =~ /id = 1/}
1159
 
    MODEL_DB.reset
 
1234
    DB.reset
1160
1235
  end
1161
1236
 
1162
1237
  it "should do a query to check if the record exists" do
1163
1238
    @model.load(:id=>1).exists?.should be_true
1164
 
    MODEL_DB.sqls.should == ['SELECT 1 FROM items WHERE (id = 1) LIMIT 1']
 
1239
    DB.sqls.should == ['SELECT 1 AS one FROM items WHERE (id = 1) LIMIT 1']
1165
1240
  end
1166
1241
 
1167
1242
  it "should return false when #this.count == 0" do
1168
1243
    @model.load(:id=>2).exists?.should be_false
1169
 
    MODEL_DB.sqls.should == ['SELECT 1 FROM items WHERE (id = 2) LIMIT 1']
 
1244
    DB.sqls.should == ['SELECT 1 AS one FROM items WHERE (id = 2) LIMIT 1']
1170
1245
  end
1171
1246
 
1172
1247
  it "should return false without issuing a query if the model object is new" do
1173
1248
    @model.new.exists?.should be_false
1174
 
    MODEL_DB.sqls.should == []
 
1249
    DB.sqls.should == []
1175
1250
  end
1176
1251
end
1177
1252
 
1288
1363
  specify "should be the same only for objects with the same class and pk if pk is composite and all values are non-NULL" do
1289
1364
    z = Class.new(Sequel::Model)
1290
1365
    z.columns :id, :id2, :x
1291
 
    z.set_primary_key(:id, :id2)
 
1366
    z.set_primary_key([:id, :id2])
1292
1367
    y = Class.new(Sequel::Model)
1293
1368
    y.columns :id, :id2, :x
1294
 
    y.set_primary_key(:id, :id2)
 
1369
    y.set_primary_key([:id, :id2])
1295
1370
    a = z.load(:id => 1, :id2=>2, :x => 3)
1296
1371
    
1297
1372
    a.hash.should == z.load(:id => 1, :id2=>2, :x => 4).hash
1302
1377
  specify "should be the same only for objects with the same class and value if pk is composite and one values is NULL" do
1303
1378
    z = Class.new(Sequel::Model)
1304
1379
    z.columns :id, :id2, :x
1305
 
    z.set_primary_key(:id, :id2)
 
1380
    z.set_primary_key([:id, :id2])
1306
1381
    y = Class.new(Sequel::Model)
1307
1382
    y.columns :id, :id2, :x
1308
 
    y.set_primary_key(:id, :id2)
 
1383
    y.set_primary_key([:id, :id2])
1309
1384
 
1310
1385
    a = z.load(:id => 1, :id2 => nil, :x => 3)
1311
1386
    a.hash.should == z.load(:id => 1, :id2=>nil, :x => 3).hash
1414
1489
 
1415
1490
describe Sequel::Model, ".create" do
1416
1491
  before do
1417
 
    MODEL_DB.reset
 
1492
    DB.reset
1418
1493
    @c = Class.new(Sequel::Model(:items)) do
1419
1494
      unrestrict_primary_key
1420
1495
      columns :x
1424
1499
  it "should be able to create rows in the associated table" do
1425
1500
    o = @c.create(:x => 1)
1426
1501
    o.class.should == @c
1427
 
    MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1502
    DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1428
1503
  end
1429
1504
 
1430
1505
  it "should be able to create rows without any values specified" do
1431
1506
    o = @c.create
1432
1507
    o.class.should == @c
1433
 
    MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1508
    DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1434
1509
  end
1435
1510
 
1436
 
  it "should accept a block and run it" do
 
1511
  it "should accept a block and call it" do
1437
1512
    o1, o2, o3 =  nil, nil, nil
1438
1513
    o = @c.create {|o4| o1 = o4; o3 = o4; o2 = :blah; o3.x = 333}
1439
1514
    o.class.should == @c
1440
1515
    o1.should === o
1441
1516
    o3.should === o
1442
1517
    o2.should == :blah
1443
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
 
1518
    DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1444
1519
  end
1445
1520
  
1446
1521
  it "should create a row for a model with custom primary key" do
1447
1522
    @c.set_primary_key :x
1448
1523
    o = @c.create(:x => 30)
1449
1524
    o.class.should == @c
1450
 
    MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (30)", "SELECT * FROM items WHERE (x = 30) LIMIT 1"]
 
1525
    DB.sqls.should == ["INSERT INTO items (x) VALUES (30)", "SELECT * FROM items WHERE (x = 30) LIMIT 1"]
1451
1526
  end
1452
1527
end
1453
1528
 
1457
1532
      unrestrict_primary_key
1458
1533
      columns :id, :x
1459
1534
    end
1460
 
    MODEL_DB.reset
 
1535
    DB.reset
1461
1536
  end
1462
1537
 
1463
1538
  specify "should reload the instance values from the database" do
1466
1541
    @c.instance_dataset._fetch = @c.dataset._fetch = {:x => 'kaboom', :id => 555}
1467
1542
    @m.refresh
1468
1543
    @m[:x].should == 'kaboom'
1469
 
    MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
 
1544
    DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1470
1545
  end
1471
1546
  
1472
1547
  specify "should raise if the instance is not found" do
1473
1548
    @m = @c.new(:id => 555)
1474
1549
    @c.instance_dataset._fetch =@c.dataset._fetch = []
1475
1550
    proc {@m.refresh}.should raise_error(Sequel::Error)
1476
 
    MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
 
1551
    DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1477
1552
  end
1478
1553
  
1479
1554
  specify "should be aliased by #reload" do
1481
1556
    @c.instance_dataset._fetch =@c.dataset._fetch = {:x => 'kaboom', :id => 555}
1482
1557
    @m.reload
1483
1558
    @m[:x].should == 'kaboom'
1484
 
    MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
 
1559
    DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1485
1560
  end
1486
1561
end
1487
1562
 
1491
1566
      columns :x
1492
1567
    end
1493
1568
    @c.db_schema = {:x=>{:type=>:integer}}
1494
 
    MODEL_DB.reset
 
1569
    @c.raise_on_typecast_failure = true
 
1570
    DB.reset
1495
1571
  end
1496
1572
 
1497
1573
  after do
1626
1702
    m.x.should == bd
1627
1703
    m.x = bd
1628
1704
    m.x.should == bd
 
1705
    m.x = '0'
 
1706
    m.x.should == 0
1629
1707
  end
1630
1708
 
1631
1709
  specify "should raise an error if invalid data is used in an decimal field" do
1632
1710
    @c.db_schema = {:x=>{:type=>:decimal}}
1633
1711
    proc{@c.new.x = Date.today}.should raise_error(Sequel::InvalidValue)
 
1712
    proc{@c.new.x = 'foo'}.should raise_error(Sequel::InvalidValue)
1634
1713
  end
1635
1714
 
1636
1715
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1847
1926
      columns :id
1848
1927
    end
1849
1928
    @c.dataset._fetch = {:id=>1}
1850
 
    MODEL_DB.reset
 
1929
    DB.reset
1851
1930
  end
1852
1931
  
1853
1932
  it "should do nothing if the record is a new record" do
1854
1933
    o = @c.new
1855
 
    called = false
1856
 
    o.meta_def(:_refresh){|x| called = true; super(x)}
 
1934
    def o._refresh(x) raise Sequel::Error; super(x) end
1857
1935
    x = o.lock!
1858
1936
    x.should == o
1859
 
    called.should == false
1860
 
    MODEL_DB.sqls.should == []
 
1937
    DB.sqls.should == []
1861
1938
  end
1862
1939
    
1863
1940
  it "should refresh the record using for_update if it is not a new record" do
1864
1941
    o = @c.load(:id => 1)
1865
 
    called = false
1866
 
    o.meta_def(:_refresh){|x| called = true; super(x)}
 
1942
    def o._refresh(x) instance_variable_set(:@a, 1); super(x) end
1867
1943
    x = o.lock!
1868
1944
    x.should == o
1869
 
    called.should == true
1870
 
    MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 1) LIMIT 1 FOR UPDATE"]
 
1945
    o.instance_variable_get(:@a).should == 1
 
1946
    DB.sqls.should == ["SELECT * FROM items WHERE (id = 1) LIMIT 1 FOR UPDATE"]
 
1947
  end
 
1948
end
 
1949
 
 
1950
describe "Model#schema_type_class" do
 
1951
  specify "should return the class or array of classes for the given type symbol" do
 
1952
    @c = Class.new(Sequel::Model(:items))
 
1953
    @c.class_eval{@db_schema = {:id=>{:type=>:integer}}}
 
1954
    @c.new.send(:schema_type_class, :id).should == Integer
1871
1955
  end
1872
1956
end