sequel 2.0.1 → 2.1.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.
data/spec/base_spec.rb CHANGED
@@ -182,7 +182,7 @@ describe Sequel::Model, "dataset" do
182
182
  end
183
183
  end
184
184
 
185
- describe Sequel::Model, "def_dataset_method" do
185
+ describe Sequel::Model, ".def_dataset_method" do
186
186
  setup do
187
187
  @c = Class.new(Sequel::Model(:items)) do
188
188
  @dataset = Object.new
@@ -210,6 +210,25 @@ describe Sequel::Model, "def_dataset_method" do
210
210
  @c.return_3.should == 3
211
211
  @c.return_4.should == 4
212
212
  end
213
+
214
+ it "should cache calls and readd methods if set_dataset is used" do
215
+ @c.instance_eval do
216
+ def_dataset_method(:return_3){3}
217
+ end
218
+ @c.set_dataset :items
219
+ @c.return_3.should == 3
220
+ @c.dataset.return_3.should == 3
221
+ end
222
+
223
+ it "should readd methods to subclasses, if set_dataset is used in a subclass" do
224
+ @c.instance_eval do
225
+ def_dataset_method(:return_3){3}
226
+ end
227
+ c = Class.new(@c)
228
+ c.set_dataset :items
229
+ c.return_3.should == 3
230
+ c.dataset.return_3.should == 3
231
+ end
213
232
  end
214
233
 
215
234
  describe "A model class with implicit table name" do
@@ -256,3 +275,144 @@ describe "Model.db=" do
256
275
  end
257
276
  end
258
277
 
