sequel 4.2.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +28 -0
  3. data/doc/extensions.rdoc +84 -0
  4. data/doc/model_plugins.rdoc +270 -0
  5. data/doc/release_notes/4.3.0.txt +40 -0
  6. data/doc/testing.rdoc +3 -0
  7. data/lib/sequel/adapters/jdbc/as400.rb +4 -0
  8. data/lib/sequel/adapters/shared/mysql.rb +6 -1
  9. data/lib/sequel/adapters/shared/postgres.rb +2 -0
  10. data/lib/sequel/ast_transformer.rb +2 -0
  11. data/lib/sequel/extensions/error_sql.rb +71 -0
  12. data/lib/sequel/extensions/migration.rb +0 -1
  13. data/lib/sequel/extensions/pagination.rb +6 -2
  14. data/lib/sequel/extensions/pg_array.rb +12 -5
  15. data/lib/sequel/extensions/pg_hstore.rb +5 -3
  16. data/lib/sequel/extensions/pg_inet.rb +3 -3
  17. data/lib/sequel/extensions/pg_interval.rb +3 -3
  18. data/lib/sequel/extensions/pg_json.rb +3 -3
  19. data/lib/sequel/extensions/pg_range.rb +3 -3
  20. data/lib/sequel/extensions/pg_row.rb +3 -3
  21. data/lib/sequel/extensions/server_block.rb +11 -3
  22. data/lib/sequel/plugins/rcte_tree.rb +59 -39
  23. data/lib/sequel/plugins/tree.rb +13 -6
  24. data/lib/sequel/sql.rb +1 -1
  25. data/lib/sequel/version.rb +1 -1
  26. data/spec/adapters/postgres_spec.rb +17 -0
  27. data/spec/core/dataset_spec.rb +14 -0
  28. data/spec/core/schema_spec.rb +1 -0
  29. data/spec/extensions/error_sql_spec.rb +20 -0
  30. data/spec/extensions/migration_spec.rb +15 -0
  31. data/spec/extensions/pagination_spec.rb +19 -0
  32. data/spec/extensions/pg_array_spec.rb +3 -2
  33. data/spec/extensions/rcte_tree_spec.rb +135 -0
  34. data/spec/extensions/tree_spec.rb +130 -0
  35. data/spec/integration/database_test.rb +5 -0
  36. data/spec/integration/dataset_test.rb +4 -0
  37. data/spec/integration/plugin_test.rb +163 -177
  38. data/spec/integration/spec_helper.rb +4 -0
  39. metadata +10 -2
@@ -24,6 +24,11 @@ describe Sequel::Database do
24
24
  proc{@db << "SELECT"}.should raise_error(Sequel::DatabaseError)
25
25
  end
26
26
 
27
+ specify "should have Sequel::DatabaseError#sql give the SQL causing the error" do
28
+ (@db << "SELECT") rescue (e = $!)
29
+ e.sql.should == "SELECT"
30
+ end if ENV['SEQUEL_ERROR_SQL']
31
+
27
32
  describe "constraint violations" do
28
33
  before do
29
34
  @db.drop_table?(:test2, :test)
@@ -371,6 +371,10 @@ describe Sequel::Database do
371
371
  DB.get(Sequel.cast(Sequel.blob("\1\2\3"), File).as(:a)).should == "\1\2\3"
372
372
  end
373
373
 
374
+ cspecify "should properly handle empty blobs", [:jdbc, :hsqldb], :oracle do
375
+ DB.get(Sequel.cast(Sequel.blob(""), File).as(:a)).should == ""
376
+ end
377
+
374
378
  cspecify "should properly escape identifiers", :db2, :oracle do
375
379
  DB.create_table(:"\\'\"[]"){Integer :id}
376
380
  DB.drop_table(:"\\'\"[]")
@@ -705,43 +705,8 @@ describe "Composition plugin" do
705
705
  end
706
706
  end
707
707
 
