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/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