278
+ describe Sequel::Model, ".(allowed|restricted)_columns " do
279
+ setup do
280
+ @c = Class.new(Sequel::Model(:blahblah)) do
281
+ columns :x, :y, :z
282
+ def refresh
283
+ self
284
+ end
285
+ end
286
+ @c.strict_param_setting = false
287
+ @c.instance_variable_set(:@columns, [:x, :y, :z])
288
+ end
289
+
290
+ it "should set the allowed columns correctly" do
291
+ @c.allowed_columns.should == nil
292
+ @c.set_allowed_columns :x
293
+ @c.allowed_columns.should == [:x]
294
+ @c.set_allowed_columns :x, :y
295
+ @c.allowed_columns.should == [:x, :y]
296
+ end
297
+
298
+ it "should set the restricted columns correctly" do
299
+ @c.restricted_columns.should == nil
300
+ @c.set_restricted_columns :x
301
+ @c.restricted_columns.should == [:x]
302
+ @c.set_restricted_columns :x, :y
303
+ @c.restricted_columns.should == [:x, :y]
304
+ end
305
+
306
+ it "should only set allowed columns by default" do
307
+ @c.set_allowed_columns :x, :y
308
+ i = @c.new(:x => 1, :y => 2, :z => 3)
309
+ i.values.should == {:x => 1, :y => 2}
310
+ i.set(:x => 4, :y => 5, :z => 6)
311
+ i.values.should == {:x => 4, :y => 5}
312
+ i.update(:x => 7, :y => 8, :z => 9)
313
+ i.values.delete(:id) # stupid specs
314
+ i.values.should == {:x => 7, :y => 8}
315
+ end
316
+
317
+ it "should not set restricted columns by default" do
318
+ @c.set_restricted_columns :z
319
+ i = @c.new(:x => 1, :y => 2, :z => 3)
320
+ i.values.should == {:x => 1, :y => 2}
321
+ i.set(:x => 4, :y => 5, :z => 6)
322
+ i.values.should == {:x => 4, :y => 5}
323
+ i.update(:x => 7, :y => 8, :z => 9)
324
+ i.values.delete(:id) # stupid specs
325
+ i.values.should == {:x => 7, :y => 8}
326
+ end
327
+
328
+ it "should have allowed take precedence over restricted" do
329
+ @c.set_allowed_columns :x, :y
330
+ @c.set_restricted_columns :y, :z
331
+ i = @c.new(:x => 1, :y => 2, :z => 3)
332
+ i.values.should == {:x => 1, :y => 2}
333
+ i.set(:x => 4, :y => 5, :z => 6)
334
+ i.values.should == {:x => 4, :y => 5}
335
+ i.update(:x => 7, :y => 8, :z => 9)
336
+ i.values.delete(:id) # stupid specs
337
+ i.values.should == {:x => 7, :y => 8}
338
+ end
339
+ end
340
+
341
+ describe Sequel::Model, ".(un)?restrict_primary_key\\??" do
342
+ setup do
343
+ @c = Class.new(Sequel::Model(:blahblah)) do
344
+ set_primary_key :id
345
+ columns :x, :y, :z, :id
346
+ def refresh
347
+ self
348
+ end
349
+ end
350
+ @c.strict_param_setting = false
351
+ @c.instance_variable_set(:@columns, [:x, :y, :z])
352
+ end
353
+
354
+ it "should restrict updates to primary key by default" do
355
+ i = @c.new(:x => 1, :y => 2, :id => 3)
356
+ i.values.should == {:x => 1, :y => 2}
357
+ i.set(:x => 4, :y => 5, :id => 6)
358
+ i.values.should == {:x => 4, :y => 5}
359
+ end
360
+
361
+ it "should allow updates to primary key if unrestrict_primary_key is used" do
362
+ @c.unrestrict_primary_key
363
+ i = @c.new(:x => 1, :y => 2, :id => 3)
364
+ i.values.should == {:x => 1, :y => 2, :id=>3}
365
+ i.set(:x => 4, :y => 5, :id => 6)
366
+ i.values.should == {:x => 4, :y => 5, :id=>6}
367
+ end
368
+
369
+ it "should have restrict_primary_key? return true or false depending" do
370
+ @c.restrict_primary_key?.should == true
371
+ @c.unrestrict_primary_key
372
+ @c.restrict_primary_key?.should == false
373
+ c1 = Class.new(@c)
374
+ c1.restrict_primary_key?.should == false
375
+ @c.restrict_primary_key
376
+ @c.restrict_primary_key?.should == true
377
+ c1.restrict_primary_key?.should == false
378
+ c2 = Class.new(@c)
379
+ c2.restrict_primary_key?.should == true
380
+ end
381
+ end
382
+
383
+ describe Sequel::Model, ".strict_param_setting" do
384
+ setup do
385
+ @c = Class.new(Sequel::Model(:blahblah)) do
386
+ columns :x, :y, :z, :id
387
+ set_restricted_columns :z
388
+ def refresh
389
+ self
390
+ end
391
+ end
392
+ @c.instance_variable_set(:@columns, [:x, :y, :z])
393
+ end
394
+
395
+ it "should be enabled by default" do
396
+ @c.strict_param_setting.should == true
397
+ end
398
+
399
+ it "should raise an error if a missing/restricted column/method is accessed" do
400
+ proc{@c.new(:z=>1)}.should raise_error(Sequel::Error)
401
+ proc{@c.create(:z=>1)}.should raise_error(Sequel::Error)
402
+ c = @c.new
403
+ proc{c.set(:z=>1)}.should raise_error(Sequel::Error)
404
+ proc{c.set_all(:id=>1)}.should raise_error(Sequel::Error)
405
+ proc{c.set_only({:x=>1}, :y)}.should raise_error(Sequel::Error)
406
+ proc{c.set_except({:x=>1}, :x)}.should raise_error(Sequel::Error)
407
+ proc{c.update(:z=>1)}.should raise_error(Sequel::Error)
408
+ proc{c.update_all(:id=>1)}.should raise_error(Sequel::Error)
409
+ proc{c.update_only({:x=>1}, :y)}.should raise_error(Sequel::Error)
410
+ proc{c.update_except({:x=>1}, :x)}.should raise_error(Sequel::Error)
411
+ end
412
+
413
+ it "should be disabled by strict_param_setting = false" do
414
+ @c.strict_param_setting = false
415
+ @c.strict_param_setting.should == false
416
+ proc{@c.new(:z=>1)}.should_not raise_error
417
+ end
418
+ end
@@ -0,0 +1,66 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Sequel::Model::DatasetMethods, "#destroy" do
4
+ before do
5
+ @c = Class.new(Sequel::Model(:items)) do
6
+ @@destroyed = []
7
+ def destroy
8
+ @@destroyed << self
9
+ end
10
+ def self.destroyed
11
+ @@destroyed
12
+ end
13
+ end
14
+ @d = @c.dataset
15
+ end
16
+
17
+ it "should instantiate objects in the dataset and call destroy on each" do
18
+ def @d.fetch_rows(sql)
19
+ yield({:id=>1})
20
+ yield({:id=>2})
21
+ end
22
+ @d.destroy
23
+ @c.destroyed.collect{|x| x.values}.should == [{:id=>1}, {:id=>2}]
24
+ end
25
+
26
+ it "should return the number of records destroyed" do
27
+ def @d.fetch_rows(sql)
28
+ yield({:id=>1})
29
+ yield({:id=>2})
30
+ end
31
+ @d.destroy.should == 2
32
+ def @d.fetch_rows(sql)
33
+ yield({:id=>1})
34
+ end
35
+ @d.destroy.should == 1
36
+ def @d.fetch_rows(sql)
37
+ end
38
+ @d.destroy.should == 0
39
+ end
40
+ end
41
+
42
+ describe Sequel::Model::DatasetMethods, "#to_hash" do
43
+ before do
44
+ @c = Class.new(Sequel::Model(:items)) do
45
+ set_primary_key :name
46
+ end
47
+ @d = @c.dataset
48
+ end
49
+
50
+ it "should result in a hash with primary key value keys and model object values" do
51
+ def @d.fetch_rows(sql)
52
+ yield({:name=>1})
53
+ yield({:name=>2})
54
+ end
55
+ h = @d.to_hash
56
+ h.should be_a_kind_of(Hash)
57
+ a = h.to_a
58
+ a.collect{|x| x[1].class}.should == [@c, @c]
59
+ [[[1, {:name=>1}], [2, {:name=>2}]], [[2, {:name=>2}], [1, {:name=>1}]]].should(include(a.collect{|x| [x[0], x[1].values]}))
60
+ end
61
+
62
+ it "should raise an error if the class doesn't have a primary key" do
63
+ @c.no_primary_key
64
+ proc{@d.to_hash}.should raise_error(Sequel::Error)
65
+ end
66
+ end
@@ -277,7 +277,7 @@ describe Sequel::Model, "#eager" do
277
277
  a.first.values.should == {:id => 101, :band_id => 101}
