sequel 4.48.0 → 4.49.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.
- checksums.yaml +4 -4
- data/CHANGELOG +56 -0
- data/doc/advanced_associations.rdoc +1 -1
- data/doc/opening_databases.rdoc +3 -2
- data/doc/release_notes/4.49.0.txt +222 -0
- data/lib/sequel/adapters/ibmdb.rb +6 -1
- data/lib/sequel/adapters/jdbc.rb +3 -1
- data/lib/sequel/adapters/jdbc/h2.rb +10 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlserver.rb +9 -2
- data/lib/sequel/adapters/mock.rb +3 -0
- data/lib/sequel/adapters/mysql2.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +2 -1
- data/lib/sequel/adapters/shared/mysql.rb +4 -1
- data/lib/sequel/adapters/shared/oracle.rb +26 -3
- data/lib/sequel/connection_pool.rb +9 -2
- data/lib/sequel/connection_pool/sharded_single.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/database/connecting.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +14 -1
- data/lib/sequel/dataset.rb +1 -1
- data/lib/sequel/dataset/actions.rb +54 -0
- data/lib/sequel/dataset/dataset_module.rb +58 -0
- data/lib/sequel/dataset/query.rb +3 -3
- data/lib/sequel/exceptions.rb +8 -0
- data/lib/sequel/extensions/_model_pg_row.rb +5 -2
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -2
- data/lib/sequel/extensions/migration.rb +5 -2
- data/lib/sequel/extensions/null_dataset.rb +1 -0
- data/lib/sequel/model/associations.rb +3 -0
- data/lib/sequel/model/base.rb +10 -55
- data/lib/sequel/model/dataset_module.rb +5 -43
- data/lib/sequel/model/errors.rb +2 -1
- data/lib/sequel/model/inflections.rb +17 -5
- data/lib/sequel/plugins/active_model.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +25 -13
- data/lib/sequel/plugins/json_serializer.rb +2 -2
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/serialization.rb +1 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +6 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +10 -2
- data/lib/sequel/sql.rb +16 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +4 -4
- data/spec/adapters/mysql_spec.rb +5 -1
- data/spec/adapters/oracle_spec.rb +4 -0
- data/spec/bin_spec.rb +7 -1
- data/spec/core/connection_pool_spec.rb +28 -14
- data/spec/core/database_spec.rb +149 -0
- data/spec/core/dataset_spec.rb +173 -0
- data/spec/extensions/class_table_inheritance_spec.rb +58 -17
- data/spec/extensions/composition_spec.rb +13 -0
- data/spec/extensions/dataset_associations_spec.rb +12 -0
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +16 -0
- data/spec/extensions/validation_helpers_spec.rb +1 -2
- data/spec/integration/associations_test.rb +8 -0
- data/spec/integration/plugin_test.rb +8 -3
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +29 -9
- data/spec/model/class_dataset_methods_spec.rb +6 -0
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/plugins_spec.rb +34 -0
- data/spec/model/record_spec.rb +1 -1
- data/spec/spec_config.rb +2 -0
- metadata +5 -2
data/spec/core/dataset_spec.rb
CHANGED
@@ -1895,6 +1895,126 @@ describe "Dataset#with_extend" do
|
|
1895
1895
|
end
|
1896
1896
|
end
|
1897
1897
|
|
1898
|
+
describe "Dataset#with_extend custom methods" do
|
1899
|
+
before do
|
1900
|
+
@ds = Sequel.mock[:items]
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
it "should have dataset_module support a where method" do
|
1904
|
+
@ds = @ds.with_extend{where :released, :released}
|
1905
|
+
@ds.released.sql.must_equal 'SELECT * FROM items WHERE released'
|
1906
|
+
@ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE (foo AND released)'
|
1907
|
+
end
|
1908
|
+
|
1909
|
+
it "should have dataset_module support a having method" do
|
1910
|
+
@ds = @ds.with_extend{having(:released){released}}
|
1911
|
+
@ds.released.sql.must_equal 'SELECT * FROM items HAVING released'
|
1912
|
+
@ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE foo HAVING released'
|
1913
|
+
end
|
1914
|
+
|
1915
|
+
it "should have dataset_module support an exclude method" do
|
1916
|
+
@ds = @ds.with_extend{exclude :released, :released}
|
1917
|
+
@ds.released.sql.must_equal 'SELECT * FROM items WHERE NOT released'
|
1918
|
+
@ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE (foo AND NOT released)'
|
1919
|
+
end
|
1920
|
+
|
1921
|
+
it "should have dataset_module support an exclude_having method" do
|
1922
|
+
@ds = @ds.with_extend{exclude_having :released, :released}
|
1923
|
+
@ds.released.sql.must_equal 'SELECT * FROM items HAVING NOT released'
|
1924
|
+
@ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE foo HAVING NOT released'
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
it "should have dataset_module support a distinct method" do
|
1928
|
+
@ds = @ds.with_extend{def supports_distinct_on?; true end; distinct :foo, :baz}
|
1929
|
+
@ds.foo.sql.must_equal 'SELECT DISTINCT ON (baz) * FROM items'
|
1930
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT DISTINCT ON (baz) * FROM items WHERE bar'
|
1931
|
+
end
|
1932
|
+
|
1933
|
+
it "should have dataset_module support a grep method" do
|
1934
|
+
@ds = @ds.with_extend{grep :foo, :baz, 'quux%'}
|
1935
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items WHERE ((baz LIKE \'quux%\' ESCAPE \'\\\'))'
|
1936
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE (bar AND ((baz LIKE \'quux%\' ESCAPE \'\\\')))'
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
it "should have dataset_module support a group method" do
|
1940
|
+
@ds = @ds.with_extend{group :foo, :baz}
|
1941
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items GROUP BY baz'
|
1942
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar GROUP BY baz'
|
1943
|
+
end
|
1944
|
+
|
1945
|
+
it "should have dataset_module support a group_and_count method" do
|
1946
|
+
@ds = @ds.with_extend{group_and_count :foo, :baz}
|
1947
|
+
@ds.foo.sql.must_equal 'SELECT baz, count(*) AS count FROM items GROUP BY baz'
|
1948
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT baz, count(*) AS count FROM items WHERE bar GROUP BY baz'
|
1949
|
+
end
|
1950
|
+
|
1951
|
+
it "should have dataset_module support a group_append method" do
|
1952
|
+
@ds = @ds.with_extend{group_append :foo, :baz}
|
1953
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items GROUP BY baz'
|
1954
|
+
@ds.group(:bar).foo.sql.must_equal 'SELECT * FROM items GROUP BY bar, baz'
|
1955
|
+
end
|
1956
|
+
|
1957
|
+
it "should have dataset_module support a limit method" do
|
1958
|
+
@ds = @ds.with_extend{limit :foo, 1}
|
1959
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items LIMIT 1'
|
1960
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar LIMIT 1'
|
1961
|
+
end
|
1962
|
+
|
1963
|
+
it "should have dataset_module support a offset method" do
|
1964
|
+
@ds = @ds.with_extend{offset :foo, 1}
|
1965
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items OFFSET 1'
|
1966
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar OFFSET 1'
|
1967
|
+
end
|
1968
|
+
|
1969
|
+
it "should have dataset_module support a order method" do
|
1970
|
+
@ds = @ds.with_extend{order(:foo){:baz}}
|
1971
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items ORDER BY baz'
|
1972
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar ORDER BY baz'
|
1973
|
+
end
|
1974
|
+
|
1975
|
+
it "should have dataset_module support a order_append method" do
|
1976
|
+
@ds = @ds.with_extend{order_append :foo, :baz}
|
1977
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items ORDER BY baz'
|
1978
|
+
@ds.order(:bar).foo.sql.must_equal 'SELECT * FROM items ORDER BY bar, baz'
|
1979
|
+
end
|
1980
|
+
|
1981
|
+
it "should have dataset_module support a order_prepend method" do
|
1982
|
+
@ds = @ds.with_extend{order_prepend :foo, :baz}
|
1983
|
+
@ds.foo.sql.must_equal 'SELECT * FROM items ORDER BY baz'
|
1984
|
+
@ds.order(:bar).foo.sql.must_equal 'SELECT * FROM items ORDER BY baz, bar'
|
1985
|
+
end
|
1986
|
+
|
1987
|
+
it "should have dataset_module support a select method" do
|
1988
|
+
@ds = @ds.with_extend{select :foo, :baz}
|
1989
|
+
@ds.foo.sql.must_equal 'SELECT baz FROM items'
|
1990
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT baz FROM items WHERE bar'
|
1991
|
+
end
|
1992
|
+
|
1993
|
+
it "should have dataset_module support a select_all method" do
|
1994
|
+
@ds = @ds.with_extend{select_all :foo, :baz}
|
1995
|
+
@ds.foo.sql.must_equal 'SELECT baz.* FROM items'
|
1996
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT baz.* FROM items WHERE bar'
|
1997
|
+
end
|
1998
|
+
|
1999
|
+
it "should have dataset_module support a select_append method" do
|
2000
|
+
@ds = @ds.with_extend{select_append :foo, :baz}
|
2001
|
+
@ds.foo.sql.must_equal 'SELECT *, baz FROM items'
|
2002
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT *, baz FROM items WHERE bar'
|
2003
|
+
end
|
2004
|
+
|
2005
|
+
it "should have dataset_module support a select_group method" do
|
2006
|
+
@ds = @ds.with_extend{select_group :foo, :baz}
|
2007
|
+
@ds.foo.sql.must_equal 'SELECT baz FROM items GROUP BY baz'
|
2008
|
+
@ds.where(:bar).foo.sql.must_equal 'SELECT baz FROM items WHERE bar GROUP BY baz'
|
2009
|
+
end
|
2010
|
+
|
2011
|
+
it "should have dataset_module support a server method" do
|
2012
|
+
@ds = @ds.with_extend{server :foo, :baz}
|
2013
|
+
@ds.foo.opts[:server].must_equal :baz
|
2014
|
+
@ds.where(:bar).foo.opts[:server].must_equal :baz
|
2015
|
+
end
|
2016
|
+
end
|
2017
|
+
|
1898
2018
|
describe "Dataset#with_row_proc" do
|
1899
2019
|
it "should returned clone dataset with the given row_proc" do
|
1900
2020
|
d = Sequel.mock.dataset
|
@@ -5533,3 +5653,56 @@ describe "Dataset#output_identifier" do
|
|
5533
5653
|
meth.call('A').must_equal :a
|
5534
5654
|
end
|
5535
5655
|
end
|
5656
|
+
|
5657
|
+
describe "Dataset#where_all" do
|
5658
|
+
before do
|
5659
|
+
@ds = Sequel.mock(:fetch=>{:id=>1})[:items].freeze
|
5660
|
+
end
|
5661
|
+
|
5662
|
+
it "should filter dataset with condition, and return related rows" do
|
5663
|
+
5.times do
|
5664
|
+
@ds.where_all(:id=>1).must_equal [{:id=>1}]
|
5665
|
+
@ds.db.sqls.must_equal ['SELECT * FROM items WHERE (id = 1)']
|
5666
|
+
end
|
5667
|
+
end
|
5668
|
+
|
5669
|
+
it "should yield each row to the given block" do
|
5670
|
+
5.times do
|
5671
|
+
a = []
|
5672
|
+
@ds.where_all(:id=>1){|r| a << r}.must_equal [{:id=>1}]
|
5673
|
+
a.must_equal [{:id=>1}]
|
5674
|
+
@ds.db.sqls.must_equal ['SELECT * FROM items WHERE (id = 1)']
|
5675
|
+
end
|
5676
|
+
end
|
5677
|
+
end
|
5678
|
+
|
5679
|
+
describe "Dataset#where_each" do
|
5680
|
+
before do
|
5681
|
+
@ds = Sequel.mock(:fetch=>{:id=>1})[:items].freeze
|
5682
|
+
end
|
5683
|
+
|
5684
|
+
it "should yield each row to the given block" do
|
5685
|
+
5.times do
|
5686
|
+
a = []
|
5687
|
+
@ds.where_each(:id=>1){|r| a << r}
|
5688
|
+
a.must_equal [{:id=>1}]
|
5689
|
+
@ds.db.sqls.must_equal ['SELECT * FROM items WHERE (id = 1)']
|
5690
|
+
end
|
5691
|
+
end
|
5692
|
+
end
|
5693
|
+
|
5694
|
+
describe "Dataset#where_single_value" do
|
5695
|
+
before do
|
5696
|
+
@ds = Sequel.mock(:fetch=>{:id=>1})[:items].with_extend do
|
5697
|
+
select :only_id, :id
|
5698
|
+
end.freeze
|
5699
|
+
end
|
5700
|
+
|
5701
|
+
it "should return single value" do
|
5702
|
+
5.times do
|
5703
|
+
a = []
|
5704
|
+
@ds.only_id.where_single_value(:id=>1).must_equal 1
|
5705
|
+
@ds.db.sqls.must_equal ['SELECT id FROM items WHERE (id = 1) LIMIT 1']
|
5706
|
+
end
|
5707
|
+
end
|
5708
|
+
end
|
@@ -585,7 +585,7 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
585
585
|
Executive.cti_models.first.must_equal Employee
|
586
586
|
end
|
587
587
|
|
588
|
-
|
588
|
+
deprecated "#cti_columns should be a mapping of table names to columns" do
|
589
589
|
Executive.cti_columns.must_equal(:employees=>[:id, :name, :kind], :managers=>[:id, :num_staff], :executives=>[:id, :num_managers])
|
590
590
|
end
|
591
591
|
|
@@ -1080,15 +1080,13 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1080
1080
|
class ::Staff < Employee
|
1081
1081
|
many_to_one :manager
|
1082
1082
|
end
|
1083
|
+
class ::Intern < Employee
|
1084
|
+
end
|
1083
1085
|
@ds = Employee.dataset
|
1084
1086
|
@db.sqls
|
1085
1087
|
end
|
1086
1088
|
after do
|
1087
|
-
Object.send(:remove_const,
|
1088
|
-
Object.send(:remove_const, :Executive)
|
1089
|
-
Object.send(:remove_const, :Manager)
|
1090
|
-
Object.send(:remove_const, :Staff)
|
1091
|
-
Object.send(:remove_const, :Employee)
|
1089
|
+
[:Intern, :Ceo, :Executive, :Manager, :Staff, :Employee].each{|s| Object.send(:remove_const, s)}
|
1092
1090
|
end
|
1093
1091
|
|
1094
1092
|
it "should freeze CTI information when freezing model class" do
|
@@ -1119,7 +1117,7 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1119
1117
|
Executive.cti_models.first.must_equal Employee
|
1120
1118
|
end
|
1121
1119
|
|
1122
|
-
|
1120
|
+
deprecated "#cti_columns should be a mapping of table names to columns" do
|
1123
1121
|
Executive.cti_columns.must_equal(:employees=>[:id, :name, :kind], :managers=>[:id, :num_staff], :executives=>[:id, :num_managers])
|
1124
1122
|
end
|
1125
1123
|
|
@@ -1128,6 +1126,7 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1128
1126
|
Executive.simple_table.must_be_nil
|
1129
1127
|
Ceo.simple_table.must_be_nil
|
1130
1128
|
Staff.simple_table.must_be_nil
|
1129
|
+
Intern.simple_table.must_be_nil
|
1131
1130
|
end
|
1132
1131
|
|
1133
1132
|
it "should have working row_proc if using set_dataset in subclass to remove columns" do
|
@@ -1142,10 +1141,11 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1142
1141
|
Executive.dataset.sql.must_equal 'SELECT * FROM (SELECT employees.id, employees.name, employees.kind, managers.num_staff, executives.num_managers FROM employees INNER JOIN managers ON (managers.id = employees.id) INNER JOIN executives ON (executives.id = managers.id)) AS employees'
|
1143
1142
|
Ceo.dataset.sql.must_equal 'SELECT * FROM (SELECT employees.id, employees.name, employees.kind, managers.num_staff, executives.num_managers FROM employees INNER JOIN managers ON (managers.id = employees.id) INNER JOIN executives ON (executives.id = managers.id) WHERE (employees.kind IN (\'Ceo\'))) AS employees'
|
1144
1143
|
Staff.dataset.sql.must_equal 'SELECT * FROM (SELECT employees.id, employees.name, employees.kind, staff.manager_id FROM employees INNER JOIN staff ON (staff.id = employees.id)) AS employees'
|
1144
|
+
Intern.dataset.sql.must_equal 'SELECT * FROM employees WHERE (employees.kind IN (\'Intern\'))'
|
1145
1145
|
end
|
1146
1146
|
|
1147
1147
|
it "should return rows with the correct class based on the polymorphic_key value" do
|
1148
|
-
@ds.with_fetch([{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Ceo'}, {:kind=>'Staff'}]).all.collect{|x| x.class}.must_equal [Employee, Manager, Executive, Ceo, Staff]
|
1148
|
+
@ds.with_fetch([{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Ceo'}, {:kind=>'Staff'}, {:kind=>'Intern'}]).all.collect{|x| x.class}.must_equal [Employee, Manager, Executive, Ceo, Staff, Intern]
|
1149
1149
|
end
|
1150
1150
|
|
1151
1151
|
it "should return rows with the correct class based on the polymorphic_key value for subclasses" do
|
@@ -1165,7 +1165,7 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1165
1165
|
|
1166
1166
|
it "should return rows with the current class if cti_key is nil" do
|
1167
1167
|
Employee.plugin(:class_table_inheritance, :alias=>:employees)
|
1168
|
-
Employee.dataset.with_fetch([{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Ceo'}, {:kind=>'Staff'}]).all.map{|x| x.class}.must_equal [Employee, Employee, Employee, Employee, Employee]
|
1168
|
+
Employee.dataset.with_fetch([{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Ceo'}, {:kind=>'Staff'}, {:kind=>'Intern'}]).all.map{|x| x.class}.must_equal [Employee, Employee, Employee, Employee, Employee, Employee]
|
1169
1169
|
end
|
1170
1170
|
|
1171
1171
|
it "should return rows with the current class if cti_key is nil in subclasses" do
|
@@ -1178,15 +1178,17 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1178
1178
|
end
|
1179
1179
|
|
1180
1180
|
it "should handle a model map with integer values" do
|
1181
|
-
Employee.plugin(:class_table_inheritance, :key=>:kind, :model_map=>{0=>:Employee, 1=>:Manager, 2=>:Executive, 3=>:Ceo}, :alias=>:employees)
|
1181
|
+
Employee.plugin(:class_table_inheritance, :key=>:kind, :model_map=>{0=>:Employee, 1=>:Manager, 2=>:Executive, 3=>:Ceo, 4=>:Intern}, :alias=>:employees)
|
1182
|
+
Object.send(:remove_const, :Intern)
|
1182
1183
|
Object.send(:remove_const, :Ceo)
|
1183
1184
|
Object.send(:remove_const, :Executive)
|
1184
1185
|
Object.send(:remove_const, :Manager)
|
1186
|
+
class ::Intern < Employee; end
|
1185
1187
|
class ::Manager < Employee; end
|
1186
1188
|
class ::Executive < Manager; end
|
1187
1189
|
class ::Ceo < Executive; end
|
1188
|
-
Employee.dataset = Employee.dataset.with_fetch([{:kind=>nil},{:kind=>0},{:kind=>1}, {:kind=>2}, {:kind=>3}])
|
1189
|
-
Employee.all.collect{|x| x.class}.must_equal [Employee, Employee, Manager, Executive, Ceo]
|
1190
|
+
Employee.dataset = Employee.dataset.with_fetch([{:kind=>nil},{:kind=>0},{:kind=>1}, {:kind=>2}, {:kind=>3}, {:kind=>4}])
|
1191
|
+
Employee.all.collect{|x| x.class}.must_equal [Employee, Employee, Manager, Executive, Ceo, Intern]
|
1190
1192
|
Manager.dataset = Manager.dataset.with_fetch([{:kind=>nil},{:kind=>0},{:kind=>1}, {:kind=>2}, {:kind=>3}])
|
1191
1193
|
Manager.all.collect{|x| x.class}.must_equal [Manager, Employee, Manager, Executive, Ceo]
|
1192
1194
|
end
|
@@ -1204,6 +1206,11 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1204
1206
|
@db.sqls.must_equal ["INSERT INTO employees (kind) VALUES ('Employee')"]
|
1205
1207
|
end
|
1206
1208
|
|
1209
|
+
it "should sets the model class name for the key when creating new class records for subclass without separate table" do
|
1210
|
+
Intern.create
|
1211
|
+
@db.sqls.must_equal ["INSERT INTO employees (kind) VALUES ('Intern')"]
|
1212
|
+
end
|
1213
|
+
|
1207
1214
|
it "should sets the model class name for the key when creating new subclass records" do
|
1208
1215
|
Ceo.create
|
1209
1216
|
@db.sqls.must_equal ["INSERT INTO employees (kind) VALUES ('Ceo')",
|
@@ -1278,10 +1285,11 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1278
1285
|
Manager.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string}, :num_staff=>{:type=>:integer})
|
1279
1286
|
Executive.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string}, :num_staff=>{:type=>:integer}, :num_managers=>{:type=>:integer})
|
1280
1287
|
Staff.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string}, :manager_id=>{:type=>:integer})
|
1288
|
+
Intern.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string})
|
1281
1289
|
end
|
1282
1290
|
|
1283
1291
|
it "should use the correct primary key (which should have the same name in all subclasses)" do
|
1284
|
-
[Employee, Manager, Executive, Ceo, Staff].each{|c| c.primary_key.must_equal :id}
|
1292
|
+
[Employee, Manager, Executive, Ceo, Staff, Intern].each{|c| c.primary_key.must_equal :id}
|
1285
1293
|
end
|
1286
1294
|
|
1287
1295
|
it "should have table_name return the table name of the most specific table" do
|
@@ -1290,20 +1298,43 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1290
1298
|
Executive.table_name.must_equal :employees
|
1291
1299
|
Ceo.table_name.must_equal :employees
|
1292
1300
|
Staff.table_name.must_equal :employees
|
1301
|
+
Intern.table_name.must_equal :employees
|
1293
1302
|
end
|
1294
1303
|
|
1295
1304
|
it "should delete the correct rows from all tables when deleting" do
|
1305
|
+
Employee.load(:id=>1).delete
|
1306
|
+
@db.sqls.must_equal ["DELETE FROM employees WHERE (id = 1)"]
|
1307
|
+
|
1308
|
+
Intern.load(:id=>1).delete
|
1309
|
+
@db.sqls.must_equal ["DELETE FROM employees WHERE (id = 1)"]
|
1310
|
+
|
1296
1311
|
Ceo.load(:id=>1).delete
|
1297
1312
|
@db.sqls.must_equal ["DELETE FROM executives WHERE (id = 1)", "DELETE FROM managers WHERE (id = 1)", "DELETE FROM employees WHERE (id = 1)"]
|
1298
1313
|
end
|
1299
1314
|
|
1300
1315
|
it "should not allow deletion of frozen object" do
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1316
|
+
[Ceo, Executive, Employee, Manager, Intern].each do |c|
|
1317
|
+
o = c.load(:id=>1)
|
1318
|
+
o.freeze
|
1319
|
+
proc{o.delete}.must_raise(Sequel::Error)
|
1320
|
+
@db.sqls.must_equal []
|
1321
|
+
end
|
1305
1322
|
end
|
1306
1323
|
|
1324
|
+
it "should insert the correct rows into all tables when inserting into parent class" do
|
1325
|
+
Employee.create(:name=>'E')
|
1326
|
+
sqls = @db.sqls
|
1327
|
+
sqls.length.must_equal 1
|
1328
|
+
sqls[0].must_match(/INSERT INTO employees \((name|kind), (name|kind)\) VALUES \('(E|Employee)', '(E|Employee)'\)/)
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
it "should insert the correct rows into all tables when inserting into subclass without separate table" do
|
1332
|
+
Intern.create(:name=>'E')
|
1333
|
+
sqls = @db.sqls
|
1334
|
+
sqls.length.must_equal 1
|
1335
|
+
sqls[0].must_match(/INSERT INTO employees \((name|kind), (name|kind)\) VALUES \('(E|Intern)', '(E|Intern)'\)/)
|
1336
|
+
end
|
1337
|
+
|
1307
1338
|
it "should insert the correct rows into all tables when inserting" do
|
1308
1339
|
Ceo.create(:num_managers=>3, :num_staff=>2, :name=>'E')
|
1309
1340
|
sqls = @db.sqls
|
@@ -1342,6 +1373,16 @@ describe "class_table_inheritance plugin with :alias option" do
|
|
1342
1373
|
sqls[2].must_match(/INSERT INTO executives \((num_managers|id), (num_managers|id)\) VALUES \([23], [23]\)/)
|
1343
1374
|
end
|
1344
1375
|
|
1376
|
+
it "should update the correct rows in all tables when updating parent class" do
|
1377
|
+
Employee.load(:id=>2).update(:name=>'E')
|
1378
|
+
@db.sqls.must_equal ["UPDATE employees SET name = 'E' WHERE (id = 2)"]
|
1379
|
+
end
|
1380
|
+
|
1381
|
+
it "should update the correct rows in all tables when updating subclass without separate table" do
|
1382
|
+
Intern.load(:id=>2).update(:name=>'E')
|
1383
|
+
@db.sqls.must_equal ["UPDATE employees SET name = 'E' WHERE (id = 2)"]
|
1384
|
+
end
|
1385
|
+
|
1345
1386
|
it "should update the correct rows in all tables when updating" do
|
1346
1387
|
Ceo.load(:id=>2).update(:num_managers=>3, :num_staff=>2, :name=>'E')
|
1347
1388
|
@db.sqls.must_equal ["UPDATE employees SET name = 'E' WHERE (id = 2)", "UPDATE managers SET num_staff = 2 WHERE (id = 2)", "UPDATE executives SET num_managers = 3 WHERE (id = 2)"]
|
@@ -44,6 +44,19 @@ describe "Composition plugin" do
|
|
44
44
|
o.valid?.must_equal true
|
45
45
|
end
|
46
46
|
|
47
|
+
it "should have decomposer work with column_conflicts plugin" do
|
48
|
+
@c.plugin :column_conflicts
|
49
|
+
@c.set_column_conflict! :year
|
50
|
+
@c.composition :date, :mapping=>[:year, :month, :day]
|
51
|
+
o = @c.new
|
52
|
+
def o.validate
|
53
|
+
[:year, :month, :day].each{|c| errors.add(c, "not present") unless send(c)}
|
54
|
+
end
|
55
|
+
o.valid?.must_equal false
|
56
|
+
o.date = Date.new(1, 2, 3)
|
57
|
+
o.valid?.must_equal true
|
58
|
+
end
|
59
|
+
|
47
60
|
it "should set column values even when not validating" do
|
48
61
|
@c.composition :date, :mapping=>[:year, :month, :day]
|
49
62
|
@c.load({}).set(:date=>Date.new(4, 8, 12)).save(:validate=>false)
|
@@ -13,14 +13,17 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
13
13
|
@Artist = Class.new(@Base)
|
14
14
|
@Album = Class.new(@Base)
|
15
15
|
@Tag = Class.new(@Base)
|
16
|
+
@Track = Class.new(@Base)
|
16
17
|
|
17
18
|
def @Artist.name; 'Artist' end
|
18
19
|
def @Album.name; 'Album' end
|
19
20
|
def @Tag.name; 'Tag' end
|
21
|
+
def @Track.name; 'Track' end
|
20
22
|
|
21
23
|
@Artist.dataset = @db[:artists]
|
22
24
|
@Album.dataset = @db[:albums]
|
23
25
|
@Tag.dataset = @db[:tags]
|
26
|
+
@Track.dataset = @db[:tracks]
|
24
27
|
|
25
28
|
@Artist.columns :id, :name
|
26
29
|
@Album.columns :id, :name, :artist_id
|
@@ -28,6 +31,7 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
28
31
|
|
29
32
|
@Album.plugin :many_through_many
|
30
33
|
@Artist.plugin :many_through_many
|
34
|
+
@Track.plugin :many_through_many
|
31
35
|
@Artist.plugin :pg_array_associations
|
32
36
|
@Tag.plugin :pg_array_associations
|
33
37
|
@Artist.one_to_many :albums, :class=>@Album
|
@@ -41,6 +45,7 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
41
45
|
@Tag.many_to_pg_array :artists, :class=>@Artist
|
42
46
|
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
43
47
|
@Artist.one_through_many :otag, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
48
|
+
@Track.many_through_many :artist_tracks, [[:albums, :id, :artist_id], [:albums, :artist_id, :id]], :class=>@Track, :left_primary_key=>:album_id, :right_primary_key=>:album_id
|
44
49
|
end
|
45
50
|
|
46
51
|
it "should work for many_to_one associations" do
|
@@ -85,6 +90,13 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
85
90
|
ds.sql.must_equal "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM artists INNER JOIN albums ON (albums.artist_id = artists.id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) INNER JOIN tags ON (tags.id = albums_tags.tag_id) WHERE (albums.artist_id IN (SELECT artists.id FROM artists))))"
|
86
91
|
end
|
87
92
|
|
93
|
+
it "should work for self referential many_through_many associations" do
|
94
|
+
ds = @Track.artist_tracks
|
95
|
+
ds.must_be_kind_of(Sequel::Dataset)
|
96
|
+
ds.model.must_equal @Track
|
97
|
+
ds.sql.must_equal "SELECT tracks.* FROM tracks WHERE (tracks.album_id IN (SELECT albums_0.id FROM tracks INNER JOIN albums ON (albums.id = tracks.album_id) INNER JOIN albums AS albums_0 ON (albums_0.artist_id = albums.artist_id) INNER JOIN tracks AS tracks_0 ON (tracks_0.album_id = albums_0.id) WHERE (albums.id IN (SELECT tracks.album_id FROM tracks))))"
|
98
|
+
end
|
99
|
+
|
88
100
|
it "should work for many_through_many associations with a single join table" do
|
89
101
|
ds = @Album.mthm_tags
|
90
102
|
ds.must_be_kind_of(Sequel::Dataset)
|
@@ -59,10 +59,10 @@ describe Sequel::Model, "many_through_many" do
|
|
59
59
|
DB.sqls.must_equal []
|
60
60
|
end
|
61
61
|
|
62
|
-
it "should handle a :
|
62
|
+
it "should handle a :predicate_key option to change the SQL used in the lookup" do
|
63
63
|
@c1.dataset = @c1.dataset.with_fetch(:id=>1)
|
64
64
|
@c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
|
65
|
-
@c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :
|
65
|
+
@c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :predicate_key=>(Sequel[:albums_artists][:artist_id] / 3)
|
66
66
|
a = @c1.eager(:tags).all
|
67
67
|
a.must_equal [@c1.load(:id => 1)]
|
68
68
|
DB.sqls.must_equal ['SELECT * FROM artists', "SELECT tags.*, (albums_artists.artist_id / 3) AS x_foreign_key_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((albums_artists.artist_id / 3) IN (1))"]
|
@@ -1231,10 +1231,10 @@ describe Sequel::Model, "one_through_many" do
|
|
1231
1231
|
DB.sqls.must_equal []
|
1232
1232
|
end
|
1233
1233
|
|
1234
|
-
it "should handle a :
|
1234
|
+
it "should handle a :predicate_key option to change the SQL used in the lookup" do
|
1235
1235
|
@c1.dataset = @c1.dataset.with_fetch(:id=>1)
|
1236
1236
|
@c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
|
1237
|
-
@c1.one_through_many :tag, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :
|
1237
|
+
@c1.one_through_many :tag, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :predicate_key=>(Sequel[:albums_artists][:artist_id] / 3)
|
1238
1238
|
a = @c1.eager(:tag).all
|
1239
1239
|
a.must_equal [@c1.load(:id => 1)]
|
1240
1240
|
DB.sqls.must_equal ['SELECT * FROM artists', "SELECT tags.*, (albums_artists.artist_id / 3) AS x_foreign_key_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((albums_artists.artist_id / 3) IN (1))"]
|