708
- # DB2's implemention of CTE is too limited to use this plugin
709
- if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
710
- describe "RcteTree Plugin" do
711
- before(:all) do
712
- @db = DB
713
- @db.create_table!(:nodes) do
714
- primary_key :id
715
- Integer :parent_id
716
- String :name
717
- end
718
- class ::Node < Sequel::Model(@db)
719
- plugin :rcte_tree, :order=>:name
720
- end
721
-
722
- @nodes = []
723
- @nodes << @a = Node.create(:name=>'a')
724
- @nodes << @b = Node.create(:name=>'b')
725
- @nodes << @aa = Node.create(:name=>'aa', :parent=>@a)
726
- @nodes << @ab = Node.create(:name=>'ab', :parent=>@a)
727
- @nodes << @ba = Node.create(:name=>'ba', :parent=>@b)
728
- @nodes << @bb = Node.create(:name=>'bb', :parent=>@b)
729
- @nodes << @aaa = Node.create(:name=>'aaa', :parent=>@aa)
730
- @nodes << @aab = Node.create(:name=>'aab', :parent=>@aa)
731
- @nodes << @aba = Node.create(:name=>'aba', :parent=>@ab)
732
- @nodes << @abb = Node.create(:name=>'abb', :parent=>@ab)
733
- @nodes << @aaaa = Node.create(:name=>'aaaa', :parent=>@aaa)
734
- @nodes << @aaab = Node.create(:name=>'aaab', :parent=>@aaa)
735
- @nodes << @aaaaa = Node.create(:name=>'aaaaa', :parent=>@aaaa)
736
- end
737
- before do
738
- @nodes.each{|n| n.associations.clear}
739
- end
740
- after(:all) do
741
- @db.drop_table? :nodes
742
- Object.send(:remove_const, :Node)
743
- end
744
-
708
+ describe "RcteTree Plugin" do
709
+ shared_examples_for "rcte tree plugin" do
745
710
  specify "should load all standard (not-CTE) methods correctly" do
746
711
  @a.children.should == [@aa, @ab]
747
712
  @b.children.should == [@ba, @bb]
@@ -803,7 +768,7 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
803
768
  end
804
769
 
805
770
  specify "should eagerly load all ancestors and descendants for a dataset" do
806
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
771
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:ancestors, :descendants).all
807
772
  nodes.should == [@a, @aaa, @b]
808
773
  nodes[0].descendants.should == [@aa, @aaa, @aaaa, @aaaaa, @aaab, @aab, @ab, @aba, @abb]
809
774
  nodes[1].descendants.should == [@aaaa, @aaaaa, @aaab]
@@ -813,26 +778,14 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
813
778
  nodes[2].ancestors.should == []
814
779
  end
815
780
 
816
- specify "should work correctly if not all columns are selected" do
817
- c = Class.new(Sequel::Model(@db[:nodes]))
818
- c.plugin :rcte_tree, :order=>:name
819
- c.plugin :lazy_attributes, :name
820
- c[:name=>'aaaa'].descendants.should == [c.load(:parent_id=>11, :id=>13)]
821
- c[:name=>'aa'].ancestors.should == [c.load(:parent_id=>nil, :id=>1)]
822
- nodes = c.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
823
- nodes.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| c.load(x)}
824
- nodes[2].descendants.should == [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| c.load(x)}
825
- nodes[1].ancestors.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| c.load(x)}
826
- end
827
-
828
781
  specify "should eagerly load descendants to a given level" do
829
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:descendants=>1).all
782
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>1).all
830
783
  nodes.should == [@a, @aaa, @b]
831
784
  nodes[0].descendants.should == [@aa, @ab]
832
785
  nodes[1].descendants.should == [@aaaa, @aaab]
833
786
  nodes[2].descendants.should == [@ba, @bb]
834
787
 
835
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:descendants=>2).all
788
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>2).all
836
789
  nodes.should == [@a, @aaa, @b]
837
790
  nodes[0].descendants.should == [@aa, @aaa, @aab, @ab, @aba, @abb]
838
791
  nodes[1].descendants.should == [@aaaa, @aaaaa, @aaab]
@@ -840,7 +793,7 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
840
793
  end
841
794
 
