sequel 1.5.1 → 2.0.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.
@@ -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