sequel 1.5.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
- describe Inflector do
3
+ describe String do
4
4
  it "should transform words from singular to plural" do
5
5
  "post".pluralize.should == "posts"
6
6
  "octopus".pluralize.should =="octopi"
@@ -31,4 +31,4 @@ describe Inflector do
31
31
  "Message".foreign_key(false).should == "messageid"
32
32
  "Admin::Post".foreign_key.should == "post_id"
33
33
  end
34
- end
34
+ end
data/spec/model_spec.rb CHANGED
@@ -4,7 +4,7 @@ describe Sequel::Model do
4
4
  it "should have class method aliased as model" do
5
5
  Sequel::Model.instance_methods.should include("model")
6
6
 
7
- model_a = Class.new Sequel::Model
7
+ model_a = Class.new(Sequel::Model(:items))
8
8
  model_a.new.model.should be(model_a)
9
9
  end
10
10
 
@@ -48,6 +48,23 @@ describe Sequel::Model, "dataset & schema" do
48
48
  @model.table_name.should == :foo
49
49
  end
50
50
 
51
+ it "set_dataset should take a symbol" do
52
+ @model.db = MODEL_DB
53
+ @model.set_dataset(:foo)
54
+ @model.table_name.should == :foo
55
+ end
56
+
57
+ it "set_dataset should raise an error unless given a Symbol or Dataset" do
58
+ proc{@model.set_dataset(Object.new)}.should raise_error(Sequel::Error)
59
+ end
60
+
61
+ it "set_dataset should add the destroy method to the dataset" do
62
+ ds = MODEL_DB[:foo]
63
+ ds.should_not respond_to(:destroy)
64
+ @model.set_dataset(ds)
65
+ ds.should respond_to(:destroy)
66
+ end
67
+
51
68
  it "sets schema with implicit table name" do
52
69
  @model.set_schema do
53
70
  primary_key :ssn, :string
@@ -142,7 +159,7 @@ describe Sequel::Model, ".subset" do
142
159
  @c = Class.new(Sequel::Model(:items))
143
160
  end
144
161
 
145
- it "should create a filter on the underlying dataset" do
162
+ pt_specify "should create a filter on the underlying dataset" do
146
163
  proc {@c.new_only}.should raise_error(NoMethodError)
147
164
 
148
165
  @c.subset(:new_only) {:age == 'new'}
@@ -156,8 +173,8 @@ describe Sequel::Model, ".subset" do
156
173
  @c.dataset.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
157
174
 
158
175
  # check if subsets are composable
159
- @c.pricey.new_only.sql.should == "SELECT * FROM items WHERE (price > 100) AND (age = 'new')"
160
- @c.new_only.pricey.sql.should == "SELECT * FROM items WHERE (age = 'new') AND (price > 100)"
176
+ @c.pricey.new_only.sql.should == "SELECT * FROM items WHERE ((price > 100) AND (age = 'new'))"
177
+ @c.new_only.pricey.sql.should == "SELECT * FROM items WHERE ((age = 'new') AND (price > 100))"
161
178
  end
162
179
 
163
180
  end
@@ -184,11 +201,11 @@ describe Sequel::Model, ".find" do
184
201
  @c.find(:name => 'sharon').should be_a_kind_of(@c)
185
202
  $sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
186
203
 
187
- @c.find {"name LIKE 'abc%'".lit}.should be_a_kind_of(@c)
188
- $sqls.last.should == "SELECT * FROM items WHERE name LIKE 'abc%' LIMIT 1"
204
+ @c.find(:name.like('abc%')).should be_a_kind_of(@c)
205
+ $sqls.last.should == "SELECT * FROM items WHERE (name LIKE 'abc%') LIMIT 1"
189
206
  end
190
207
 
191
- it "should accept filter blocks" do
208
+ pt_specify "should accept filter blocks" do
192
209
  @c.find {:id == 1}.should be_a_kind_of(@c)
193
210
  $sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
194
211
 
@@ -217,73 +234,6 @@ describe Sequel::Model, ".fetch" do
217
234
 
218
235
  end
219
236
 