842
795
  specify "should populate all :children associations when eagerly loading descendants for a dataset" do
843
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:descendants).all
796
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants).all
844
797
  nodes[0].associations[:children].should == [@aa, @ab]
845
798
  nodes[1].associations[:children].should == [@aaaa, @aaab]
846
799
  nodes[2].associations[:children].should == [@ba, @bb]
@@ -854,7 +807,7 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
854
807
  end
855
808
 
856
809
  specify "should not populate :children associations for final level when loading descendants to a given level" do
857
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:descendants=>1).all
810
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>1).all
858
811
  nodes[0].associations[:children].should == [@aa, @ab]
859
812
  nodes[0].associations[:children].map{|c1| c1.associations[:children]}.should == [nil, nil]
860
813
  nodes[1].associations[:children].should == [@aaaa, @aaab]
@@ -866,7 +819,7 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
866
819
  nodes[1].associations[:children].map{|c1| c1.children}.should == [[@aaaaa], []]
867
820
  nodes[2].associations[:children].map{|c1| c1.children}.should == [[], []]
868
821
 
869
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:descendants=>2).all
822
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>2).all
870
823
  nodes[0].associations[:children].should == [@aa, @ab]
871
824
  nodes[0].associations[:children].map{|c1| c1.associations[:children]}.should == [[@aaa, @aab], [@aba, @abb]]
872
825
  nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.should == [[[@aaaa, @aaab], nil], [nil, nil]]
@@ -904,7 +857,7 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
904
857
  end
905
858
 
906
859
  specify "should populate all :parent associations when eagerly loading ancestors for a dataset" do
907
- nodes = Node.filter(:id=>[@a.id, @ba.id, @aaa.id, @aaaaa.id]).order(:name).eager(:ancestors).all
860
+ nodes = @Node.filter(@Node.primary_key=>[@a.pk, @ba.pk, @aaa.pk, @aaaaa.pk]).order(:name).eager(:ancestors).all
908
861
  nodes[0].associations.fetch(:parent, 1).should == nil
909
862
  nodes[1].associations[:parent].should == @aa
910
863
  nodes[1].associations[:parent].associations[:parent].should == @a
@@ -937,7 +890,91 @@ if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
937
890
  @aaaaa.associations[:parent].associations[:parent].associations[:parent].associations[:parent].associations.fetch(:parent, 1).should == nil
938
891
  end
939
892
  end