278
278
  MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (id = 101)', 'SELECT bands.* FROM bands WHERE (id IN (101))']
279
279
  a = a.first
280
- a.instance_variable_get(:@band).should == :null
280
+ a.associations.fetch(:band, 2).should == nil
281
281
  a.band.should == nil
282
282
  MODEL_DB.sqls.length.should == 2
283
283
  end
@@ -290,10 +290,10 @@ describe Sequel::Model, "#eager" do
290
290
  a.first.values.should == {:id => 101}
291
291
  a.last.values.should == {:id => 102}
292
292
  MODEL_DB.sqls.should == ['SELECT * FROM bands WHERE (id > 100)', 'SELECT albums.* FROM albums WHERE (band_id IN (101, 102))', "SELECT tracks.* FROM tracks WHERE (album_id IN (101))"]
293
- a.first.instance_variable_get(:@albums).should be_a_kind_of(Array)
293
+ a.first.associations[:albums].should be_a_kind_of(Array)
294
294
  a.first.albums.length.should == 1
295
295
  a.first.albums.first.should be_a_kind_of(EagerAlbum)
296
- a.last.instance_variable_get(:@albums).should == []
296
+ a.last.associations[:albums].should == []
297
297
  a.last.albums.should == []
298
298
  MODEL_DB.sqls.length.should == 3
299
299
  end
@@ -384,7 +384,7 @@ describe Sequel::Model, "#eager_graph" do
384
384
 
385
385
  it "should eagerly load a single many_to_one association" do
386
386
  ds = GraphAlbum.eager_graph(:band)
387
- ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands band ON (band.id = albums.band_id)'
387
+ ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
388
388
  def ds.fetch_rows(sql, &block)
389
389
  yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
390
390
  end
@@ -436,7 +436,7 @@ describe Sequel::Model, "#eager_graph" do
436
436
 
437
437
  it "should eagerly load multiple associations" do
438
438
  ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
439
- ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands band ON (band.id = albums.band_id)'
439
+ ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
440
440
  def ds.fetch_rows(sql, &block)
441
441
  yield({:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6})
442
442
  end
@@ -460,7 +460,7 @@ describe Sequel::Model, "#eager_graph" do
460
460
 
461
461
  it "should allow cascading of eager loading for associations of associated models" do
462
462
  ds = GraphTrack.eager_graph(:album=>{:band=>:members})
