sequel 3.22.0 → 3.23.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/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
|