940
- end
893
+
894
+ before do
895
+ @nodes.each{|n| n.associations.clear}
896
+ end
897
+
898
+ describe "with single key" do
899
+ before(:all) do
900
+ @db = DB
901
+ @db.create_table!(:nodes) do
902
+ primary_key :id
903
+ Integer :parent_id
904
+ String :name
905
+ end
906
+ @Node = Class.new(Sequel::Model(@db[:nodes]))
907
+ @Node.plugin :rcte_tree, :order=>:name
908
+ @nodes = []
909
+ @nodes << @a = @Node.create(:name=>'a')
910
+ @nodes << @b = @Node.create(:name=>'b')
911
+ @nodes << @aa = @Node.create(:name=>'aa', :parent=>@a)
912
+ @nodes << @ab = @Node.create(:name=>'ab', :parent=>@a)
913
+ @nodes << @ba = @Node.create(:name=>'ba', :parent=>@b)
914
+ @nodes << @bb = @Node.create(:name=>'bb', :parent=>@b)
915
+ @nodes << @aaa = @Node.create(:name=>'aaa', :parent=>@aa)
916
+ @nodes << @aab = @Node.create(:name=>'aab', :parent=>@aa)
917
+ @nodes << @aba = @Node.create(:name=>'aba', :parent=>@ab)
918
+ @nodes << @abb = @Node.create(:name=>'abb', :parent=>@ab)
919
+ @nodes << @aaaa = @Node.create(:name=>'aaaa', :parent=>@aaa)
920
+ @nodes << @aaab = @Node.create(:name=>'aaab', :parent=>@aaa)
921
+ @nodes << @aaaaa = @Node.create(:name=>'aaaaa', :parent=>@aaaa)
922
+ end
923
+ after(:all) do
924
+ @db.drop_table? :nodes
925
+ end
926
+
927
+ it_should_behave_like "rcte tree plugin"
928
+
929
+ specify "should work correctly if not all columns are selected" do
930
+ c = Class.new(Sequel::Model(@db[:nodes]))
931
+ c.plugin :rcte_tree, :order=>:name
932
+ c.plugin :lazy_attributes, :name
933
+ c[:name=>'aaaa'].descendants.should == [c.load(:parent_id=>11, :id=>13)]
934
+ c[:name=>'aa'].ancestors.should == [c.load(:parent_id=>nil, :id=>1)]
935
+ nodes = c.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
936
+ nodes.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| c.load(x)}
937
+ nodes[2].descendants.should == [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| c.load(x)}
938
+ nodes[1].ancestors.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| c.load(x)}
939
+ end
940
+ end
941
+
942
+ describe "with composite keys" do
943
+ before(:all) do
944
+ @db = DB
945
+ @db.create_table!(:nodes) do
946
+ Integer :id
947
+ Integer :id2
948
+ Integer :parent_id
949
+ Integer :parent_id2
950
+ String :name
951
+ primary_key [:id, :id2]
952
+ end
953
+ @Node = Class.new(Sequel::Model(@db[:nodes]))
954
+ @Node.plugin :rcte_tree, :order=>:name, :key=>[:parent_id, :parent_id2]
955
+ @Node.unrestrict_primary_key
956
+ @nodes = []
957
+ @nodes << @a = @Node.create(:id=>1, :id2=>1, :name=>'a')
958
+ @nodes << @b = @Node.create(:id=>1, :id2=>2, :name=>'b')
959
+ @nodes << @aa = @Node.create(:id=>2, :id2=>1, :name=>'aa', :parent=>@a)
960
+ @nodes << @ab = @Node.create(:id=>2, :id2=>2, :name=>'ab', :parent=>@a)
961
+ @nodes << @ba = @Node.create(:id=>3, :id2=>1, :name=>'ba', :parent=>@b)
962
+ @nodes << @bb = @Node.create(:id=>3, :id2=>2, :name=>'bb', :parent=>@b)
963
+ @nodes << @aaa = @Node.create(:id=>3, :id2=>3, :name=>'aaa', :parent=>@aa)
964
+ @nodes << @aab = @Node.create(:id=>1, :id2=>3, :name=>'aab', :parent=>@aa)
965
+ @nodes << @aba = @Node.create(:id=>2, :id2=>3, :name=>'aba', :parent=>@ab)
966
+ @nodes << @abb = @Node.create(:id=>4, :id2=>1, :name=>'abb', :parent=>@ab)
967
+ @nodes << @aaaa = @Node.create(:id=>1, :id2=>4, :name=>'aaaa', :parent=>@aaa)
968
+ @nodes << @aaab = @Node.create(:id=>2, :id2=>4, :name=>'aaab', :parent=>@aaa)
969
+ @nodes << @aaaaa = @Node.create(:id=>3, :id2=>4, :name=>'aaaaa', :parent=>@aaaa)
970
+ end
971
+ after(:all) do
972
+ @db.drop_table? :nodes
973
+ end
974
+
975
+ it_should_behave_like "rcte tree plugin"
976
+ end
977
+ end if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
941
978
 
942
979
  describe "Instance Filters plugin" do
943
980
  before(:all) do
@@ -1538,167 +1575,116 @@ describe "List plugin with a scope" do
1538
1575
  end
1539
1576
 
1540
1577
  describe "Sequel::Plugins::Tree" do