463
- ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
463
+ ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
464
464
  def ds.fetch_rows(sql, &block)
465
465
  yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6})
466
466
  end
@@ -505,7 +505,7 @@ describe Sequel::Model, "#eager_graph" do
505
505
 
506
506
  it "should eager load multiple associations from the same table" do
507
507
  ds = GraphBand.eager_graph(:vocalist, :members)
508
- ds.sql.should == 'SELECT bands.id, bands.vocalist_id, vocalist.id AS vocalist_id_0, members.id AS members_id FROM bands LEFT OUTER JOIN members vocalist ON (vocalist.id = bands.vocalist_id) LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
508
+ ds.sql.should == 'SELECT bands.id, bands.vocalist_id, vocalist.id AS vocalist_id_0, members.id AS members_id FROM bands LEFT OUTER JOIN members AS vocalist ON (vocalist.id = bands.vocalist_id) LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
509
509
  def ds.fetch_rows(sql, &block)
510
510
  yield({:id=>2, :vocalist_id=>6, :vocalist_id_0=>6, :members_id=>5})
511
511
  end
@@ -525,16 +525,16 @@ describe Sequel::Model, "#eager_graph" do
525
525
 
526
526
  it "should give you a graph of tables when called without .all" do
527
527
  ds = GraphAlbum.eager_graph(:band)
528
- ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands band ON (band.id = albums.band_id)'
528
+ ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
529
529
  def ds.fetch_rows(sql, &block)
530
530
  yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
531
531
  end
532
- ds.first.should == {:albums=>GraphAlbum.new(:id => 1, :band_id => 2), :band=>GraphBand.new(:id => 2, :vocalist_id=>3)}
532
+ ds.first.should == {:albums=>GraphAlbum.load(:id => 1, :band_id => 2), :band=>GraphBand.load(:id => 2, :vocalist_id=>3)}
533
533
  end
534
534
 
535
535
  it "should not drop any associated objects if the graph could not be a cartesian product" do
536
536
  ds = GraphBand.eager_graph(:members, :vocalist)
537
- ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, vocalist.id AS vocalist_id_0 FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN members vocalist ON (vocalist.id = bands.vocalist_id)'
537
+ ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, vocalist.id AS vocalist_id_0 FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN members AS vocalist ON (vocalist.id = bands.vocalist_id)'
538
538
  def ds.fetch_rows(sql, &block)
539
539
  yield({:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6})
540
540
  yield({:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6})
@@ -615,7 +615,7 @@ describe Sequel::Model, "#eager_graph" do
615
615
 
616
616
  it "should handle no associated records for a single many_to_one association" do
617
617
  ds = GraphAlbum.eager_graph(:band)
618
- ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands band ON (band.id = albums.band_id)'
618
+ ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
619
619
  def ds.fetch_rows(sql, &block)
620
620
  yield({:id=>1, :band_id=>2, :band_id_0=>nil, :vocalist_id=>nil})
621
621
  end
@@ -624,7 +624,7 @@ describe Sequel::Model, "#eager_graph" do
624
624
  a.size.should == 1
625
625
  a.first.should be_a_kind_of(GraphAlbum)
626
626
  a.first.values.should == {:id => 1, :band_id => 2}
627
- a.first.instance_variable_get(:@band).should == :null
627
+ a.first.associations.fetch(:band, 2).should == nil
628
628
  end
629
629
 
630
630
  it "should handle no associated records for a single one_to_many association" do
@@ -657,7 +657,7 @@ describe Sequel::Model, "#eager_graph" do
657
657
 
658
658
  it "should handle missing associated records when loading multiple associations" do
659
659
  ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
660
- ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands band ON (band.id = albums.band_id)'
660
+ ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
661
661
  def ds.fetch_rows(sql, &block)
662
662
  yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>3, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
663
663
  yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>4, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
@@ -674,13 +674,13 @@ describe Sequel::Model, "#eager_graph" do
674
674
  a.tracks.size.should == 4
675
675
  a.tracks.first.should be_a_kind_of(GraphTrack)
676
676
  a.tracks.collect{|x|x[:id]}.should == [3,4,5,6]
677
- a.instance_variable_get(:@band).should == :null
677
+ a.associations.fetch(:band, 2).should == nil
678
678
  a.genres.should == []
679
679
  end