220
- ### DEPRECATED
221
- describe Sequel::Model, "magic methods" do
222
-
223
- before(:each) do
224
- @c = Class.new(Sequel::Dataset) do
225
- @@sqls = []
226
-
227
- def self.sqls; @@sqls; end
228
-
229
- def fetch_rows(sql)
230
- @@sqls << sql
231
- yield({:id => 123, :name => 'hey'})
232
- end
233
- end
234
-
235
- @m = Class.new(Sequel::Model(@c.new(nil).from(:items)))
236
- end
237
-
238
- it "should support order_by_xxx" do
239
- @m.order_by_name.should be_a_kind_of(@c)
240
- @m.order_by_name.sql.should == "SELECT * FROM items ORDER BY name"
241
- end
242
-
243
- it "should support group_by_xxx" do
244
- @m.group_by_name.should be_a_kind_of(@c)
245
- @m.group_by_name.sql.should == "SELECT * FROM items GROUP BY name"
246
- end
247
-
248
- it "should support count_by_xxx" do
249
- @m.count_by_name.should be_a_kind_of(@c)
250
- @m.count_by_name.sql.should == "SELECT name, count(*) AS count FROM items GROUP BY name ORDER BY count"
251
- end
252
-
253
- it "should support filter_by_xxx" do
254
- @m.filter_by_name('sharon').should be_a_kind_of(@c)
255
- @m.filter_by_name('sharon').sql.should == "SELECT * FROM items WHERE (name = 'sharon')"
256
- end
257
-
258
- it "should support all_by_xxx" do
259
- all = @m.all_by_name('sharon')
260
- all.class.should == Array
261
- all.size.should == 1
262
- all.first.should be_a_kind_of(@m)
263
- all.first.values.should == {:id => 123, :name => 'hey'}
264
- @c.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon')"]
265
- end
266
-
267
- it "should support find_by_xxx" do
268
- @m.find_by_name('sharon').should be_a_kind_of(@m)
269
- @m.find_by_name('sharon').values.should == {:id => 123, :name => 'hey'}
270
- @c.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"] * 2
271
- end
272
-
273
- it "should support first_by_xxx" do
274
- @m.first_by_name('sharon').should be_a_kind_of(@m)
275
- @m.first_by_name('sharon').values.should == {:id => 123, :name => 'hey'}
276
- @c.sqls.should == ["SELECT * FROM items ORDER BY name LIMIT 1"] * 2
277
- end
278
-
279
- it "should support last_by_xxx" do
280
- @m.last_by_name('sharon').should be_a_kind_of(@m)
281
- @m.last_by_name('sharon').values.should == {:id => 123, :name => 'hey'}
282
- @c.sqls.should == ["SELECT * FROM items ORDER BY name DESC LIMIT 1"] * 2
283
- end
284
-
285
- end
286
-
287
237
  describe Sequel::Model, ".find_or_create" do
288
238
 
289
239
  before(:each) do
@@ -420,14 +370,17 @@ describe Sequel::Model, "A model class without a primary key" do
420
370
  end
421
371
 
422
372
  describe Sequel::Model, "attribute accessors" do
373
+ after do
374
+ Sequel::Model.lazy_load_schema = false
375
+ end
423
376
 
424
- before(:each) do
377
+ before do
425
378
  MODEL_DB.reset
426
379
 
427
380
  @c = Class.new(Sequel::Model) do
428
381
  def self.columns; orig_columns; end
429
382
  end
430
- @dataset = Object.new
383
+ @dataset = Sequel::Dataset.new(MODEL_DB)
431
384
  def @dataset.db; end
432
385
  def @dataset.set_model(blah); end
433
386
  def @dataset.naked; self; end
@@ -435,7 +388,7 @@ describe Sequel::Model, "attribute accessors" do
435
388
  def @dataset.def_mutation_method(*names); end
436
389
  end
437
390
 
438
- it "should be created on set_dataset" do
391
+ it "should be created on set_dataset unless lazy loading schema" do
439
392
  %w'x y x= y='.each do |x|
440
393
  @c.instance_methods.include?(x).should == false
441
394
  end
@@ -453,6 +406,28 @@ describe Sequel::Model, "attribute accessors" do
453
406
  o.x.should == 34
454
407
  end
455
408
 