1541
- before(:all) do
1542
- @db = DB
1543
- end
1544
-
1545
- describe "with natural database order" do
1546
- before(:all) do
1547
- @db.create_table!(:nodes) do
1548
- Integer :id, :primary_key=>true
1549
- String :name
1550
- Integer :parent_id
1551
- Integer :position
1552
- end
1553
-
1554
- @nodes = [{:id => 1, :name => 'one', :parent_id => nil, :position => 1},
1555
- {:id => 2, :name => 'two', :parent_id => nil, :position => 2},
1556
- {:id => 3, :name => 'three', :parent_id => nil, :position => 3},
1557
- {:id => 4, :name => "two.one", :parent_id => 2, :position => 1},
1558
- {:id => 5, :name => "two.two", :parent_id => 2, :position => 2},
1559
- {:id => 6, :name => "two.two.one", :parent_id => 5, :position => 1},
1560
- {:id => 7, :name => "one.two", :parent_id => 1, :position => 2},
1561
- {:id => 8, :name => "one.one", :parent_id => 1, :position => 1},
1562
- {:id => 9, :name => "five", :parent_id => nil, :position => 5},
1563
- {:id => 10, :name => "four", :parent_id => nil, :position => 4},
1564
- {:id => 11, :name => "five.one", :parent_id => 9, :position => 1},
1565
- {:id => 12, :name => "two.three", :parent_id => 2, :position => 3}]
1566
- @nodes.each{|node| @db[:nodes].insert(node)}
1567
-
1568
- class ::Node < Sequel::Model
1569
- plugin :tree
1570
- end
1571
- end
1572
- after(:all) do
1573
- @db.drop_table?(:nodes)
1574
- Object.send(:remove_const, :Node)
1575
- end
1576
-
1578
+ shared_examples_for "tree plugin" do
1577
1579
  it "should instantiate" do
1578
- Node.all.size.should == 12
1579
- end
1580
-
1581
- it "should find top level nodes" do
1582
- Node.roots_dataset.count.should == 5
1580
+ @Node.all.size.should == 12
1583
1581
  end
1584
1582
 
1585
1583
  it "should find all descendants of a node" do
1586
- two = Node.find(:id => 2)
1587
- two.name.should == "two"
1588
- two.descendants.map{|m| m[:id]}.should == [4, 5, 12, 6]
1584
+ @Node.find(:name => 'two').descendants.map{|m| m.name}.should == %w'two.one two.two two.three two.two.one'
1589
1585
  end
1590
1586
 
1591
1587
  it "should find all ancestors of a node" do
1592
- twotwoone = Node.find(:id => 6)
1593
- twotwoone.name.should == "two.two.one"
1594
- twotwoone.ancestors.map{|m| m[:id]}.should == [5, 2]
1588
+ @Node.find(:name => "two.two.one").ancestors.map{|m| m.name}.should == %w'two.two two'
1595
1589
  end
1596
1590
 
1597
1591
  it "should find all siblings of a node, excepting self" do
1598
- twoone = Node.find(:id => 4)
1599
- twoone.name.should == "two.one"
1600
- twoone.siblings.map{|m| m[:id]}.should == [5, 12]
1592
+ @Node.find(:name=>"two.one").siblings.map{|m| m.name}.should == %w'two.two two.three'
1601
1593
  end
1602
1594
 
1603
1595
  it "should find all siblings of a node, including self" do
1604
- twoone = Node.find(:id => 4)
1605
- twoone.name.should == "two.one"
1606
- twoone.self_and_siblings.map{|m| m[:id]}.should == [4, 5, 12]
1596
+ @Node.find(:name=>"two.one").self_and_siblings.map{|m| m.name}.should == %w'two.one two.two two.three'
1607
1597
  end
1608
1598
 
1609
1599
  it "should find siblings for root nodes" do
1610
- three = Node.find(:id => 3)
1611
- three.name.should == "three"
1612
- three.self_and_siblings.map{|m| m[:id]}.should == [1, 2, 3, 9, 10]
1600
+ @Node.find(:name=>'three').self_and_siblings.map{|m| m.name}.should == %w'one two three four five'
1613
1601
  end
1614
1602
 
1615
1603
  it "should find correct root for a node" do