680
680
 
681
681
  it "should handle missing associated records when cascading eager loading for associations of associated models" do
682
682
  ds = GraphTrack.eager_graph(:album=>{:band=>:members})
683
- ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
683
+ ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
684
684
  def ds.fetch_rows(sql, &block)
685
685
  yield({:id=>2, :album_id=>2, :album_id_0=>nil, :band_id=>nil, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil})
686
686
  yield({:id=>3, :album_id=>3, :album_id_0=>3, :band_id=>3, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil})
@@ -693,10 +693,10 @@ describe Sequel::Model, "#eager_graph" do
693
693
  a.size.should == 4
694
694
  a.first.should be_a_kind_of(GraphTrack)
695
695
  a.collect{|x|x[:id]}.should == [2,3,4,5]
696
- a[0].instance_variable_get(:@album).should == :null
696
+ a[0].associations.fetch(:album, 2).should == nil
697
697
  a[1].album.should be_a_kind_of(GraphAlbum)
698
698
  a[1].album.values.should == {:id => 3, :band_id => 3}
699
- a[1].album.instance_variable_get(:@band).should == :null
699
+ a[1].album.associations.fetch(:band, 2).should == nil
700
700
  a[2].album.should be_a_kind_of(GraphAlbum)
701
701
  a[2].album.values.should == {:id => 4, :band_id => 2}
702
702
  a[2].album.band.should be_a_kind_of(GraphBand)
@@ -713,33 +713,44 @@ describe Sequel::Model, "#eager_graph" do
713
713
  a[3].album.band.members.last.values.should == {:id => 6}
714
714
  end
715
715
 
716
+ it "should respect the association's :graph_select option" do
717
+ GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :graph_select=>:vocalist_id
718
+ GraphAlbum.eager_graph(:inner_band).sql.should == 'SELECT albums.id, albums.band_id, inner_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS inner_band ON (inner_band.id = albums.band_id)'
719
+
720
+ GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :graph_select=>[:album_id]
721
+ GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.id)'
722
+
723
+ GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_select=>[]
724
+ GraphAlbum.eager_graph(:inner_genres).sql.should == 'SELECT albums.id, albums.band_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS inner_genres ON (inner_genres.id = ag.genre_id)'
725
+ end
726
+
716
727
  it "should respect the association's :graph_join_type option" do
717
728
  GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :graph_join_type=>:inner
718
- GraphAlbum.eager_graph(:inner_band).sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums INNER JOIN bands inner_band ON (inner_band.id = albums.band_id)'
729
+ GraphAlbum.eager_graph(:inner_band).sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums INNER JOIN bands AS inner_band ON (inner_band.id = albums.band_id)'
719
730
 
720
731
  GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :graph_join_type=>:right_outer
721
- GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums RIGHT OUTER JOIN tracks right_tracks ON (right_tracks.album_id = albums.id)'
732
+ GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums RIGHT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.id)'
722
733
 
723
734
  GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_join_type=>:inner
724
- GraphAlbum.eager_graph(:inner_genres).sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres inner_genres ON (inner_genres.id = ag.genre_id)'
735
+ GraphAlbum.eager_graph(:inner_genres).sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres AS inner_genres ON (inner_genres.id = ag.genre_id)'
725
736
  end
726
737
 
727
738
  it "should respect the association's :graph_conditions option" do
728
739
  GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_conditions=>{:active=>true}
729
- GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands active_band ON ((active_band.id = albums.band_id) AND (active_band.active = 't'))"
740
+ GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS active_band ON ((active_band.id = albums.band_id) AND (active_band.active = 't'))"
730
741
 
731
742
  GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_conditions=>{true=>:active}
732
- GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
743
+ GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
733
744
 
734
745
  GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_conditions=>{:id=>(0..100)}
735
- GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands active_band ON ((active_band.id = albums.band_id) AND ((active_band.id >= 0) AND (active_band.id <= 100)))"
746
+ GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS active_band ON ((active_band.id = albums.band_id) AND ((active_band.id >= 0) AND (active_band.id <= 100)))"
736
747
  end
737
748
 
738
749
  it "should respect the association's :graph_join_table_conditions option" do
739
750
  GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_join_table_conditions=>{:active=>true}
