sequel 3.37.0 → 3.38.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +56 -0
- data/README.rdoc +82 -58
- data/Rakefile +6 -5
- data/bin/sequel +1 -1
- data/doc/active_record.rdoc +67 -52
- data/doc/advanced_associations.rdoc +33 -48
- data/doc/association_basics.rdoc +41 -51
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +47 -43
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +4 -5
- data/doc/model_hooks.rdoc +3 -3
- data/doc/object_model.rdoc +31 -25
- data/doc/opening_databases.rdoc +19 -5
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/querying.rdoc +109 -52
- data/doc/reflection.rdoc +6 -6
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/schema_modification.rdoc +22 -13
- data/doc/sharding.rdoc +8 -9
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +47 -7
- data/doc/thread_safety.rdoc +1 -1
- data/doc/transactions.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +29 -43
- data/lib/sequel/adapters/do/postgres.rb +1 -4
- data/lib/sequel/adapters/jdbc.rb +14 -3
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +41 -4
- data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
- data/lib/sequel/adapters/mock.rb +10 -4
- data/lib/sequel/adapters/postgres.rb +1 -28
- data/lib/sequel/adapters/shared/mssql.rb +23 -13
- data/lib/sequel/adapters/shared/postgres.rb +46 -0
- data/lib/sequel/adapters/swift.rb +21 -13
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +4 -5
- data/lib/sequel/adapters/swift/sqlite.rb +2 -1
- data/lib/sequel/adapters/tinytds.rb +14 -2
- data/lib/sequel/adapters/utils/pg_types.rb +5 -0
- data/lib/sequel/core.rb +29 -17
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +3 -0
- data/lib/sequel/dataset/actions.rb +5 -6
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/dataset/sql.rb +5 -18
- data/lib/sequel/extensions/core_extensions.rb +8 -12
- data/lib/sequel/extensions/pg_array.rb +59 -33
- data/lib/sequel/extensions/pg_array_ops.rb +32 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +32 -17
- data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
- data/lib/sequel/extensions/pg_inet.rb +1 -2
- data/lib/sequel/extensions/pg_interval.rb +0 -1
- data/lib/sequel/extensions/pg_json.rb +41 -23
- data/lib/sequel/extensions/pg_range.rb +36 -11
- data/lib/sequel/extensions/pg_range_ops.rb +32 -4
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +164 -0
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/schema_dumper.rb +7 -8
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/model/base.rb +1 -0
- data/lib/sequel/no_core_ext.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/validation_helpers.rb +31 -0
- data/lib/sequel/sql.rb +64 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +37 -12
- data/spec/adapters/mysql_spec.rb +39 -75
- data/spec/adapters/oracle_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +414 -237
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +14 -14
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +169 -205
- data/spec/core/expression_filters_spec.rb +182 -295
- data/spec/core/object_graph_spec.rb +6 -6
- data/spec/core/schema_spec.rb +14 -14
- data/spec/core/spec_helper.rb +1 -0
- data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
- data/spec/extensions/columns_introspection_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +28 -36
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/pg_array_ops_spec.rb +15 -7
- data/spec/extensions/pg_array_spec.rb +81 -48
- data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
- data/spec/extensions/pg_hstore_spec.rb +66 -65
- data/spec/extensions/pg_inet_spec.rb +2 -4
- data/spec/extensions/pg_interval_spec.rb +2 -3
- data/spec/extensions/pg_json_spec.rb +20 -18
- data/spec/extensions/pg_range_ops_spec.rb +11 -4
- data/spec/extensions/pg_range_spec.rb +30 -7
- data/spec/extensions/pg_row_ops_spec.rb +48 -0
- data/spec/extensions/pg_row_plugin_spec.rb +45 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/query_literals_spec.rb +11 -11
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +20 -4
- data/spec/extensions/schema_spec.rb +18 -41
- data/spec/extensions/select_remove_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +4 -8
- data/spec/extensions/to_dot_spec.rb +5 -5
- data/spec/extensions/validation_class_methods_spec.rb +28 -16
- data/spec/integration/associations_test.rb +20 -20
- data/spec/integration/dataset_test.rb +98 -98
- data/spec/integration/eager_loader_test.rb +13 -27
- data/spec/integration/plugin_test.rb +5 -5
- data/spec/integration/prepared_statement_test.rb +22 -13
- data/spec/integration/schema_test.rb +28 -18
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +2 -2
- data/spec/integration/type_test.rb +15 -6
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +4 -4
- data/spec/model/base_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +15 -15
- data/spec/model/model_spec.rb +32 -32
- data/spec/model/record_spec.rb +16 -0
- data/spec/model/spec_helper.rb +2 -6
- data/spec/model/validations_spec.rb +1 -1
- metadata +16 -4
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe Sequel::Model, "PgTypecastOnLoad plugin" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.mock(:host=>'postgres', :fetch=>{:id=>1, :b=>"t", :y=>"0"}, :columns=>[:id, :b, :y], :numrows=>1)
|
6
|
+
def @db.schema(*args)
|
7
|
+
[[:id, {}], [:b, {:type=>:boolean, :oid=>16}], [:y, {:type=>:integer, :oid=>20}]]
|
8
|
+
end
|
9
|
+
@c = Class.new(Sequel::Model(@db[:items]))
|
10
|
+
@c.plugin :pg_typecast_on_load, :b, :y
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "should call the database conversion proc for all given columns" do
|
14
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>0}
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "should call the database conversion proc with value when reloading the object, for all given columns" do
|
18
|
+
@c.first.refresh.values.should == {:id=>1, :b=>true, :y=>0}
|
19
|
+
end
|
20
|
+
|
21
|
+
specify "should call the database conversion proc with value when automatically reloading the object on creation via insert_select" do
|
22
|
+
@c.dataset.meta_def(:insert_select){|h| insert(h); first}
|
23
|
+
@c.create.values.should == {:id=>1, :b=>true, :y=>0}
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "should allowing setting columns separately via add_typecast_on_load_columns" do
|
27
|
+
@c = Class.new(Sequel::Model(@db[:items]))
|
28
|
+
@c.plugin :pg_typecast_on_load
|
29
|
+
@c.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
30
|
+
@c.add_pg_typecast_on_load_columns :b
|
31
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>"0"}
|
32
|
+
@c.add_pg_typecast_on_load_columns :y
|
33
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>0}
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "should work with subclasses" do
|
37
|
+
@c = Class.new(Sequel::Model(@db[:items]))
|
38
|
+
@c.plugin :pg_typecast_on_load
|
39
|
+
@c.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
40
|
+
|
41
|
+
c1 = Class.new(@c)
|
42
|
+
@c.add_pg_typecast_on_load_columns :b
|
43
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>"0"}
|
44
|
+
c1.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
45
|
+
|
46
|
+
c2 = Class.new(@c)
|
47
|
+
@c.add_pg_typecast_on_load_columns :y
|
48
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>0}
|
49
|
+
c2.first.values.should == {:id=>1, :b=>true, :y=>"0"}
|
50
|
+
|
51
|
+
c1.add_pg_typecast_on_load_columns :y
|
52
|
+
c1.first.values.should == {:id=>1, :b=>"t", :y=>0}
|
53
|
+
end
|
54
|
+
|
55
|
+
specify "should not mark the object as modified" do
|
56
|
+
@c.first.modified?.should == false
|
57
|
+
end
|
58
|
+
end
|
@@ -18,7 +18,7 @@ describe "query_literals extension" do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should have #select work the standard way if initial string is a literal string already" do
|
21
|
-
@ds.select('a, b, ?'
|
21
|
+
@ds.select(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT a, b, ?, 1 FROM t'
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should have #select work regularly if not given a string as the first argument" do
|
@@ -39,7 +39,7 @@ describe "query_literals extension" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should have #select_more work the standard way if initial string is a literal string already" do
|
42
|
-
@ds.select_more('a, b, ?'
|
42
|
+
@ds.select_more(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT d, a, b, ?, 1 FROM t'
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should have #select_more work regularly if not given a string as the first argument" do
|
@@ -56,7 +56,7 @@ describe "query_literals extension" do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should have #select_append work the standard way if initial string is a literal string already" do
|
59
|
-
@ds.select_append('a, b, ?'
|
59
|
+
@ds.select_append(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT *, a, b, ?, 1 FROM t'
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should have #select_append work regularly if not given a string as the first argument" do
|
@@ -72,7 +72,7 @@ describe "query_literals extension" do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should have #select_group work the standard way if initial string is a literal string already" do
|
75
|
-
@ds.select_group('a, b, ?'
|
75
|
+
@ds.select_group(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT a, b, ?, 1 FROM t GROUP BY a, b, ?, 1'
|
76
76
|
end
|
77
77
|
|
78
78
|
it "should have #select_group work regularly if not given a string as the first argument" do
|
@@ -87,11 +87,11 @@ describe "query_literals extension" do
|
|
87
87
|
@ds.group('a, b, ?', 1).sql.should == 'SELECT * FROM t GROUP BY a, b, 1'
|
88
88
|
end
|
89
89
|
|
90
|
-
it "should have #
|
91
|
-
@ds.group('a, b, ?'
|
90
|
+
it "should have #group work the standard way if initial string is a literal string already" do
|
91
|
+
@ds.group(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t GROUP BY a, b, ?, 1'
|
92
92
|
end
|
93
93
|
|
94
|
-
it "should have #
|
94
|
+
it "should have #group work regularly if not given a string as the first argument" do
|
95
95
|
@ds.group(:a, 1).sql.should == 'SELECT * FROM t GROUP BY a, 1'
|
96
96
|
end
|
97
97
|
|
@@ -104,7 +104,7 @@ describe "query_literals extension" do
|
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should have #group_and_count work the standard way if initial string is a literal string already" do
|
107
|
-
@ds.group_and_count('a, b, ?'
|
107
|
+
@ds.group_and_count(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT a, b, ?, 1, count(*) AS count FROM t GROUP BY a, b, ?, 1'
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should have #group_and_count work regularly if not given a string as the first argument" do
|
@@ -120,7 +120,7 @@ describe "query_literals extension" do
|
|
120
120
|
end
|
121
121
|
|
122
122
|
it "should have #order work the standard way if initial string is a literal string already" do
|
123
|
-
@ds.order('a, b, ?'
|
123
|
+
@ds.order(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t ORDER BY a, b, ?, 1'
|
124
124
|
end
|
125
125
|
|
126
126
|
it "should have #order work regularly if not given a string as the first argument" do
|
@@ -141,7 +141,7 @@ describe "query_literals extension" do
|
|
141
141
|
end
|
142
142
|
|
143
143
|
it "should have #order_more work the standard way if initial string is a literal string already" do
|
144
|
-
@ds.order_more('a, b, ?'
|
144
|
+
@ds.order_more(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t ORDER BY d, a, b, ?, 1'
|
145
145
|
end
|
146
146
|
|
147
147
|
it "should have #order_more work regularly if not given a string as the first argument" do
|
@@ -157,7 +157,7 @@ describe "query_literals extension" do
|
|
157
157
|
end
|
158
158
|
|
159
159
|
it "should have #order_append work the standard way if initial string is a literal string already" do
|
160
|
-
@ds.order_prepend('a, b, ?'
|
160
|
+
@ds.order_prepend(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t ORDER BY a, b, ?, 1, d'
|
161
161
|
end
|
162
162
|
|
163
163
|
it "should have #order_append work regularly if not given a string as the first argument" do
|
@@ -41,13 +41,13 @@ describe "Dataset#query" do
|
|
41
41
|
specify "should support #where" do
|
42
42
|
q = @d.query do
|
43
43
|
from :zzz
|
44
|
-
where
|
44
|
+
where{x + 2 > Sequel.expr(:y) + 3}
|
45
45
|
end
|
46
46
|
q.class.should == @d.class
|
47
47
|
q.sql.should == "SELECT * FROM zzz WHERE ((x + 2) > (y + 3))"
|
48
48
|
|
49
49
|
q = @d.from(:zzz).query do
|
50
|
-
where(
|
50
|
+
where{(x > 1) & (Sequel.expr(:y) > 2)}
|
51
51
|
end
|
52
52
|
q.class.should == @d.class
|
53
53
|
q.sql.should == "SELECT * FROM zzz WHERE ((x > 1) AND (y > 2))"
|
@@ -63,7 +63,7 @@ describe "Dataset#query" do
|
|
63
63
|
q = @d.query do
|
64
64
|
from :abc
|
65
65
|
group_by :id
|
66
|
-
having
|
66
|
+
having{x >= 2}
|
67
67
|
end
|
68
68
|
q.class.should == @d.class
|
69
69
|
q.sql.should == "SELECT * FROM abc GROUP BY id HAVING (x >= 2)"
|
@@ -67,7 +67,7 @@ describe "Sequel::Database dump methods" do
|
|
67
67
|
@d.meta_def(:tables){|o| [:t1, :t2]}
|
68
68
|
@d.meta_def(:schema) do |t, *o|
|
69
69
|
case t
|
70
|
-
when :t1, 't__t1', :t__t1
|
70
|
+
when :t1, 't__t1', Sequel.identifier(:t__t1)
|
71
71
|
[[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>false}],
|
72
72
|
[:c2, {:db_type=>'varchar(20)', :allow_null=>true}]]
|
73
73
|
when :t2
|
@@ -88,7 +88,7 @@ describe "Sequel::Database dump methods" do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
it "should support dumping table schemas when given an identifier" do
|
91
|
-
@d.dump_table_schema(:t__t1
|
91
|
+
@d.dump_table_schema(Sequel.identifier(:t__t1)).should == "create_table(\"t__t1\") do\n primary_key :c1\n String :c2, :size=>20\nend"
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should dump non-Integer primary key columns with explicit :type" do
|
@@ -593,10 +593,10 @@ END_MIG
|
|
593
593
|
s
|
594
594
|
end
|
595
595
|
@d.dump_table_schema(:t4).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal.new(\"0.1005E3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.parse(\"2008-10-29\")\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n Time :c9, :default=>Sequel::SQLTime.parse(\"10:20:30\"), :only_time=>true\n String :c10\nend"
|
596
|
-
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30\")\n column :c10, \"interval\", :default
|
596
|
+
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30\")\n column :c10, \"interval\", :default=>Sequel::LiteralString.new(\"'6 weeks'\")\nend"
|
597
597
|
end
|
598
598
|
|
599
|
-
it "should not use a
|
599
|
+
it "should not use a literal string as a fallback if using MySQL with the :same_db option" do
|
600
600
|
@d.meta_def(:database_type){:mysql}
|
601
601
|
@d.meta_def(:schema) do |t, *os|
|
602
602
|
s = [[:c10, {:db_type=>'interval', :default=>"'6 weeks'", :type=>:interval, :allow_null=>true}]]
|
@@ -712,6 +712,22 @@ end
|
|
712
712
|
END_MIG
|
713
713
|
end
|
714
714
|
|
715
|
+
it "should convert mysql types to ruby types" do
|
716
|
+
types = ['double(15,2)', 'double(7,1) unsigned']
|
717
|
+
@d.meta_def(:schema) do |t, *o|
|
718
|
+
i = 0
|
719
|
+
types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
|
720
|
+
end
|
721
|
+
@d.dump_table_schema(:x).should == (<<END_MIG).chomp
|
722
|
+
create_table(:x) do
|
723
|
+
Float :c1
|
724
|
+
Float :c2
|
725
|
+
|
726
|
+
check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c2), 0)
|
727
|
+
end
|
728
|
+
END_MIG
|
729
|
+
end
|
730
|
+
|
715
731
|
it "should use separate primary_key call with non autoincrementable types" do
|
716
732
|
@d.meta_def(:schema){|*s| [[:c1, {:db_type=>'varchar(8)', :primary_key=>true}]]}
|
717
733
|
@d.dump_table_schema(:t3).should == "create_table(:t3) do\n String :c1, :size=>8\n \n primary_key [:c1]\nend"
|
@@ -3,6 +3,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
3
3
|
describe Sequel::Model, "dataset & schema" do
|
4
4
|
before do
|
5
5
|
@model = Class.new(Sequel::Model(:items))
|
6
|
+
@model.plugin :schema
|
6
7
|
end
|
7
8
|
|
8
9
|
specify "sets schema with implicit table name" do
|
@@ -22,27 +23,17 @@ describe Sequel::Model, "dataset & schema" do
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
describe Sequel::Model, "table_exists?" do
|
26
|
-
before do
|
27
|
-
MODEL_DB.reset
|
28
|
-
@model = Class.new(Sequel::Model(:items))
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should get the table name and question the model's db if table_exists?" do
|
32
|
-
@model.db.should_receive(:table_exists?).and_return(false)
|
33
|
-
@model.table_exists?.should == false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
26
|
describe Sequel::Model, "create_table and schema" do
|
38
27
|
before do
|
39
|
-
|
40
|
-
@model
|
28
|
+
@model = Class.new(Sequel::Model)
|
29
|
+
@model.class_eval do
|
30
|
+
plugin :schema
|
41
31
|
set_schema(:items) do
|
42
32
|
text :name
|
43
33
|
float :price, :null => false
|
44
34
|
end
|
45
35
|
end
|
36
|
+
MODEL_DB.reset
|
46
37
|
end
|
47
38
|
|
48
39
|
it "should get the create table SQL list from the db and execute it line by line" do
|
@@ -74,61 +65,47 @@ describe Sequel::Model, "create_table and schema" do
|
|
74
65
|
|
75
66
|
it "should return nil if no schema is present" do
|
76
67
|
@model = Class.new(Sequel::Model)
|
68
|
+
@model.plugin :schema
|
77
69
|
@model.schema.should == nil
|
78
70
|
@submodel = Class.new(@model)
|
79
71
|
@submodel.schema.should == nil
|
80
72
|
end
|
81
73
|
end
|
82
74
|
|
83
|
-
describe Sequel::Model, "
|
75
|
+
describe Sequel::Model, "schema methods" do
|
84
76
|
before do
|
85
77
|
@model = Class.new(Sequel::Model(:items))
|
78
|
+
@model.plugin :schema
|
86
79
|
MODEL_DB.reset
|
87
80
|
end
|
88
81
|
|
89
|
-
it "should
|
90
|
-
@model.
|
91
|
-
|
82
|
+
it "table_exists? should get the table name and question the model's db if table_exists?" do
|
83
|
+
@model.db.should_receive(:table_exists?).and_return(false)
|
84
|
+
@model.table_exists?.should == false
|
92
85
|
end
|
93
|
-
end
|
94
86
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
MODEL_DB.reset
|
87
|
+
it "drop_table should drop the related table" do
|
88
|
+
@model.drop_table
|
89
|
+
MODEL_DB.sqls.should == ['DROP TABLE items']
|
99
90
|
end
|
100
91
|
|
101
|
-
it "should drop the table if it exists" do
|
92
|
+
it "drop_table? should drop the table if it exists" do
|
102
93
|
@model.drop_table?
|
103
94
|
MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items']
|
104
95
|
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe Sequel::Model, "create_table!" do
|
108
|
-
before do
|
109
|
-
MODEL_DB.reset
|
110
|
-
@model = Class.new(Sequel::Model(:items))
|
111
|
-
end
|
112
96
|
|
113
|
-
it "should drop table if it exists and then create the table" do
|
97
|
+
it "create_table! should drop table if it exists and then create the table" do
|
114
98
|
@model.create_table!
|
115
99
|
MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items', 'CREATE TABLE items ()']
|
116
100
|
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe Sequel::Model, "create_table?" do
|
120
|
-
before do
|
121
|
-
MODEL_DB.reset
|
122
|
-
@model = Class.new(Sequel::Model(:items))
|
123
|
-
end
|
124
101
|
|
125
|
-
it "should not create the table if it already exists" do
|
102
|
+
it "create_table? should not create the table if it already exists" do
|
126
103
|
@model.should_receive(:table_exists?).and_return(true)
|
127
104
|
@model.create_table?
|
128
105
|
MODEL_DB.sqls.should == []
|
129
106
|
end
|
130
107
|
|
131
|
-
it "should create the table if it doesn't exist" do
|
108
|
+
it "create_table? should create the table if it doesn't exist" do
|
132
109
|
@model.should_receive(:table_exists?).and_return(false)
|
133
110
|
@model.create_table?
|
134
111
|
MODEL_DB.sqls.should == ['CREATE TABLE items ()']
|
@@ -24,15 +24,15 @@ describe "Dataset#select_remove" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
specify "should handle expressions where Sequel can't determine the alias by itself" do
|
27
|
-
d = @d.select(:a, :b
|
27
|
+
d = @d.select(:a, Sequel.function(:b), Sequel.as(:c, :b))
|
28
28
|
d.columns :a, :"b()", :b
|
29
29
|
d.select_remove(:"b()").sql.should == 'SELECT a, c AS b FROM test'
|
30
30
|
end
|
31
31
|
|
32
32
|
specify "should remove expressions if given exact expressions" do
|
33
|
-
d = @d.select(:a, :b
|
33
|
+
d = @d.select(:a, Sequel.function(:b), Sequel.as(:c, :b))
|
34
34
|
d.columns :a, :"b()", :b
|
35
|
-
d.select_remove(:b
|
36
|
-
d.select_remove(
|
35
|
+
d.select_remove(Sequel.function(:b)).sql.should == 'SELECT a, c AS b FROM test'
|
36
|
+
d.select_remove(Sequel.as(:c, :b)).sql.should == 'SELECT a, b() FROM test'
|
37
37
|
end
|
38
38
|
end
|
@@ -8,13 +8,9 @@ if defined?(RSpec)
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
unless Object.const_defined?('Sequel')
|
11
|
+
unless Object.const_defined?('Sequel') && Sequel.const_defined?('Model')
|
12
12
|
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
13
|
-
require 'sequel/
|
14
|
-
end
|
15
|
-
unless Sequel.const_defined?('Model')
|
16
|
-
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
17
|
-
require 'sequel/model'
|
13
|
+
require 'sequel/no_core_ext'
|
18
14
|
end
|
19
15
|
|
20
16
|
begin
|
@@ -26,8 +22,8 @@ rescue LoadError
|
|
26
22
|
nil
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
|
25
|
+
# Load most extensions by default, so that any conflicts are easily detectable.
|
26
|
+
Sequel.extension(*%w'string_date_time inflector pagination query pretty_table blank migration schema_dumper looser_typecasting sql_expr thread_local_timezones to_dot columns_introspection server_block arbitrary_servers pg_auto_parameterize pg_statement_cache pg_array pg_array_ops pg_hstore pg_hstore_ops pg_range pg_range_ops pg_json pg_inet pg_row pg_row_ops schema_caching null_dataset select_remove query_literals eval_inspect')
|
31
27
|
|
32
28
|
Sequel::Dataset.introspect_all_columns if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
33
29
|
|
@@ -100,19 +100,19 @@ END
|
|
100
100
|
end
|
101
101
|
|
102
102
|
it "should handle SQL::OrderedExpressions" do
|
103
|
-
dot(@ds.order(
|
103
|
+
dot(@ds.order(Sequel.desc(:a, :nulls=>:last))).should == ["1 -> 2 [label=\"order\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"OrderedExpression: DESC NULLS LAST\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];"]
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should handle SQL::AliasedExpressions" do
|
107
|
-
dot(@ds.from(
|
107
|
+
dot(@ds.from(Sequel.as(:a, :b))).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"AliasedExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"alias\"];", "5 [label=\":b\"];"]
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should handle SQL::CaseExpressions" do
|
111
|
-
dot(@ds.select({:a=>:b}
|
111
|
+
dot(@ds.select(Sequel.case({:a=>:b}, :c, :d))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"CaseExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":d\"];", "3 -> 5 [label=\"conditions\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"Array\"];", "6 -> 7 [label=\"0\"];", "7 [label=\":a\"];", "6 -> 8 [label=\"1\"];", "8 [label=\":b\"];", "3 -> 9 [label=\"default\"];", "9 [label=\":c\"];"]
|
112
112
|
end
|
113
113
|
|
114
114
|
it "should handle SQL::Cast" do
|
115
|
-
dot(@ds.select(
|
115
|
+
dot(@ds.select(Sequel.cast(:a, Integer))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Cast\"];", "3 -> 4 [label=\"expr\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"type\"];", "5 [label=\"Integer\"];"]
|
116
116
|
end
|
117
117
|
|
118
118
|
it "should handle SQL::Function" do
|
@@ -120,7 +120,7 @@ END
|
|
120
120
|
end
|
121
121
|
|
122
122
|
it "should handle SQL::Subscript" do
|
123
|
-
dot(@ds.select(:a
|
123
|
+
dot(@ds.select(Sequel.subscript(:a, 1))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Subscript\"];", "3 -> 4 [label=\"f\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"sub\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"1\"];"]
|
124
124
|
end
|
125
125
|
|
126
126
|
it "should handle SQL::WindowFunction" do
|
@@ -1,8 +1,15 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
2
|
|
3
|
+
model_class = proc do |klass, &block|
|
4
|
+
c = Class.new(klass)
|
5
|
+
c.plugin :validation_class_methods
|
6
|
+
c.class_eval(&block) if block
|
7
|
+
c
|
8
|
+
end
|
9
|
+
|
3
10
|
describe Sequel::Model do
|
4
11
|
before do
|
5
|
-
@c =
|
12
|
+
@c = model_class.call Sequel::Model do
|
6
13
|
def self.validates_coolness_of(attr)
|
7
14
|
validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
|
8
15
|
end
|
@@ -135,8 +142,7 @@ end
|
|
135
142
|
|
136
143
|
describe Sequel::Model do
|
137
144
|
before do
|
138
|
-
@c =
|
139
|
-
@c.class_eval do
|
145
|
+
@c = model_class.call Sequel::Model do
|
140
146
|
columns :score
|
141
147
|
validates_each :score do |o, a, v|
|
142
148
|
o.errors[a] << 'too low' if v < 87
|
@@ -165,11 +171,11 @@ describe Sequel::Model do
|
|
165
171
|
end
|
166
172
|
end
|
167
173
|
|
168
|
-
describe Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator do
|
174
|
+
describe "Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator" do
|
169
175
|
before do
|
170
176
|
$testit = nil
|
171
177
|
|
172
|
-
@c =
|
178
|
+
@c = model_class.call Sequel::Model do
|
173
179
|
def self.validates_blah
|
174
180
|
$testit = 1324
|
175
181
|
end
|
@@ -186,7 +192,7 @@ end
|
|
186
192
|
|
187
193
|
describe Sequel::Model do
|
188
194
|
before do
|
189
|
-
@c =
|
195
|
+
@c = model_class.call Sequel::Model do
|
190
196
|
columns :value
|
191
197
|
|
192
198
|
def self.filter(*args)
|
@@ -579,8 +585,7 @@ end
|
|
579
585
|
|
580
586
|
describe "Superclass validations" do
|
581
587
|
before do
|
582
|
-
@c1 =
|
583
|
-
@c1.class_eval do
|
588
|
+
@c1 = model_class.call Sequel::Model do
|
584
589
|
columns :value
|
585
590
|
validates_length_of :value, :minimum => 5
|
586
591
|
end
|
@@ -624,8 +629,7 @@ end
|
|
624
629
|
|
625
630
|
describe ".validates with block" do
|
626
631
|
specify "should support calling .each" do
|
627
|
-
@c =
|
628
|
-
@c.class_eval do
|
632
|
+
@c = model_class.call Sequel::Model do
|
629
633
|
columns :vvv
|
630
634
|
validates do
|
631
635
|
each :vvv do |o, a, v|
|
@@ -646,24 +650,36 @@ describe Sequel::Model, "Validations" do
|
|
646
650
|
|
647
651
|
before(:all) do
|
648
652
|
class ::Person < Sequel::Model
|
653
|
+
plugin :validation_class_methods
|
649
654
|
columns :id,:name,:first_name,:last_name,:middle_name,:initials,:age, :terms
|
650
655
|
end
|
651
656
|
|
652
657
|
class ::Smurf < Person
|
653
658
|
end
|
659
|
+
|
660
|
+
class ::Can < Sequel::Model
|
661
|
+
plugin :validation_class_methods
|
662
|
+
columns :id, :name
|
663
|
+
end
|
654
664
|
|
655
665
|
class ::Cow < Sequel::Model
|
666
|
+
plugin :validation_class_methods
|
656
667
|
columns :id, :name, :got_milk
|
657
668
|
end
|
658
669
|
|
659
670
|
class ::User < Sequel::Model
|
671
|
+
plugin :validation_class_methods
|
660
672
|
columns :id, :username, :password
|
661
673
|
end
|
662
674
|
|
663
675
|
class ::Address < Sequel::Model
|
676
|
+
plugin :validation_class_methods
|
664
677
|
columns :id, :zip_code
|
665
678
|
end
|
666
679
|
end
|
680
|
+
after(:all) do
|
681
|
+
[:Person, :Smurf, :Cow, :User, :Address].each{|c| Object.send(:remove_const, c)}
|
682
|
+
end
|
667
683
|
|
668
684
|
it "should validate the acceptance of a column" do
|
669
685
|
class ::Cow < Sequel::Model
|
@@ -741,8 +757,7 @@ describe Sequel::Model, "Validations" do
|
|
741
757
|
end
|
742
758
|
|
743
759
|
it "should validate that a column doesn't have a string value" do
|
744
|
-
p =
|
745
|
-
p.class_eval do
|
760
|
+
p = model_class.call Sequel::Model do
|
746
761
|
columns :age, :price, :confirmed
|
747
762
|
self.raise_on_typecast_failure = false
|
748
763
|
validates_not_string :age
|
@@ -941,8 +956,6 @@ describe Sequel::Model, "Validations" do
|
|
941
956
|
|
942
957
|
it "should validate correctly instances initialized with string keys" do
|
943
958
|
class ::Can < Sequel::Model
|
944
|
-
columns :id, :name
|
945
|
-
|
946
959
|
validates_length_of :name, :minimum => 4
|
947
960
|
end
|
948
961
|
|
@@ -954,8 +967,7 @@ end
|
|
954
967
|
|
955
968
|
describe "Model#save" do
|
956
969
|
before do
|
957
|
-
@c =
|
958
|
-
@c.class_eval do
|
970
|
+
@c = model_class.call Sequel::Model(:people) do
|
959
971
|
columns :id, :x
|
960
972
|
|
961
973
|
validates_each :x do |o, a, v|
|