sequel 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +38 -0
- data/README +3 -4
- data/Rakefile +4 -4
- data/lib/sequel_model.rb +22 -2
- data/lib/sequel_model/association_reflection.rb +2 -9
- data/lib/sequel_model/associations.rb +184 -91
- data/lib/sequel_model/base.rb +117 -22
- data/lib/sequel_model/caching.rb +1 -1
- data/lib/sequel_model/dataset_methods.rb +26 -0
- data/lib/sequel_model/eager_loading.rb +16 -20
- data/lib/sequel_model/hooks.rb +1 -1
- data/lib/sequel_model/plugins.rb +1 -1
- data/lib/sequel_model/record.rb +125 -39
- data/lib/sequel_model/validations.rb +101 -115
- data/spec/association_reflection_spec.rb +6 -6
- data/spec/associations_spec.rb +205 -37
- data/spec/base_spec.rb +161 -1
- data/spec/dataset_methods_spec.rb +66 -0
- data/spec/eager_loading_spec.rb +36 -25
- data/spec/model_spec.rb +51 -6
- data/spec/record_spec.rb +172 -62
- data/spec/schema_spec.rb +7 -0
- data/spec/validations_spec.rb +152 -51
- metadata +5 -3
data/spec/record_spec.rb
CHANGED
@@ -227,20 +227,20 @@ describe Sequel::Model, "with this" do
|
|
227
227
|
before { @example = Class.new Sequel::Model(:examples); @example.columns :id, :a, :x, :y }
|
228
228
|
|
229
229
|
it "should return a dataset identifying the record" do
|
230
|
-
instance = @example.
|
230
|
+
instance = @example.load :id => 3
|
231
231
|
instance.this.sql.should be_eql("SELECT * FROM examples WHERE (id = 3) LIMIT 1")
|
232
232
|
end
|
233
233
|
|
234
234
|
it "should support arbitary primary keys" do
|
235
235
|
@example.set_primary_key :a
|
236
236
|
|
237
|
-
instance = @example.
|
237
|
+
instance = @example.load :a => 3
|
238
238
|
instance.this.sql.should be_eql("SELECT * FROM examples WHERE (a = 3) LIMIT 1")
|
239
239
|
end
|
240
240
|
|
241
241
|
it "should support composite primary keys" do
|
242
242
|
@example.set_primary_key :x, :y
|
243
|
-
instance = @example.
|
243
|
+
instance = @example.load :x => 4, :y => 5
|
244
244
|
|
245
245
|
parts = [
|
246
246
|
'SELECT * FROM examples WHERE %s LIMIT 1',
|
@@ -261,19 +261,19 @@ describe "Model#pk" do
|
|
261
261
|
end
|
262
262
|
|
263
263
|
it "should be default return the value of the :id column" do
|
264
|
-
m = @m.
|
264
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
265
265
|
m.pk.should == 111
|
266
266
|
end
|
267
267
|
|
268
268
|
it "should be return the primary key value for custom primary key" do
|
269
269
|
@m.set_primary_key :x
|
270
|
-
m = @m.
|
270
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
271
271
|
m.pk.should == 2
|
272
272
|
end
|
273
273
|
|
274
274
|
it "should be return the primary key value for composite primary key" do
|
275
275
|
@m.set_primary_key [:y, :x]
|
276
|
-
m = @m.
|
276
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
277
277
|
m.pk.should == [3, 2]
|
278
278
|
end
|
279
279
|
|
@@ -295,19 +295,19 @@ describe "Model#pk_hash" do
|
|
295
295
|
end
|
296
296
|
|
297
297
|
it "should be default return the value of the :id column" do
|
298
|
-
m = @m.
|
298
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
299
299
|
m.pk_hash.should == {:id => 111}
|
300
300
|
end
|
301
301
|
|
302
302
|
it "should be return the primary key value for custom primary key" do
|
303
303
|
@m.set_primary_key :x
|
304
|
-
m = @m.
|
304
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
305
305
|
m.pk_hash.should == {:x => 2}
|
306
306
|
end
|
307
307
|
|
308
308
|
it "should be return the primary key value for composite primary key" do
|
309
309
|
@m.set_primary_key [:y, :x]
|
310
|
-
m = @m.
|
310
|
+
m = @m.load(:id => 111, :x => 2, :y => 3)
|
311
311
|
m.pk_hash.should == {:y => 3, :x => 2}
|
312
312
|
end
|
313
313
|
|
@@ -322,89 +322,180 @@ describe "Model#pk_hash" do
|
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
325
|
-
describe Sequel::Model, "
|
326
|
-
|
327
|
-
before(:each) do
|
325
|
+
describe Sequel::Model, "#set" do
|
326
|
+
before do
|
328
327
|
MODEL_DB.reset
|
329
328
|
|
330
329
|
@c = Class.new(Sequel::Model(:items)) do
|
330
|
+
set_primary_key :id
|
331
331
|
columns :x, :y, :id
|
332
332
|
end
|
333
|
+
@c.strict_param_setting = false
|
333
334
|
@c.instance_variable_set(:@columns, true)
|
334
335
|
@o1 = @c.new
|
335
336
|
@o2 = @c.load(:id => 5)
|
336
337
|
end
|
337
|
-
|
338
|
+
|
338
339
|
it "should filter the given params using the model columns" do
|
339
|
-
@o1.
|
340
|
+
@o1.set(:x => 1, :z => 2)
|
340
341
|
@o1.values.should == {:x => 1}
|
341
342
|
MODEL_DB.sqls.should == []
|
342
343
|
|
343
|
-
@o2.
|
344
|
+
@o2.set(:y => 1, :abc => 2)
|
344
345
|
@o2.values.should == {:y => 1, :id=> 5}
|
345
346
|
MODEL_DB.sqls.should == []
|
346
347
|
end
|
347
348
|
|
348
349
|
it "should work with both strings and symbols" do
|
349
|
-
@o1.
|
350
|
+
@o1.set('x'=> 1, 'z'=> 2)
|
350
351
|
@o1.values.should == {:x => 1}
|
351
352
|
MODEL_DB.sqls.should == []
|
352
353
|
|
353
|
-
@o2.
|
354
|
+
@o2.set('y'=> 1, 'abc'=> 2)
|
354
355
|
@o2.values.should == {:y => 1, :id=> 5}
|
355
356
|
MODEL_DB.sqls.should == []
|
356
357
|
end
|
357
358
|
|
358
359
|
it "should support virtual attributes" do
|
359
360
|
@c.class_def(:blah=) {|v| self.x = v}
|
360
|
-
@o1.
|
361
|
+
@o1.set(:blah => 333)
|
361
362
|
@o1.values.should == {:x => 333}
|
362
363
|
MODEL_DB.sqls.should == []
|
363
|
-
@o1.
|
364
|
+
@o1.set('blah'=> 334)
|
364
365
|
@o1.values.should == {:x => 334}
|
365
366
|
MODEL_DB.sqls.should == []
|
366
367
|
end
|
367
|
-
|
368
|
+
|
369
|
+
it "should not modify the primary key" do
|
370
|
+
@o1.set(:x => 1, :id => 2)
|
371
|
+
@o1.values.should == {:x => 1}
|
372
|
+
MODEL_DB.sqls.should == []
|
373
|
+
@o2.set('y'=> 1, 'id'=> 2)
|
374
|
+
@o2.values.should == {:y => 1, :id=> 5}
|
375
|
+
MODEL_DB.sqls.should == []
|
376
|
+
end
|
368
377
|
|
369
|
-
|
378
|
+
it "should be aliased as set_with_params" do
|
379
|
+
@o1.set_with_params(:x => 1, :z => 2)
|
380
|
+
@o1.values.should == {:x => 1}
|
381
|
+
MODEL_DB.sqls.should == []
|
382
|
+
end
|
383
|
+
end
|
370
384
|
|
371
|
-
|
385
|
+
describe Sequel::Model, "#update" do
|
386
|
+
before do
|
372
387
|
MODEL_DB.reset
|
373
388
|
|
374
389
|
@c = Class.new(Sequel::Model(:items)) do
|
390
|
+
set_primary_key :id
|
375
391
|
columns :x, :y, :id
|
376
392
|
end
|
393
|
+
@c.strict_param_setting = false
|
377
394
|
@c.instance_variable_set(:@columns, true)
|
378
395
|
@o1 = @c.new
|
379
396
|
@o2 = @c.load(:id => 5)
|
380
397
|
end
|
381
398
|
|
382
399
|
it "should filter the given params using the model columns" do
|
383
|
-
@o1.
|
400
|
+
@o1.update(:x => 1, :z => 2)
|
384
401
|
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
385
402
|
|
386
403
|
MODEL_DB.reset
|
387
|
-
@o2.
|
404
|
+
@o2.update(:y => 1, :abc => 2)
|
388
405
|
MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
|
389
406
|
end
|
390
407
|
|
391
408
|
it "should support virtual attributes" do
|
392
409
|
@c.class_def(:blah=) {|v| self.x = v}
|
393
|
-
@o1.
|
410
|
+
@o1.update(:blah => 333)
|
394
411
|
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
|
395
412
|
end
|
413
|
+
|
414
|
+
it "should not modify the primary key" do
|
415
|
+
@o1.update(:x => 1, :id => 2)
|
416
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
417
|
+
MODEL_DB.reset
|
418
|
+
@o2.update('y'=> 1, 'id'=> 2)
|
419
|
+
@o2.values.should == {:y => 1, :id=> 5}
|
420
|
+
MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
|
421
|
+
end
|
422
|
+
|
423
|
+
it "should be aliased as update_with_params" do
|
424
|
+
@o1.update_with_params(:x => 1, :z => 2)
|
425
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
426
|
+
end
|
396
427
|
end
|
397
428
|
|
398
|
-
describe Sequel::Model, "#
|
429
|
+
describe Sequel::Model, "#(set|update)_(all|except|only)" do
|
430
|
+
before do
|
431
|
+
MODEL_DB.reset
|
432
|
+
|
433
|
+
@c = Class.new(Sequel::Model(:items)) do
|
434
|
+
set_primary_key :id
|
435
|
+
columns :x, :y, :z, :id
|
436
|
+
set_allowed_columns :x
|
437
|
+
set_restricted_columns :y
|
438
|
+
end
|
439
|
+
@c.strict_param_setting = false
|
440
|
+
@c.instance_variable_set(:@columns, true)
|
441
|
+
@o1 = @c.new
|
442
|
+
end
|
399
443
|
|
400
|
-
|
444
|
+
it "#set_all should set all attributes" do
|
445
|
+
@o1.set_all(:x => 1, :y => 2, :z=>3, :id=>4)
|
446
|
+
@o1.values.should == {:x => 1, :y => 2, :z=>3}
|
447
|
+
end
|
448
|
+
|
449
|
+
it "#set_only should only set given attributes" do
|
450
|
+
@o1.set_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
|
451
|
+
@o1.values.should == {:x => 1, :y => 2}
|
452
|
+
@o1.set_only({:x => 4, :y => 5, :z=>6, :id=>7}, :x, :y)
|
453
|
+
@o1.values.should == {:x => 4, :y => 5}
|
454
|
+
end
|
455
|
+
|
456
|
+
it "#set_except should not set given attributes" do
|
457
|
+
@o1.set_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
|
458
|
+
@o1.values.should == {:x => 1}
|
459
|
+
@o1.set_except({:x => 4, :y => 2, :z=>3, :id=>4}, :y, :z)
|
460
|
+
@o1.values.should == {:x => 4}
|
461
|
+
end
|
462
|
+
|
463
|
+
it "#update_all should update all attributes" do
|
464
|
+
@c.new.update_all(:x => 1, :id=>4)
|
465
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
466
|
+
MODEL_DB.reset
|
467
|
+
@c.new.update_all(:y => 1, :id=>4)
|
468
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
|
469
|
+
MODEL_DB.reset
|
470
|
+
@c.new.update_all(:z => 1, :id=>4)
|
471
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (z) VALUES (1)"
|
472
|
+
end
|
473
|
+
|
474
|
+
it "#update_only should only update given attributes" do
|
475
|
+
@o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
|
476
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
477
|
+
MODEL_DB.reset
|
478
|
+
@c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
|
479
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
480
|
+
end
|
481
|
+
|
482
|
+
it "#update_except should not update given attributes" do
|
483
|
+
@o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
|
484
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
485
|
+
MODEL_DB.reset
|
486
|
+
@c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
|
487
|
+
MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
describe Sequel::Model, "#destroy" do
|
492
|
+
before do
|
401
493
|
MODEL_DB.reset
|
402
494
|
@model = Class.new(Sequel::Model(:items))
|
403
495
|
@model.columns :id
|
404
496
|
@model.dataset.meta_def(:delete) {MODEL_DB.execute delete_sql}
|
405
497
|
|
406
|
-
@instance = @model.
|
407
|
-
#@model.stub!(:delete).and_return(:true)
|
498
|
+
@instance = @model.load(:id => 1234)
|
408
499
|
end
|
409
500
|
|
410
501
|
it "should return self" do
|
@@ -452,7 +543,7 @@ describe Sequel::Model, "#each" do
|
|
452
543
|
setup do
|
453
544
|
@model = Class.new(Sequel::Model(:items))
|
454
545
|
@model.columns :a, :b, :id
|
455
|
-
@m = @model.
|
546
|
+
@m = @model.load(:a => 1, :b => 2, :id => 4444)
|
456
547
|
end
|
457
548
|
|
458
549
|
specify "should iterate over the values" do
|
@@ -466,7 +557,7 @@ describe Sequel::Model, "#keys" do
|
|
466
557
|
setup do
|
467
558
|
@model = Class.new(Sequel::Model(:items))
|
468
559
|
@model.columns :a, :b, :id
|
469
|
-
@m = @model.
|
560
|
+
@m = @model.load(:a => 1, :b => 2, :id => 4444)
|
470
561
|
end
|
471
562
|
|
472
563
|
specify "should return the value keys" do
|
@@ -482,9 +573,9 @@ describe Sequel::Model, "#==" do
|
|
482
573
|
specify "should compare instances by values" do
|
483
574
|
z = Class.new(Sequel::Model)
|
484
575
|
z.columns :id, :x
|
485
|
-
a = z.
|
486
|
-
b = z.
|
487
|
-
c = z.
|
576
|
+
a = z.load(:id => 1, :x => 3)
|
577
|
+
b = z.load(:id => 1, :x => 4)
|
578
|
+
c = z.load(:id => 1, :x => 3)
|
488
579
|
|
489
580
|
a.should_not == b
|
490
581
|
a.should == c
|
@@ -494,9 +585,9 @@ describe Sequel::Model, "#==" do
|
|
494
585
|
specify "should be aliased to #eql?" do
|
495
586
|
z = Class.new(Sequel::Model)
|
496
587
|
z.columns :id, :x
|
497
|
-
a = z.
|
498
|
-
b = z.
|
499
|
-
c = z.
|
588
|
+
a = z.load(:id => 1, :x => 3)
|
589
|
+
b = z.load(:id => 1, :x => 4)
|
590
|
+
c = z.load(:id => 1, :x => 3)
|
500
591
|
|
501
592
|
a.eql?(b).should == false
|
502
593
|
a.eql?(c).should == true
|
@@ -510,10 +601,10 @@ describe Sequel::Model, "#===" do
|
|
510
601
|
z.columns :id, :x
|
511
602
|
y = Class.new(Sequel::Model)
|
512
603
|
y.columns :id, :x
|
513
|
-
a = z.
|
514
|
-
b = z.
|
515
|
-
c = z.
|
516
|
-
d = y.
|
604
|
+
a = z.load(:id => 1, :x => 3)
|
605
|
+
b = z.load(:id => 1, :x => 4)
|
606
|
+
c = z.load(:id => 2, :x => 3)
|
607
|
+
d = y.load(:id => 1, :x => 3)
|
517
608
|
|
518
609
|
a.should === b
|
519
610
|
a.should_not === c
|
@@ -542,10 +633,10 @@ describe Sequel::Model, "#hash" do
|
|
542
633
|
z.columns :id, :x
|
543
634
|
y = Class.new(Sequel::Model)
|
544
635
|
y.columns :id, :x
|
545
|
-
a = z.
|
546
|
-
b = z.
|
547
|
-
c = z.
|
548
|
-
d = y.
|
636
|
+
a = z.load(:id => 1, :x => 3)
|
637
|
+
b = z.load(:id => 1, :x => 4)
|
638
|
+
c = z.load(:id => 2, :x => 3)
|
639
|
+
d = y.load(:id => 1, :x => 3)
|
549
640
|
|
550
641
|
a.hash.should == b.hash
|
551
642
|
a.hash.should_not == c.hash
|
@@ -573,11 +664,17 @@ describe Sequel::Model, "#initialize" do
|
|
573
664
|
@c = Class.new(Sequel::Model) do
|
574
665
|
columns :id, :x
|
575
666
|
end
|
667
|
+
@c.strict_param_setting = false
|
576
668
|
end
|
577
669
|
|
578
670
|
specify "should accept values" do
|
671
|
+
m = @c.new(:x => 2)
|
672
|
+
m.values.should == {:x => 2}
|
673
|
+
end
|
674
|
+
|
675
|
+
specify "should not modify the primary key" do
|
579
676
|
m = @c.new(:id => 1, :x => 2)
|
580
|
-
m.values.should == {:
|
677
|
+
m.values.should == {:x => 2}
|
581
678
|
end
|
582
679
|
|
583
680
|
specify "should accept no values" do
|
@@ -599,14 +696,14 @@ describe Sequel::Model, "#initialize" do
|
|
599
696
|
@c.class_def(:blah=) {|x| @blah = x}
|
600
697
|
@c.class_def(:blah) {@blah}
|
601
698
|
|
602
|
-
m = @c.new(:
|
603
|
-
m.values.should == {:
|
699
|
+
m = @c.new(:x => 2, :blah => 3)
|
700
|
+
m.values.should == {:x => 2}
|
604
701
|
m.blah.should == 3
|
605
702
|
end
|
606
703
|
|
607
704
|
specify "should convert string keys into symbol keys" do
|
608
|
-
m = @c.new('
|
609
|
-
m.values.should == {:
|
705
|
+
m = @c.new('x' => 2)
|
706
|
+
m.values.should == {:x => 2}
|
610
707
|
end
|
611
708
|
end
|
612
709
|
|
@@ -680,16 +777,10 @@ describe Sequel::Model, "#refresh" do
|
|
680
777
|
|
681
778
|
specify "should remove cached associations" do
|
682
779
|
@c.many_to_one :node, :class=>@c
|
683
|
-
@c.one_to_many :attributes, :class=>@c
|
684
|
-
@c.many_to_many :tags, :class=>@c
|
685
780
|
@m = @c.new(:id => 555)
|
686
|
-
@m.
|
687
|
-
@m.instance_variable_set(:@attributes, [15])
|
688
|
-
@m.instance_variable_set(:@tags, [15])
|
781
|
+
@m.associations[:node] = 15
|
689
782
|
@m.reload
|
690
|
-
@m.
|
691
|
-
@m.instance_variable_get(:@attributes).should == nil
|
692
|
-
@m.instance_variable_get(:@tags).should == nil
|
783
|
+
@m.associations.should == {}
|
693
784
|
end
|
694
785
|
end
|
695
786
|
|
@@ -702,7 +793,7 @@ describe Sequel::Model, "typecasting" do
|
|
702
793
|
end
|
703
794
|
|
704
795
|
teardown do
|
705
|
-
Sequel.
|
796
|
+
Sequel.datetime_class = Time
|
706
797
|
end
|
707
798
|
|
708
799
|
specify "should not convert if typecasting is turned off" do
|
@@ -765,6 +856,25 @@ describe Sequel::Model, "typecasting" do
|
|
765
856
|
proc{@c.new.x = 'a'}.should raise_error
|
766
857
|
end
|
767
858
|
|
859
|
+
specify "should convert to BigDecimal for a decimal field" do
|
860
|
+
@c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
|
861
|
+
m = @c.new
|
862
|
+
bd = '1.0'.to_d
|
863
|
+
m.x = '1.0'
|
864
|
+
m.x.should == bd
|
865
|
+
m.x = 1.0
|
866
|
+
m.x.should == bd
|
867
|
+
m.x = 1
|
868
|
+
m.x.should == bd
|
869
|
+
m.x = bd
|
870
|
+
m.x.should == bd
|
871
|
+
end
|
872
|
+
|
873
|
+
specify "should raise an error if invalid data is used in an decimal field" do
|
874
|
+
@c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
|
875
|
+
proc{@c.new.x = Date.today}.should raise_error
|
876
|
+
end
|
877
|
+
|
768
878
|
specify "should convert to string for a string field" do
|
769
879
|
@c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
|
770
880
|
m = @c.new
|
@@ -851,7 +961,7 @@ describe Sequel::Model, "typecasting" do
|
|
851
961
|
proc{@c.new.x = '2008-10-21'.to_datetime}.should raise_error
|
852
962
|
end
|
853
963
|
|
854
|
-
specify "should convert to the Sequel.
|
964
|
+
specify "should convert to the Sequel.datetime_class for a datetime field" do
|
855
965
|
@c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
|
856
966
|
m = @c.new
|
857
967
|
x = '2007-10-21T10:20:30-07:00'
|
@@ -864,7 +974,7 @@ describe Sequel::Model, "typecasting" do
|
|
864
974
|
m.x.should == y
|
865
975
|
m.x = '2007-10-21'.to_date
|
866
976
|
m.x.should == '2007-10-21'.to_time
|
867
|
-
Sequel.
|
977
|
+
Sequel.datetime_class = DateTime
|
868
978
|
y = x.to_datetime
|
869
979
|
m.x = x
|
870
980
|
m.x.should == y
|
@@ -880,7 +990,7 @@ describe Sequel::Model, "typecasting" do
|
|
880
990
|
@c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
|
881
991
|
proc{@c.new.x = '0000'}.should raise_error
|
882
992
|
proc{@c.new.x = ''}.should_not raise_error # Valid Time
|
883
|
-
Sequel.
|
993
|
+
Sequel.datetime_class = DateTime
|
884
994
|
proc{@c.new.x = '0000'}.should raise_error
|
885
995
|
proc{@c.new.x = ''}.should raise_error
|
886
996
|
end
|