409
+ it "should be created on first initialization if lazy loading schema" do
410
+ Sequel::Model.lazy_load_schema = true
411
+ %w'x y x= y='.each do |x|
412
+ @c.instance_methods.include?(x).should == false
413
+ end
414
+ @c.set_dataset(@dataset)
415
+ %w'x y x= y='.each do |x|
416
+ @c.instance_methods.include?(x).should == false
417
+ end
418
+ o = @c.new
419
+ %w'x y x= y='.each do |x|
420
+ @c.instance_methods.include?(x).should == true
421
+ end
422
+ %w'x y x= y='.each do |x|
423
+ o.methods.include?(x).should == true
424
+ end
425
+
426
+ o.x.should be_nil
427
+ o.x = 34
428
+ o.x.should == 34
429
+ end
430
+
456
431
  it "should be only accept one argument for the write accessor" do
457
432
  @c.set_dataset(@dataset)
458
433
  o = @c.new
@@ -505,7 +480,7 @@ describe Sequel::Model, ".[]" do
505
480
  @c.set_primary_key [:node_id, :kind]
506
481
  @c[3921, 201].should be_a_kind_of(@c)
507
482
  $sqls.last.should =~ \
508
- /^SELECT \* FROM items WHERE (\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\)) LIMIT 1$/
483
+ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
509
484
  end
510
485
  end
511
486
 
@@ -518,3 +493,60 @@ context "Model#inspect" do
518
493
  @o.inspect.should == '#<Sequel::Model @values={:x=>333}>'
519
494
  end
520
495
  end
496
+
497
+ context "Model.db_schema" do
498
+ setup do
499
+ @c = Class.new(Sequel::Model(:items)) do
500
+ def self.columns; orig_columns; end
501
+ end
502
+ @dataset = Sequel::Dataset.new(nil).from(:items)
503
+ @dataset.meta_def(:db){@db ||= Sequel::Database.new}
504
+ def @dataset.set_model(blah); end
505
+ def @dataset.naked; self; end
506
+ def @dataset.columns; []; end
507
+ def @dataset.def_mutation_method(*names); end
508
+ end
509
+
510
+ specify "should use the database's schema_for_table and set the columns" do
511
+ d = @dataset.db
512
+ def d.schema(table)
513
+ [[:x, {:type=>:integer}], [:y, {:type=>:string}]]
514
+ end
515
+ @c.dataset = @dataset
516
+ @c.db_schema.should == {:x=>{:type=>:integer}, :y=>{:type=>:string}}
517
+ @c.columns.should == [:x, :y]
518
+ end
519
+
520
+ specify "should restrict the schema and columns for datasets with a :select option" do
521
+ ds = @dataset.select(:x, :y___z)
522
+ d = ds.db
523
+ def d.schema(table)
524
+ [[:x, {:type=>:integer}], [:y, {:type=>:string}]]
525
+ end
526
+ def @c.columns; [:x, :z]; end
527
+ @c.dataset = ds
528
+ @c.db_schema.should == {:x=>{:type=>:integer}, :z=>{}}
529
+ end
530
+
531
+ specify "should not use schema_for_table if the dataset uses multiple tables or custom sql" do
532
+ ds = @dataset.join(:x, :id)
533
+ d = ds.db
534
+ e = false
535
+ d.meta_def(:schema){|table| e = true}
536
+ def @c.columns; [:x]; end
537
+ @c.dataset = ds
538
+ @c.db_schema.should == {:x=>{}}
539
+ e.should == false
540
+ end
541
+
542
+ specify "should fallback to fetching records if schema_for_table raises an error" do
543
+ ds = @dataset.join(:x, :id)
544
+ d = ds.db
545
+ def d.schema(table)
546
+ raise StandardError
547
+ end
548
+ def @c.columns; [:x]; end
549
+ @c.dataset = ds
550
+ @c.db_schema.should == {:x=>{}}
551
+ end
552
+ end
data/spec/plugins_spec.rb CHANGED
@@ -62,6 +62,10 @@ describe Sequel::Model, "using a plugin" do
62
62
  # dataset methods
63
63
  c.dataset.should respond_to(:ghi)
64
64
  c.dataset.ghi.should == {:a => 1, :b => 2}
65
+
66
+ # dataset methods called on the class
67
+ c.should respond_to(:ghi)
68
+ c.ghi.should == {:a => 1, :b => 2}
65
69
  end
66
70
 
