sequel 3.22.0 → 3.23.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +28 -0
- data/README.rdoc +15 -1
- data/doc/association_basics.rdoc +121 -40
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +2 -2
- data/lib/sequel/model/associations.rb +168 -32
- data/lib/sequel/model/base.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +2 -2
- data/lib/sequel/plugins/many_through_many.rb +28 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/spec_helper.rb +5 -0
- data/spec/core/spec_helper.rb +5 -0
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/many_through_many_spec.rb +21 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
- data/spec/extensions/spec_helper.rb +3 -1
- data/spec/extensions/xml_serializer_spec.rb +12 -0
- data/spec/integration/associations_test.rb +58 -0
- data/spec/integration/plugin_test.rb +15 -0
- data/spec/integration/spec_helper.rb +5 -0
- data/spec/model/associations_spec.rb +117 -0
- data/spec/model/eager_loading_spec.rb +269 -1
- data/spec/model/record_spec.rb +6 -0
- data/spec/model/spec_helper.rb +5 -0
- metadata +10 -4
@@ -163,6 +163,12 @@ describe Sequel::Model, "#eager" do
|
|
163
163
|
MODEL_DB.sqls.length.should == 2
|
164
164
|
end
|
165
165
|
|
166
|
+
it "should correctly handle a :select=>[] option to many_to_many" do
|
167
|
+
EagerAlbum.many_to_many :sgenres, :clone=>:genres, :select=>[]
|
168
|
+
a = EagerAlbum.eager(:sgenres).all
|
169
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
170
|
+
end
|
171
|
+
|
166
172
|
it "should eagerly load multiple associations in a single call" do
|
167
173
|
a = EagerAlbum.eager(:genres, :tracks, :band).all
|
168
174
|
a.should be_a_kind_of(Array)
|
@@ -646,6 +652,148 @@ describe Sequel::Model, "#eager" do
|
|
646
652
|
a.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
647
653
|
a.al_genres.should == [EagerGenre.load(:id=>4)]
|
648
654
|
end
|
655
|
+
|
656
|
+
it "should eagerly load a many_to_one association with custom eager block" do
|
657
|
+
a = EagerAlbum.eager(:band => proc {|ds| ds.select(:id, :name)}).all
|
658
|
+
a.should be_a_kind_of(Array)
|
659
|
+
a.size.should == 1
|
660
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
661
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
662
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id, name FROM bands WHERE (bands.id IN (2))']
|
663
|
+
a = a.first
|
664
|
+
a.band.should be_a_kind_of(EagerBand)
|
665
|
+
a.band.values.should == {:id => 2}
|
666
|
+
MODEL_DB.sqls.length.should == 2
|
667
|
+
end
|
668
|
+
|
669
|
+
it "should eagerly load a one_to_one association with custom eager block" do
|
670
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id
|
671
|
+
a = EagerAlbum.eager(:track => proc {|ds| ds.select(:id)}).all
|
672
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
673
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id FROM tracks WHERE (tracks.album_id IN (1))']
|
674
|
+
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
675
|
+
MODEL_DB.sqls.length.should == 2
|
676
|
+
end
|
677
|
+
|
678
|
+
it "should eagerly load a one_to_many association with custom eager block" do
|
679
|
+
a = EagerAlbum.eager(:tracks => proc {|ds| ds.select(:id)}).all
|
680
|
+
a.should be_a_kind_of(Array)
|
681
|
+
a.size.should == 1
|
682
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
683
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
684
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id FROM tracks WHERE (tracks.album_id IN (1))']
|
685
|
+
a = a.first
|
686
|
+
a.tracks.should be_a_kind_of(Array)
|
687
|
+
a.tracks.size.should == 1
|
688
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
689
|
+
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
690
|
+
MODEL_DB.sqls.length.should == 2
|
691
|
+
end
|
692
|
+
|
693
|
+
it "should eagerly load a many_to_many association with custom eager block" do
|
694
|
+
a = EagerAlbum.eager(:genres => proc {|ds| ds.select(:name)}).all
|
695
|
+
a.should be_a_kind_of(Array)
|
696
|
+
a.size.should == 1
|
697
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
698
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
699
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
700
|
+
a = a.first
|
701
|
+
a.genres.should be_a_kind_of(Array)
|
702
|
+
a.genres.size.should == 1
|
703
|
+
a.genres.first.should be_a_kind_of(EagerGenre)
|
704
|
+
a.genres.first.values.should == {:id => 4}
|
705
|
+
MODEL_DB.sqls.length.should == 2
|
706
|
+
end
|
707
|
+
|
708
|
+
it "should allow cascading of eager loading within a custom eager block" do
|
709
|
+
a = EagerTrack.eager(:album => proc {|ds| ds.eager(:band => :members)}).all
|
710
|
+
a.should be_a_kind_of(Array)
|
711
|
+
a.size.should == 1
|
712
|
+
a.first.should be_a_kind_of(EagerTrack)
|
713
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
714
|
+
MODEL_DB.sqls.length.should == 4
|
715
|
+
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
716
|
+
'SELECT * FROM albums WHERE (albums.id IN (1))',
|
717
|
+
'SELECT * FROM bands WHERE (bands.id IN (2))',
|
718
|
+
"SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
|
719
|
+
a = a.first
|
720
|
+
a.album.should be_a_kind_of(EagerAlbum)
|
721
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
722
|
+
a.album.band.should be_a_kind_of(EagerBand)
|
723
|
+
a.album.band.values.should == {:id => 2}
|
724
|
+
a.album.band.members.should be_a_kind_of(Array)
|
725
|
+
a.album.band.members.size.should == 1
|
726
|
+
a.album.band.members.first.should be_a_kind_of(EagerBandMember)
|
727
|
+
a.album.band.members.first.values.should == {:id => 5}
|
728
|
+
MODEL_DB.sqls.length.should == 4
|
729
|
+
end
|
730
|
+
|
731
|
+
it "should allow cascading of eager loading with custom callback with hash value" do
|
732
|
+
a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>{:band => :members}}).all
|
733
|
+
a.should be_a_kind_of(Array)
|
734
|
+
a.size.should == 1
|
735
|
+
a.first.should be_a_kind_of(EagerTrack)
|
736
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
737
|
+
MODEL_DB.sqls.length.should == 4
|
738
|
+
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
739
|
+
'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
|
740
|
+
'SELECT * FROM bands WHERE (bands.id IN (2))',
|
741
|
+
"SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
|
742
|
+
a = a.first
|
743
|
+
a.album.should be_a_kind_of(EagerAlbum)
|
744
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
745
|
+
a.album.band.should be_a_kind_of(EagerBand)
|
746
|
+
a.album.band.values.should == {:id => 2}
|
747
|
+
a.album.band.members.should be_a_kind_of(Array)
|
748
|
+
a.album.band.members.size.should == 1
|
749
|
+
a.album.band.members.first.should be_a_kind_of(EagerBandMember)
|
750
|
+
a.album.band.members.first.values.should == {:id => 5}
|
751
|
+
MODEL_DB.sqls.length.should == 4
|
752
|
+
end
|
753
|
+
|
754
|
+
it "should allow cascading of eager loading with custom callback with symbol value" do
|
755
|
+
a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>:band}).all
|
756
|
+
a.should be_a_kind_of(Array)
|
757
|
+
a.size.should == 1
|
758
|
+
a.first.should be_a_kind_of(EagerTrack)
|
759
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
760
|
+
MODEL_DB.sqls.length.should == 3
|
761
|
+
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
762
|
+
'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
|
763
|
+
'SELECT * FROM bands WHERE (bands.id IN (2))']
|
764
|
+
a = a.first
|
765
|
+
a.album.should be_a_kind_of(EagerAlbum)
|
766
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
767
|
+
a.album.band.should be_a_kind_of(EagerBand)
|
768
|
+
a.album.band.values.should == {:id => 2}
|
769
|
+
MODEL_DB.sqls.length.should == 3
|
770
|
+
end
|
771
|
+
|
772
|
+
it "should allow cascading of eager loading with custom callback with array value" do
|
773
|
+
a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>[:band, :band_name]}).all
|
774
|
+
a.should be_a_kind_of(Array)
|
775
|
+
a.size.should == 1
|
776
|
+
a.first.should be_a_kind_of(EagerTrack)
|
777
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
778
|
+
MODEL_DB.sqls.length.should == 4
|
779
|
+
MODEL_DB.sqls[0..1].should == ['SELECT * FROM tracks',
|
780
|
+
'SELECT id, band_id FROM albums WHERE (albums.id IN (1))']
|
781
|
+
MODEL_DB.sqls[2..-1].sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
|
782
|
+
'SELECT id, name FROM bands WHERE (bands.id IN (2))']
|
783
|
+
a = a.first
|
784
|
+
a.album.should be_a_kind_of(EagerAlbum)
|
785
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
786
|
+
a.album.band.should be_a_kind_of(EagerBand)
|
787
|
+
a.album.band.values.should == {:id => 2}
|
788
|
+
a.album.band_name.should be_a_kind_of(EagerBand)
|
789
|
+
a.album.band_name.values.should == {:id => 2}
|
790
|
+
MODEL_DB.sqls.length.should == 4
|
791
|
+
end
|
792
|
+
|
793
|
+
it "should call both association and custom eager blocks" do
|
794
|
+
EagerBand.eager(:good_albums => proc {|ds| ds.select(:name)}).all
|
795
|
+
MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT name FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))"]
|
796
|
+
end
|
649
797
|
end
|
650
798
|
|
651
799
|
describe Sequel::Model, "#eager_graph" do
|
@@ -664,6 +812,11 @@ describe Sequel::Model, "#eager_graph" do
|
|
664
812
|
c.instance_variable_set(:@columns, (@columns.dup if @columns))
|
665
813
|
c
|
666
814
|
end
|
815
|
+
def select_columns(*a)
|
816
|
+
ds = select(*a)
|
817
|
+
ds.instance_variable_set(:@columns, a)
|
818
|
+
ds
|
819
|
+
end
|
667
820
|
end
|
668
821
|
|
669
822
|
class ::GraphAlbum < Sequel::Model(:albums)
|
@@ -1284,13 +1437,17 @@ describe Sequel::Model, "#eager_graph" do
|
|
1284
1437
|
GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :eager_grapher=>proc{|ds, aa, ta| ds.graph(GraphBand, {:active=>true}, :table_alias=>aa, :join_type=>:inner)}
|
1285
1438
|
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 INNER JOIN bands AS active_band ON (active_band.active IS TRUE)"
|
1286
1439
|
|
1287
|
-
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :eager_grapher=>proc{|
|
1440
|
+
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :eager_grapher=>proc{|eo| eo[:self].graph(GraphTrack, nil, :join_type=>:natural, :table_alias=>eo[:table_alias])}
|
1288
1441
|
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 NATURAL JOIN tracks AS right_tracks'
|
1289
1442
|
|
1290
1443
|
GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :eager_grapher=>proc{|ds, aa, ta| ds.graph(:ag, {:album_id=>:id}, :table_alias=>:a123, :implicit_qualifier=>ta).graph(GraphGenre, [:album_id], :table_alias=>aa)}
|
1291
1444
|
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 AS a123 ON (a123.album_id = albums.id) LEFT OUTER JOIN genres AS active_genres USING (album_id)"
|
1292
1445
|
end
|
1293
1446
|
|
1447
|
+
it "should raise an error if you use an :eager_grapher proc with the wrong arity" do
|
1448
|
+
proc{GraphAlbum.many_to_one :special_band, :eager_grapher=>proc{|a, b|}}.should raise_error(Sequel::Error)
|
1449
|
+
end
|
1450
|
+
|
1294
1451
|
it "should respect the association's :graph_only_conditions option" do
|
1295
1452
|
GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_only_conditions=>{:active=>true}
|
1296
1453
|
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.active IS TRUE)"
|
@@ -1367,6 +1524,8 @@ describe Sequel::Model, "#eager_graph" do
|
|
1367
1524
|
as = ds.all
|
1368
1525
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
1369
1526
|
as.first.inner_genres.should == [GraphGenre.load(:id=>5), GraphGenre.load(:id=>6)]
|
1527
|
+
GraphAlbum.set_primary_key :id
|
1528
|
+
GraphGenre.set_primary_key :id
|
1370
1529
|
end
|
1371
1530
|
|
1372
1531
|
it "should handle eager loading with schemas and aliases of different types" do
|
@@ -1392,4 +1551,113 @@ describe Sequel::Model, "#eager_graph" do
|
|
1392
1551
|
ds = c1.join(:s__t, [:b_id]).eager_graph(:a_genres)
|
1393
1552
|
ds.sql.should == 'SELECT a.id, a_genres.id AS a_genres_id FROM (SELECT * FROM s.a INNER JOIN s.t USING (b_id)) AS a LEFT OUTER JOIN s.ag AS ag ON (ag.album_id = a.id) LEFT OUTER JOIN s.g AS a_genres ON (a_genres.id = ag.genre_id)'
|
1394
1553
|
end
|
1554
|
+
|
1555
|
+
it "should eagerly load a many_to_one association with a custom callback" do
|
1556
|
+
ds = GraphAlbum.eager_graph(:band => proc {|ds| ds.select_columns(:id)})
|
1557
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0 FROM albums LEFT OUTER JOIN (SELECT id FROM bands) AS band ON (band.id = albums.band_id)'
|
1558
|
+
def ds.fetch_rows(sql, &block)
|
1559
|
+
yield({:id=>1, :band_id=>2, :band_id_0=>2})
|
1560
|
+
end
|
1561
|
+
a = ds.all
|
1562
|
+
a.should be_a_kind_of(Array)
|
1563
|
+
a.size.should == 1
|
1564
|
+
a.first.should be_a_kind_of(GraphAlbum)
|
1565
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
1566
|
+
a = a.first
|
1567
|
+
a.band.should be_a_kind_of(GraphBand)
|
1568
|
+
a.band.values.should == {:id => 2}
|
1569
|
+
end
|
1570
|
+
|
1571
|
+
it "should eagerly load a one_to_one association with a custom callback" do
|
1572
|
+
GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
1573
|
+
ds = GraphAlbum.eager_graph(:track => proc {|ds| ds.select_columns(:album_id)})
|
1574
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, track.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS track ON (track.album_id = albums.id)'
|
1575
|
+
def ds.fetch_rows(sql, &block)
|
1576
|
+
yield({:id=>1, :band_id=>2, :album_id=>1})
|
1577
|
+
end
|
1578
|
+
a = ds.all
|
1579
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1580
|
+
a.first.track.should == GraphTrack.load(:album_id=>1)
|
1581
|
+
end
|
1582
|
+
|
1583
|
+
it "should eagerly load a one_to_many association with a custom callback" do
|
1584
|
+
ds = GraphAlbum.eager_graph(:tracks => proc {|ds| ds.select_columns(:album_id)})
|
1585
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS tracks ON (tracks.album_id = albums.id)'
|
1586
|
+
def ds.fetch_rows(sql, &block)
|
1587
|
+
yield({:id=>1, :band_id=>2, :album_id=>1})
|
1588
|
+
end
|
1589
|
+
a = ds.all
|
1590
|
+
a.should be_a_kind_of(Array)
|
1591
|
+
a.size.should == 1
|
1592
|
+
a.first.should be_a_kind_of(GraphAlbum)
|
1593
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
1594
|
+
a = a.first
|
1595
|
+
a.tracks.should be_a_kind_of(Array)
|
1596
|
+
a.tracks.size.should == 1
|
1597
|
+
a.tracks.first.should be_a_kind_of(GraphTrack)
|
1598
|
+
a.tracks.first.values.should == {:album_id=>1}
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
it "should eagerly load a many_to_many association with a custom callback" do
|
1602
|
+
ds = GraphAlbum.eager_graph(:genres => proc {|ds| ds.select_columns(:id)})
|
1603
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN (SELECT id FROM genres) AS genres ON (genres.id = ag.genre_id)'
|
1604
|
+
def ds.fetch_rows(sql, &block)
|
1605
|
+
yield({:id=>1, :band_id=>2, :genres_id=>4})
|
1606
|
+
end
|
1607
|
+
a = ds.all
|
1608
|
+
a.should be_a_kind_of(Array)
|
1609
|
+
a.size.should == 1
|
1610
|
+
a.first.should be_a_kind_of(GraphAlbum)
|
1611
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
1612
|
+
a = a.first
|
1613
|
+
a.genres.should be_a_kind_of(Array)
|
1614
|
+
a.genres.size.should == 1
|
1615
|
+
a.genres.first.should be_a_kind_of(GraphGenre)
|
1616
|
+
a.genres.first.values.should == {:id => 4}
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
it "should allow cascading of eager loading with a custom callback with hash value" do
|
1620
|
+
ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select_columns(:id, :band_id)}=>{:band=>:members}})
|
1621
|
+
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 (SELECT id, band_id FROM 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)'
|
1622
|
+
def ds.fetch_rows(sql, &block)
|
1623
|
+
yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6})
|
1624
|
+
end
|
1625
|
+
a = ds.all
|
1626
|
+
a.should be_a_kind_of(Array)
|
1627
|
+
a.size.should == 1
|
1628
|
+
a.first.should be_a_kind_of(GraphTrack)
|
1629
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
1630
|
+
a = a.first
|
1631
|
+
a.album.should be_a_kind_of(GraphAlbum)
|
1632
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
1633
|
+
a.album.band.should be_a_kind_of(GraphBand)
|
1634
|
+
a.album.band.values.should == {:id => 2, :vocalist_id=>6}
|
1635
|
+
a.album.band.members.should be_a_kind_of(Array)
|
1636
|
+
a.album.band.members.size.should == 1
|
1637
|
+
a.album.band.members.first.should be_a_kind_of(GraphBandMember)
|
1638
|
+
a.album.band.members.first.values.should == {:id => 5}
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
it "should allow cascading of eager loading with a custom callback with array value" do
|
1642
|
+
ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select_columns(:id, :band_id)}=>[:band, :tracks]})
|
1643
|
+
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, tracks_0.id AS tracks_0_id, tracks_0.album_id AS tracks_0_album_id FROM tracks LEFT OUTER JOIN (SELECT id, band_id FROM albums) AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN tracks AS tracks_0 ON (tracks_0.album_id = album.id)'
|
1644
|
+
def ds.fetch_rows(sql, &block)
|
1645
|
+
yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>6, :tracks_0_id=>3, :tracks_0_album_id=>1})
|
1646
|
+
end
|
1647
|
+
a = ds.all
|
1648
|
+
a.should be_a_kind_of(Array)
|
1649
|
+
a.size.should == 1
|
1650
|
+
a.first.should be_a_kind_of(GraphTrack)
|
1651
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
1652
|
+
a = a.first
|
1653
|
+
a.album.should be_a_kind_of(GraphAlbum)
|
1654
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
1655
|
+
a.album.band.should be_a_kind_of(GraphBand)
|
1656
|
+
a.album.band.values.should == {:id => 2, :vocalist_id=>6}
|
1657
|
+
a.album.tracks.should be_a_kind_of(Array)
|
1658
|
+
a.album.tracks.size.should == 1
|
1659
|
+
a.album.tracks.first.should be_a_kind_of(GraphTrack)
|
1660
|
+
a.album.tracks.first.values.should == {:id => 3, :album_id => 1}
|
1661
|
+
end
|
1662
|
+
|
1395
1663
|
end
|
data/spec/model/record_spec.rb
CHANGED
@@ -63,6 +63,12 @@ describe "Model#save" do
|
|
63
63
|
MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2)"]
|
64
64
|
end
|
65
65
|
|
66
|
+
it "should not use dataset's insert_select method if specific columns are selected" do
|
67
|
+
ds = @c.dataset = @c.dataset.select(:y)
|
68
|
+
ds.should_not_receive(:insert_select)
|
69
|
+
@c.new(:x => 1).save
|
70
|
+
end
|
71
|
+
|
66
72
|
it "should use value returned by insert as the primary key and refresh the object" do
|
67
73
|
@c.dataset.meta_def(:insert){|h| super(h); 13}
|
68
74
|
o = @c.new(:x => 11)
|
data/spec/model/spec_helper.rb
CHANGED
@@ -8,6 +8,11 @@ unless Sequel.const_defined?('Model')
|
|
8
8
|
require 'sequel/model'
|
9
9
|
end
|
10
10
|
|
11
|
+
if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
12
|
+
Sequel.extension :columns_introspection
|
13
|
+
Sequel::Dataset.introspect_all_columns
|
14
|
+
end
|
15
|
+
|
11
16
|
class MockDataset < Sequel::Dataset
|
12
17
|
def insert(*args)
|
13
18
|
@db.execute insert_sql(*args)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 91
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 3
|
8
|
-
-
|
8
|
+
- 23
|
9
9
|
- 0
|
10
|
-
version: 3.
|
10
|
+
version: 3.23.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Evans
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-05-02 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -86,6 +86,7 @@ extra_rdoc_files:
|
|
86
86
|
- doc/release_notes/3.20.0.txt
|
87
87
|
- doc/release_notes/3.21.0.txt
|
88
88
|
- doc/release_notes/3.22.0.txt
|
89
|
+
- doc/release_notes/3.23.0.txt
|
89
90
|
files:
|
90
91
|
- MIT-LICENSE
|
91
92
|
- CHANGELOG
|
@@ -139,6 +140,7 @@ files:
|
|
139
140
|
- doc/release_notes/3.20.0.txt
|
140
141
|
- doc/release_notes/3.21.0.txt
|
141
142
|
- doc/release_notes/3.22.0.txt
|
143
|
+
- doc/release_notes/3.23.0.txt
|
142
144
|
- doc/sharding.rdoc
|
143
145
|
- doc/sql.rdoc
|
144
146
|
- doc/virtual_rows.rdoc
|
@@ -218,6 +220,8 @@ files:
|
|
218
220
|
- spec/extensions/xml_serializer_spec.rb
|
219
221
|
- spec/extensions/to_dot_spec.rb
|
220
222
|
- spec/extensions/association_autoreloading_spec.rb
|
223
|
+
- spec/extensions/serialization_modification_detection_spec.rb
|
224
|
+
- spec/extensions/columns_introspection_spec.rb
|
221
225
|
- spec/integration/associations_test.rb
|
222
226
|
- spec/integration/database_test.rb
|
223
227
|
- spec/integration/dataset_test.rb
|
@@ -366,6 +370,7 @@ files:
|
|
366
370
|
- lib/sequel/extensions/string_date_time.rb
|
367
371
|
- lib/sequel/extensions/thread_local_timezones.rb
|
368
372
|
- lib/sequel/extensions/to_dot.rb
|
373
|
+
- lib/sequel/extensions/columns_introspection.rb
|
369
374
|
- lib/sequel/metaprogramming.rb
|
370
375
|
- lib/sequel/model.rb
|
371
376
|
- lib/sequel/model/associations.rb
|
@@ -412,6 +417,7 @@ files:
|
|
412
417
|
- lib/sequel/plugins/tree.rb
|
413
418
|
- lib/sequel/plugins/xml_serializer.rb
|
414
419
|
- lib/sequel/plugins/association_autoreloading.rb
|
420
|
+
- lib/sequel/plugins/serialization_modification_detection.rb
|
415
421
|
- lib/sequel/sql.rb
|
416
422
|
- lib/sequel/timezones.rb
|
417
423
|
- lib/sequel/version.rb
|