1616
- twotwoone = Node.find(:id => 6)
1617
- twotwoone.name.should == "two.two.one"
1618
- twotwoone.root[:id].should == 2
1619
-
1620
- three = Node.find(:id => 3)
1621
- three.name.should == "three"
1622
- three.root[:id].should == 3
1623
-
1624
- fiveone = Node.find(:id => 11)
1625
- fiveone.name.should == "five.one"
1626
- fiveone.root[:id].should == 9
1604
+ @Node.find(:name=>"two.two.one").root.name.should == 'two'
1605
+ @Node.find(:name=>"three").root.name.should == 'three'
1606
+ @Node.find(:name=>"five.one").root.name.should == 'five'
1627
1607
  end
1628
1608
 
1629
- it "iterate top-level nodes in natural database order" do
1630
- Node.roots_dataset.count.should == 5
1631
- Node.roots.inject([]){|ids, p| ids << p.position}.should == [1, 2, 3, 5, 4]
1609
+ it "iterate top-level nodes in order" do
1610
+ @Node.roots_dataset.count.should == 5
1611
+ @Node.roots.map{|p| p.name}.should == %w'one two three four five'
1632
1612
  end
1633
1613
 
1634
1614
  it "should have children" do
1635
- one = Node.find(:id => 1)
1636
- one.name.should == "one"
1637
- one.children.size.should == 2
1638
- end
1639
-
1640
- it "children should be natural database order" do
1641
- one = Node.find(:id => 1)
1642
- one.name.should == "one"
1643
- one.children.map{|m| m[:position]}.should == [2, 1]
1615
+ @Node.find(:name=>'one').children.map{|m| m.name}.should == %w'one.one one.two'
1644
1616
  end
1617
+ end
1645
1618
 
1646
- describe "Nodes in specified order" do
1647
- before(:all) do
1648
- class ::OrderedNode < Sequel::Model(:nodes)
1649
- plugin :tree, :order => :position
1650
- end
1651
- end
1652
- after(:all) do
1653
- Object.send(:remove_const, :OrderedNode)
1619
+ describe "with simple key" do
1620
+ before(:all) do
1621
+ @db = DB
1622
+ @db.create_table!(:nodes) do
1623
+ Integer :id, :primary_key=>true
1624
+ String :name
1625
+ Integer :parent_id
1626
+ Integer :position
1654
1627
  end
1655
1628
 
1656
- it "iterate top-level nodes in order by position" do
1657
- OrderedNode.roots_dataset.count.should == 5
1658
- OrderedNode.roots.inject([]){|ids, p| ids << p.position}.should == [1, 2, 3, 4, 5]
1659
- end
1629
+ @nodes = [{:id => 1, :name => 'one', :parent_id => nil, :position => 1},
1630
+ {:id => 2, :name => 'two', :parent_id => nil, :position => 2},
1631
+ {:id => 3, :name => 'three', :parent_id => nil, :position => 3},
1632
+ {:id => 4, :name => "two.one", :parent_id => 2, :position => 1},
1633
+ {:id => 5, :name => "two.two", :parent_id => 2, :position => 2},
1634
+ {:id => 6, :name => "two.two.one", :parent_id => 5, :position => 1},
1635
+ {:id => 7, :name => "one.two", :parent_id => 1, :position => 2},
1636
+ {:id => 8, :name => "one.one", :parent_id => 1, :position => 1},
1637
+ {:id => 9, :name => "five", :parent_id => nil, :position => 5},
1638
+ {:id => 10, :name => "four", :parent_id => nil, :position => 4},
1639
+ {:id => 11, :name => "five.one", :parent_id => 9, :position => 1},
1640
+ {:id => 12, :name => "two.three", :parent_id => 2, :position => 3}]
1641
+ @nodes.each{|node| @db[:nodes].insert(node)}
1660
1642
 
1661
- it "children should be in specified order" do
1662
- one = OrderedNode.find(:id => 1)
1663
- one.name.should == "one"
1664
- one.children.map{|m| m[:position]}.should == [1, 2]
1665
- end
1643
+ @Node = Class.new(Sequel::Model(:nodes))
1644
+ @Node.plugin :tree, :order=>:position
1645
+ end
1646
+ after(:all) do
1647
+ @db.drop_table?(:nodes)
1666
1648
  end