67
71
  it "should fail to apply if the plugin has DatasetMethod and the model has no datset" do
data/spec/rcov.opts CHANGED
@@ -1,4 +1,4 @@
1
1
  --exclude
2
2
  gems
3
3
  --exclude
4
- spec
4
+ spec
data/spec/record_spec.rb CHANGED
@@ -185,16 +185,6 @@ describe "Model#new?" do
185
185
  n.save
186
186
  n.should_not be_new
187
187
  end
188
-
189
- ### DEPRECATED
190
- it "should alias new_record? to new?" do
191
- n = @c.new(:x => 1)
192
- n.should respond_to(:new_record?)
193
- n.should be_new_record
194
- n.save
195
- n.should_not be_new_record
196
- end
197
-
198
188
  end
199
189
 
200
190
  describe Sequel::Model, "w/ primary key" do
@@ -254,8 +244,8 @@ describe Sequel::Model, "with this" do
254
244
 
255
245
  parts = [
256
246
  'SELECT * FROM examples WHERE %s LIMIT 1',
257
- '(x = 4) AND (y = 5)',
258
- '(y = 5) AND (x = 4)'
247
+ '((x = 4) AND (y = 5))',
248
+ '((y = 5) AND (x = 4))'
259
249
  ].map { |expr| Regexp.escape expr }
260
250
  regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
261
251
 
@@ -398,16 +388,6 @@ describe Sequel::Model, "update_with_params" do
398
388
  MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
399
389
  end
400
390
 
401
- ### DEPRECATE
402
- it "should be aliased by update_with" do
403
- @o1.update_with(:x => 1, :z => 2)
404
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
405
-
406
- MODEL_DB.reset
407
- @o2.update_with(:y => 1, :abc => 2)
408
- MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
409
- end
410
-
411
391
  it "should support virtual attributes" do
412
392
  @c.class_def(:blah=) {|v| self.x = v}
413
393
  @o1.update_with_params(:blah => 333)
@@ -415,43 +395,6 @@ describe Sequel::Model, "update_with_params" do
415
395
  end
416
396
  end
417
397
 
418
- ### DEPRECATE
419
- describe Sequel::Model, "create_with_params" do
420
-
421
- before(:each) do
422
- MODEL_DB.reset
423
-
424
- @c = Class.new(Sequel::Model(:items)) do
425
- columns :x, :y
426
- end
427
- @c.instance_variable_set(:@columns, true)
428
- end
429
-
430
- it "should filter the given params using the model columns" do
431
- @c.create_with_params(:x => 1, :z => 2)
432
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
433
-
434
- MODEL_DB.reset
435
- @c.create_with_params(:y => 1, :abc => 2)
436
- MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
437
- end
438
-
439
- it "should be aliased by create_with" do
440
- @c.create_with(:x => 1, :z => 2)
441
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
442
-
443
- MODEL_DB.reset
444
- @c.create_with(:y => 1, :abc => 2)
445
- MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
446
- end
447
-
448
- it "should support virtual attributes" do
449
- @c.class_def(:blah=) {|v| self.x = v}
450
- o = @c.create_with(:blah => 333)
451
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
452
- end
453
- end
454
-
455
398
  describe Sequel::Model, "#destroy" do
456
399
 
457
400
  before(:each) do
@@ -749,3 +692,161 @@ describe Sequel::Model, "#refresh" do
749
692
  @m.instance_variable_get(:@tags).should == nil
750
693
  end
751
694
  end