740
- GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON ((ag.album_id = albums.id) AND (ag.active = 't')) LEFT OUTER JOIN genres active_genres ON (active_genres.id = ag.genre_id)"
751
+ GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON ((ag.album_id = albums.id) AND (ag.active = 't')) LEFT OUTER JOIN genres AS active_genres ON (active_genres.id = ag.genre_id)"
741
752
 
742
753
  GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_conditions=>{true=>:active}, :graph_join_table_conditions=>{true=>:active}
743
- GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON ((ag.album_id = albums.id) AND ('t' = albums.active)) LEFT OUTER JOIN genres active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
754
+ GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON ((ag.album_id = albums.id) AND ('t' = albums.active)) LEFT OUTER JOIN genres AS active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
744
755
  end
745
756
  end
data/spec/model_spec.rb CHANGED
@@ -25,7 +25,6 @@ describe Sequel::Model do
25
25
  end
26
26
 
27
27
  describe Sequel::Model, "dataset & schema" do
28
-
29
28
  before do
30
29
  @model = Class.new(Sequel::Model(:items))
31
30
  end
@@ -80,9 +79,57 @@ describe Sequel::Model, "dataset & schema" do
80
79
  @model.primary_key.should == :id
81
80
  @model.table_name.should == :foo
82
81
  end
82
+ end
83
83
 
84
- it "puts the lotion in the basket or it gets the hose again" do
85
- # just kidding!
84
+ describe Sequel::Model, "#sti_key" do
85
+ before do
86
+ class StiTest < Sequel::Model
87
+ def kind=(x); self[:kind] = x; end
88
+ def refresh; end
89
+ set_sti_key :kind
90
+ end
91
+ class StiTestSub1 < StiTest
92
+ end
93
+ class StiTestSub2 < StiTest
94
+ end
95
+ @ds = StiTest.dataset
96
+ MODEL_DB.reset
97
+ end
98
+
99
+ it "should return rows with the correct class based on the polymorphic_key value" do
100
+ def @ds.fetch_rows(sql)
101
+ yield({:kind=>'StiTest'})
102
+ yield({:kind=>'StiTestSub1'})
103
+ yield({:kind=>'StiTestSub2'})
104
+ end
105
+ StiTest.all.collect{|x| x.class}.should == [StiTest, StiTestSub1, StiTestSub2]
106
+ end
107
+
108
+ it "should fallback to the main class if polymophic_key value is NULL" do
109
+ def @ds.fetch_rows(sql)
110
+ yield({:kind=>nil})
111
+ end
112
+ StiTest.all.collect{|x| x.class}.should == [StiTest]
113
+ end
114
+
115
+ it "should fallback to the main class if the given class does not exist" do
116
+ def @ds.fetch_rows(sql)
117
+ yield({:kind=>'StiTestSub3'})
118
+ end
119
+ StiTest.all.collect{|x| x.class}.should == [StiTest]
120
+ end
121
+
122
+ it "should add a before_create hook that sets the model class name for the key" do
123
+ StiTest.new.save
124
+ StiTestSub1.new.save
125
+ StiTestSub2.new.save
126
+ MODEL_DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTest')", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub2')"]
127
+ end
128
+
129
+ it "should add a filter to model datasets inside subclasses hook to only retreive objects with the matching key" do
130
+ StiTest.dataset.sql.should == "SELECT * FROM sti_tests"
131
+ StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (kind = 'StiTestSub1')"
132
+ StiTestSub2.dataset.sql.should == "SELECT * FROM sti_tests WHERE (kind = 'StiTestSub2')"
86
133
  end
87
134
  end
88
135
 
@@ -152,8 +199,7 @@ describe Sequel::Model, "new" do
152
199
  end
153
200
 
154
201
  describe Sequel::Model, ".subset" do
155
-
156
- before(:each) do
202
+ before do
157
203
  MODEL_DB.reset
158
204
 
159
205
  @c = Class.new(Sequel::Model(:items))
@@ -172,7 +218,6 @@ describe Sequel::Model, ".subset" do
172
218
  @c.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
173
219
  @c.dataset.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
174
220
 
175
- # check if subsets are composable
176
221
  @c.pricey.new_only.sql.should == "SELECT * FROM items WHERE ((price > 100) AND (age = 'new'))"
177
222
  @c.new_only.pricey.sql.should == "SELECT * FROM items WHERE ((age = 'new') AND (price > 100))"
178
223
  end