1649
+
1650
+ it_should_behave_like "tree plugin"
1667
1651
  end
1668
1652
 
1669
- describe "Lorems in specified order" do
1653
+ describe "with composite key" do
1670
1654
  before(:all) do
1671
- @db.create_table!(:lorems) do
1672
- Integer :id, :primary_key=>true
1655
+ @db = DB
1656
+ @db.create_table!(:nodes) do
1657
+ Integer :id
1658
+ Integer :id2
1673
1659
  String :name
1674
- Integer :ipsum_id
1675
- Integer :neque
1660
+ Integer :parent_id
1661
+ Integer :parent_id2
1662
+ Integer :position
1663
+ primary_key [:id, :id2]
1676
1664
  end
1677
1665
 
1678
- @lorems = [{:id => 1, :name => 'Lorem', :ipsum_id => nil, :neque => 4},
1679
- {:id => 2, :name => 'Ipsum', :ipsum_id => nil, :neque => 3},
1680
- {:id => 4, :name => "Neque", :ipsum_id => 2, :neque => 2},
1681
- {:id => 5, :name => "Porro", :ipsum_id => 2, :neque => 1}]
1682
- @lorems.each{|lorem| @db[:lorems].insert(lorem)}
1666
+ @nodes = [{:id => 1, :id2=> 1, :name => 'one', :parent_id => nil, :parent_id2 => nil, :position => 1},
1667
+ {:id => 2, :id2=> 1, :name => 'two', :parent_id => nil, :parent_id2 => nil, :position => 2},
1668
+ {:id => 1, :id2=> 2, :name => 'three', :parent_id => nil, :parent_id2 => nil, :position => 3},
1669
+ {:id => 2, :id2=> 2, :name => "two.one", :parent_id => 2, :parent_id2 => 1, :position => 1},
1670
+ {:id => 3, :id2=> 1, :name => "two.two", :parent_id => 2, :parent_id2 => 1, :position => 2},
1671
+ {:id => 3, :id2=> 2, :name => "two.two.one", :parent_id => 3, :parent_id2 => 1, :position => 1},
1672
+ {:id => 3, :id2=> 3, :name => "one.two", :parent_id => 1, :parent_id2 => 1, :position => 2},
1673
+ {:id => 1, :id2=> 3, :name => "one.one", :parent_id => 1, :parent_id2 => 1, :position => 1},
1674
+ {:id => 2, :id2=> 3, :name => "five", :parent_id => nil, :parent_id2 => nil, :position => 5},
1675
+ {:id => 4, :id2=> 1, :name => "four", :parent_id => nil, :parent_id2 => nil, :position => 4},
1676
+ {:id => 1, :id2=> 4, :name => "five.one", :parent_id => 2, :parent_id2 => 3, :position => 1},
1677
+ {:id => 2, :id2=> 4, :name => "two.three", :parent_id => 2, :parent_id2 => 1, :position => 3}]
1678
+ @nodes.each{|node| @db[:nodes].insert(node)}
1683
1679
 
1684
- class ::Lorem < Sequel::Model
1685
- plugin :tree, :key => :ipsum_id, :order => :neque
1686
- end
1680
+ @Node = Class.new(Sequel::Model(:nodes))
1681
+ @Node.plugin :tree, :order=>:position, :key=>[:parent_id, :parent_id2]
1687
1682
  end
1688
1683
  after(:all) do
1689
- @db.drop_table?(:lorems)
1690
- Object.send(:remove_const, :Lorem)
1691
- end
1692
-
1693
- it "iterate top-level nodes in order by position" do
1694
- Lorem.roots_dataset.count.should == 2
1695
- Lorem.roots.inject([]){|ids, p| ids << p.neque}.should == [3, 4]
1684
+ @db.drop_table?(:nodes)
1696
1685
  end
1697
1686
 
1698
- it "children should be specified order" do
1699
- one = Lorem.find(:id => 2)
1700
- one.children.map{|m| m[:neque]}.should == [1, 2]
1701
- end
1687
+ it_should_behave_like "tree plugin"
1702
1688
  end
1703
1689
  end
1704
1690