695
+
696
+ describe Sequel::Model, "typecasting" do
697
+ setup do
698
+ MODEL_DB.reset
699
+ @c = Class.new(Sequel::Model(:items)) do
700
+ columns :x
701
+ end
702
+ end
703
+
704
+ specify "should not convert if typecasting is turned off" do
705
+ @c.typecast_on_assignment = false
706
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
707
+ m = @c.new
708
+ m.x = '1'
709
+ m.x.should == '1'
710
+ end
711
+
712
+ specify "should convert to integer for an integer field" do
713
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
714
+ m = @c.new
715
+ m.x = '1'
716
+ m.x.should == 1
717
+ m.x = 1
718
+ m.x.should == 1
719
+ m.x = 1.3
720
+ m.x.should == 1
721
+ end
722
+
723
+ specify "should not typecast nil if NULLs are allowed" do
724
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>true}})
725
+ m = @c.new
726
+ m.x = nil
727
+ m.x.should == nil
728
+ end
729
+
730
+ specify "should raise an error if attempting to typecast nil and NULLs are not allowed" do
731
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
732
+ proc{@c.new.x = nil}.should raise_error(Sequel::Error)
733
+ end
734
+
735
+ specify "should not raise an error if NULLs are not allowed and typecasting is turned off" do
736
+ @c.typecast_on_assignment = false
737
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
738
+ m = @c.new
739
+ m.x = nil
740
+ m.x.should == nil
741
+ end
742
+
743
+ specify "should raise an error if invalid data is used in an integer field" do
744
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
745
+ proc{@c.new.x = 'a'}.should raise_error
746
+ end
747
+
748
+ specify "should convert to float for a float field" do
749
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
750
+ m = @c.new
751
+ m.x = '1.3'
752
+ m.x.should == 1.3
753
+ m.x = 1
754
+ m.x.should == 1.0
755
+ m.x = 1.3
756
+ m.x.should == 1.3
757
+ end
758
+
759
+ specify "should raise an error if invalid data is used in an float field" do
760
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
761
+ proc{@c.new.x = 'a'}.should raise_error
762
+ end
763
+
764
+ specify "should convert to string for a string field" do
765
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
766
+ m = @c.new
767
+ m.x = '1.3'
768
+ m.x.should == '1.3'
769
+ m.x = 1
770
+ m.x.should == '1'
771
+ m.x = 1.3
772
+ m.x.should == '1.3'
773
+ end
774
+
775
+ specify "should convert to boolean for a boolean field" do
776
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:boolean}})
777
+ m = @c.new
778
+ m.x = '1.3'
779
+ m.x.should == true
780
+ m.x = 1
781
+ m.x.should == true
782
+ m.x = 1.3
783
+ m.x.should == true
784
+ m.x = 't'
785
+ m.x.should == true
786
+ m.x = 'T'
787
+ m.x.should == true
788
+ m.x = true
789
+ m.x.should == true
790
+ m.x = nil
791
+ m.x.should == nil
792
+ m.x = ''
793
+ m.x.should == nil
794
+ m.x = []
795
+ m.x.should == nil
796
+ m.x = 'f'
797
+ m.x.should == false
798
+ m.x = 'F'
799
+ m.x.should == false
800
+ m.x = 'false'
801
+ m.x.should == false
802
+ m.x = 'FALSE'
803
+ m.x.should == false
804
+ m.x = '0'
805
+ m.x.should == false
806
+ m.x = 0
807
+ m.x.should == false
808
+ m.x = false
809
+ m.x.should == false
810
+ end
811
+
812
+ specify "should convert to date for a date field" do
813
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
814
+ m = @c.new
815
+ y = Date.new(2007,10,21)
816
+ m.x = '2007-10-21'
817
+ m.x.should == y
818
+ m.x = '2007-10-21'.to_date
819
+ m.x.should == y
820
+ m.x = '2007-10-21'.to_time
821
+ m.x.should == y
822
+ m.x = '2007-10-21'.to_datetime
823
+ m.x.should == y
824
+ end
825
+
826
+ specify "should raise an error if invalid data is used in a date field" do
827
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
828
+ proc{@c.new.x = 'a'}.should raise_error
829
+ end
830
+
831
+ specify "should convert to date for a datetime field" do
832
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
833
+ m = @c.new
834
+ m.x = '2007-10-21 10:20:30'
835
+ m.x.should == '2007-10-21 10:20:30'.to_datetime
836
+ y = DateTime.new(2007,10,21,10,20,30)
837
+ m.x = '2007-10-21 10:20:30'
838
+ m.x.should == y
839
+ m.x = '2007-10-21 10:20:30'.to_datetime
840
+ m.x.should == y
841
+ m.x = '2007-10-21 10:20:30'.to_time
842
+ m.x.should == y
843
+ m.x = '2007-10-21'.to_date
844
+ m.x.should == DateTime.new(2007,10,21)
845
+ end
846
+
847
+ specify "should raise an error if invalid data is used in a datetime field" do
848
+ @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
849
+ proc{@c.new.x = 'a'}.should raise_error
850
+ end
851
+
852
+ end