sequel 2.9.0 → 2.10.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 +56 -0
- data/{README → README.rdoc} +85 -57
- data/Rakefile +10 -5
- data/bin/sequel +7 -16
- data/doc/advanced_associations.rdoc +5 -17
- data/doc/cheat_sheet.rdoc +18 -20
- data/doc/dataset_filtering.rdoc +8 -32
- data/doc/schema.rdoc +20 -0
- data/lib/sequel_core.rb +35 -1
- data/lib/sequel_core/adapters/ado.rb +1 -1
- data/lib/sequel_core/adapters/db2.rb +2 -2
- data/lib/sequel_core/adapters/dbi.rb +2 -11
- data/lib/sequel_core/adapters/do.rb +205 -0
- data/lib/sequel_core/adapters/do/mysql.rb +38 -0
- data/lib/sequel_core/adapters/do/postgres.rb +92 -0
- data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
- data/lib/sequel_core/adapters/firebird.rb +298 -0
- data/lib/sequel_core/adapters/informix.rb +10 -1
- data/lib/sequel_core/adapters/jdbc.rb +78 -19
- data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
- data/lib/sequel_core/adapters/jdbc/mysql.rb +10 -0
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +7 -3
- data/lib/sequel_core/adapters/mysql.rb +53 -77
- data/lib/sequel_core/adapters/odbc.rb +1 -1
- data/lib/sequel_core/adapters/openbase.rb +1 -1
- data/lib/sequel_core/adapters/oracle.rb +2 -2
- data/lib/sequel_core/adapters/postgres.rb +16 -14
- data/lib/sequel_core/adapters/shared/mysql.rb +44 -9
- data/lib/sequel_core/adapters/shared/oracle.rb +4 -5
- data/lib/sequel_core/adapters/shared/postgres.rb +86 -82
- data/lib/sequel_core/adapters/shared/sqlite.rb +39 -24
- data/lib/sequel_core/adapters/sqlite.rb +11 -1
- data/lib/sequel_core/connection_pool.rb +10 -2
- data/lib/sequel_core/core_sql.rb +13 -3
- data/lib/sequel_core/database.rb +131 -30
- data/lib/sequel_core/database/schema.rb +5 -5
- data/lib/sequel_core/dataset.rb +31 -6
- data/lib/sequel_core/dataset/convenience.rb +11 -11
- data/lib/sequel_core/dataset/query.rb +2 -2
- data/lib/sequel_core/dataset/sql.rb +6 -6
- data/lib/sequel_core/exceptions.rb +4 -0
- data/lib/sequel_core/migration.rb +4 -4
- data/lib/sequel_core/schema/generator.rb +19 -3
- data/lib/sequel_core/schema/sql.rb +24 -20
- data/lib/sequel_core/sql.rb +13 -16
- data/lib/sequel_core/version.rb +11 -0
- data/lib/sequel_model.rb +2 -0
- data/lib/sequel_model/base.rb +2 -2
- data/lib/sequel_model/hooks.rb +46 -7
- data/lib/sequel_model/record.rb +11 -9
- data/lib/sequel_model/schema.rb +1 -1
- data/lib/sequel_model/validations.rb +72 -61
- data/spec/adapters/firebird_spec.rb +371 -0
- data/spec/adapters/mysql_spec.rb +118 -62
- data/spec/adapters/oracle_spec.rb +5 -5
- data/spec/adapters/postgres_spec.rb +33 -18
- data/spec/adapters/sqlite_spec.rb +2 -2
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/schema_test.rb +55 -5
- data/spec/integration/spec_helper.rb +11 -0
- data/spec/integration/type_test.rb +59 -16
- data/spec/sequel_core/connection_pool_spec.rb +14 -0
- data/spec/sequel_core/core_sql_spec.rb +24 -14
- data/spec/sequel_core/database_spec.rb +96 -11
- data/spec/sequel_core/dataset_spec.rb +97 -37
- data/spec/sequel_core/expression_filters_spec.rb +51 -40
- data/spec/sequel_core/object_graph_spec.rb +2 -2
- data/spec/sequel_core/schema_generator_spec.rb +31 -6
- data/spec/sequel_core/schema_spec.rb +25 -9
- data/spec/sequel_core/spec_helper.rb +4 -1
- data/spec/sequel_core/version_spec.rb +7 -0
- data/spec/sequel_model/associations_spec.rb +1 -1
- data/spec/sequel_model/hooks_spec.rb +68 -13
- data/spec/sequel_model/model_spec.rb +4 -4
- data/spec/sequel_model/record_spec.rb +22 -0
- data/spec/sequel_model/spec_helper.rb +2 -1
- data/spec/sequel_model/validations_spec.rb +107 -7
- metadata +15 -5
@@ -138,7 +138,7 @@ describe Sequel::Dataset, " graphing" do
|
|
138
138
|
end
|
139
139
|
|
140
140
|
it "#set_graph_aliases should allow a third entry to specify an expression to use other than the default" do
|
141
|
-
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, :random
|
141
|
+
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, :random.sql_function])
|
142
142
|
['SELECT 1 AS x, random() AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
|
143
143
|
'SELECT random() AS y, 1 AS x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
144
144
|
].should(include(ds.sql))
|
@@ -241,7 +241,7 @@ describe Sequel::Dataset, " graphing" do
|
|
241
241
|
end
|
242
242
|
|
243
243
|
it "#graph_each should correctly map values when #set_graph_aliases is used with a third argument for each entry" do
|
244
|
-
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, :random
|
244
|
+
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, :random.sql_function])
|
245
245
|
def ds.fetch_rows(sql, &block)
|
246
246
|
yield({:x=>2,:y=>3})
|
247
247
|
end
|
@@ -47,9 +47,9 @@ describe Sequel::Schema::Generator do
|
|
47
47
|
|
48
48
|
it "creates foreign key column" do
|
49
49
|
@columns[3][:name].should == :parent_id
|
50
|
-
@columns[3][:type].should ==
|
50
|
+
@columns[3][:type].should == Integer
|
51
51
|
@columns[6][:name].should == :node_id
|
52
|
-
@columns[6][:type].should ==
|
52
|
+
@columns[6][:type].should == Integer
|
53
53
|
end
|
54
54
|
|
55
55
|
it "uses table for foreign key columns, if specified" do
|
@@ -107,7 +107,7 @@ describe Sequel::Schema::AlterTableGenerator do
|
|
107
107
|
add_spatial_index :geom
|
108
108
|
add_index :blah, :type => :hash
|
109
109
|
add_index :blah, :where => {:something => true}
|
110
|
-
add_constraint :con1, '
|
110
|
+
add_constraint :con1, 'fred > 100'
|
111
111
|
drop_constraint :con2
|
112
112
|
add_unique_constraint [:aaa, :bbb, :ccc], :name => :con3
|
113
113
|
add_primary_key :id
|
@@ -130,13 +130,38 @@ describe Sequel::Schema::AlterTableGenerator do
|
|
130
130
|
{:op => :add_index, :columns => [:geom], :type => :spatial},
|
131
131
|
{:op => :add_index, :columns => [:blah], :type => :hash},
|
132
132
|
{:op => :add_index, :columns => [:blah], :where => {:something => true}},
|
133
|
-
{:op => :add_constraint, :type => :check, :constraint_type => :check, :name => :con1, :check => ['
|
133
|
+
{:op => :add_constraint, :type => :check, :constraint_type => :check, :name => :con1, :check => ['fred > 100']},
|
134
134
|
{:op => :drop_constraint, :name => :con2},
|
135
135
|
{:op => :add_constraint, :type => :check, :constraint_type => :unique, :name => :con3, :columns => [:aaa, :bbb, :ccc]},
|
136
|
-
{:op => :add_column, :name => :id, :type =>
|
137
|
-
{:op => :add_column, :name => :node_id, :type =>
|
136
|
+
{:op => :add_column, :name => :id, :type => Integer, :primary_key=>true, :auto_increment=>true},
|
137
|
+
{:op => :add_column, :name => :node_id, :type => Integer, :table=>:nodes},
|
138
138
|
{:op => :add_constraint, :type => :check, :constraint_type => :primary_key, :columns => [:aaa, :bbb]},
|
139
139
|
{:op => :add_constraint, :type => :check, :constraint_type => :foreign_key, :columns => [:node_id, :prop_id], :table => :nodes_props}
|
140
140
|
]
|
141
141
|
end
|
142
142
|
end
|
143
|
+
|
144
|
+
describe "Sequel::Schema::Generator generic type methods" do
|
145
|
+
before do
|
146
|
+
@generator = Sequel::Schema::Generator.new(SchemaDummyDatabase.new) do
|
147
|
+
String :a
|
148
|
+
Integer :b
|
149
|
+
Fixnum :c
|
150
|
+
Bignum :d
|
151
|
+
Float :e
|
152
|
+
BigDecimal :f
|
153
|
+
Date :g
|
154
|
+
DateTime :h
|
155
|
+
Time :i
|
156
|
+
Numeric :j
|
157
|
+
File :k
|
158
|
+
TrueClass :l
|
159
|
+
FalseClass :m
|
160
|
+
end
|
161
|
+
@columns, @indexes = @generator.create_info
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should store the type class in :type for each column" do
|
165
|
+
@columns.map{|c| c[:type]}.should == [String, Integer, Fixnum, Bignum, Float, BigDecimal, Date, DateTime, Time, Numeric, File, TrueClass, FalseClass]
|
166
|
+
end
|
167
|
+
end
|
@@ -38,6 +38,28 @@ context "DB#create_table" do
|
|
38
38
|
end
|
39
39
|
@db.sqls.should == ['CREATE TABLE cats (id integer, name text)']
|
40
40
|
end
|
41
|
+
|
42
|
+
specify "should transform types given as ruby classes to database-specific types" do
|
43
|
+
@db.create_table(:cats) do
|
44
|
+
String :a
|
45
|
+
Integer :b
|
46
|
+
Fixnum :c
|
47
|
+
Bignum :d
|
48
|
+
Float :e
|
49
|
+
BigDecimal :f
|
50
|
+
Date :g
|
51
|
+
DateTime :h
|
52
|
+
Time :i
|
53
|
+
Numeric :j
|
54
|
+
File :k
|
55
|
+
TrueClass :l
|
56
|
+
FalseClass :m
|
57
|
+
column :n, Fixnum
|
58
|
+
primary_key :o, :type=>String
|
59
|
+
foreign_key :p, :f, :type=>Date
|
60
|
+
end
|
61
|
+
@db.sqls.should == ['CREATE TABLE cats (o varchar(255) PRIMARY KEY AUTOINCREMENT, a varchar(255), b integer, c integer, d bigint, e double precision, f numeric, g date, h timestamp, i timestamp, j numeric, k blob, l boolean, m boolean, n integer, p date REFERENCES f)']
|
62
|
+
end
|
41
63
|
|
42
64
|
specify "should accept primary key definition" do
|
43
65
|
@db.create_table(:cats) do
|
@@ -332,7 +354,7 @@ context "DB#create_table" do
|
|
332
354
|
specify "should accept unnamed constraint definitions with blocks" do
|
333
355
|
@db.create_table(:cats) do
|
334
356
|
integer :score
|
335
|
-
check {(:x > 0) & (:y < 1)}
|
357
|
+
check {(:x.sql_number > 0) & (:y.sql_number < 1)}
|
336
358
|
end
|
337
359
|
@db.sqls.should == ["CREATE TABLE cats (score integer, CHECK ((x > 0) AND (y < 1)))"]
|
338
360
|
end
|
@@ -361,7 +383,7 @@ context "DB#create_table" do
|
|
361
383
|
|
362
384
|
specify "should accept named constraint definitions with block" do
|
363
385
|
@db.create_table(:cats) do
|
364
|
-
constraint(:blah_blah) {(:x > 0) & (:y < 1)}
|
386
|
+
constraint(:blah_blah) {(:x.sql_number > 0) & (:y.sql_number < 1)}
|
365
387
|
end
|
366
388
|
@db.sqls.should == ["CREATE TABLE cats (CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1)))"]
|
367
389
|
end
|
@@ -510,7 +532,7 @@ context "DB#alter_table" do
|
|
510
532
|
|
511
533
|
specify "should support add_constraint with block" do
|
512
534
|
@db.alter_table(:cats) do
|
513
|
-
add_constraint(:blah_blah) {(:x > 0) & (:y < 1)}
|
535
|
+
add_constraint(:blah_blah) {(:x.sql_number > 0) & (:y.sql_number < 1)}
|
514
536
|
end
|
515
537
|
@db.sqls.should == ["ALTER TABLE cats ADD CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1))"]
|
516
538
|
end
|
@@ -686,12 +708,6 @@ context "Schema Parser" do
|
|
686
708
|
@sqls.should == ['x']
|
687
709
|
@db.schema(nil, :reload=>true).should == {'x'=>[[:x, {:db_type=>"x"}]]}
|
688
710
|
@sqls.should == ['x', 'x']
|
689
|
-
@db.meta_def(:schema_parse_tables) do |opts|
|
690
|
-
sqls << 1
|
691
|
-
{'x'=>[[:a, {:db_type=>"1"}]]}
|
692
|
-
end
|
693
|
-
@db.schema(nil, :reload=>true).should == {'x'=>[[:a, {:db_type=>"1"}]]}
|
694
|
-
@sqls.should == ['x', 'x', 1]
|
695
711
|
end
|
696
712
|
|
697
713
|
specify "should convert various types of table name arguments" do
|
@@ -25,7 +25,8 @@ end
|
|
25
25
|
|
26
26
|
class MockDatabase < Sequel::Database
|
27
27
|
@@quote_identifiers = false
|
28
|
-
|
28
|
+
self.identifier_input_method = nil
|
29
|
+
self.identifier_output_method = nil
|
29
30
|
attr_reader :sqls
|
30
31
|
|
31
32
|
def execute(sql, opts={})
|
@@ -44,6 +45,8 @@ end
|
|
44
45
|
|
45
46
|
class SchemaDummyDatabase < Sequel::Database
|
46
47
|
attr_reader :sqls
|
48
|
+
self.identifier_input_method = nil
|
49
|
+
self.identifier_output_method = nil
|
47
50
|
|
48
51
|
def execute(sql, opts={})
|
49
52
|
@sqls ||= []
|
@@ -120,7 +120,7 @@ describe Sequel::Model, "many_to_one" do
|
|
120
120
|
it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
|
121
121
|
c2 = @c2
|
122
122
|
@c2.many_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{c2.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
|
123
|
-
ds.filter(:x > 1)
|
123
|
+
ds.filter(:x.sql_number > 1)
|
124
124
|
end
|
125
125
|
@c2.load(:id => 100).child_20
|
126
126
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((parent_id = 100) AND (x > 1)) ORDER BY name LIMIT 1 OFFSET 20"]
|
@@ -37,8 +37,20 @@ describe "Model hooks" do
|
|
37
37
|
c.new.before_save
|
38
38
|
$adds.should == ['bye']
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
specify "should be additive" do
|
42
|
+
$adds = []
|
43
|
+
c = Class.new(Sequel::Model)
|
44
|
+
c.class_eval do
|
45
|
+
after_save {$adds << 'hyiyie'}
|
46
|
+
after_save {$adds << 'byiyie'}
|
47
|
+
end
|
48
|
+
|
49
|
+
c.new.after_save
|
50
|
+
$adds.should == ['hyiyie', 'byiyie']
|
51
|
+
end
|
52
|
+
|
53
|
+
specify "before hooks should run in reverse order" do
|
42
54
|
$adds = []
|
43
55
|
c = Class.new(Sequel::Model)
|
44
56
|
c.class_eval do
|
@@ -47,7 +59,7 @@ describe "Model hooks" do
|
|
47
59
|
end
|
48
60
|
|
49
61
|
c.new.before_save
|
50
|
-
$adds.should == ['
|
62
|
+
$adds.should == ['byiyie', 'hyiyie']
|
51
63
|
end
|
52
64
|
|
53
65
|
specify "should not be additive if the method or tag already exists" do
|
@@ -101,16 +113,16 @@ describe "Model hooks" do
|
|
101
113
|
$adds = []
|
102
114
|
a = Class.new(Sequel::Model)
|
103
115
|
a.class_eval do
|
104
|
-
|
116
|
+
after_save {$adds << '123'}
|
105
117
|
end
|
106
118
|
|
107
119
|
b = Class.new(a)
|
108
120
|
b.class_eval do
|
109
|
-
|
110
|
-
|
121
|
+
after_save {$adds << '456'}
|
122
|
+
after_save {$adds << '789'}
|
111
123
|
end
|
112
124
|
|
113
|
-
b.new.
|
125
|
+
b.new.after_save
|
114
126
|
$adds.should == ['123', '456', '789']
|
115
127
|
end
|
116
128
|
|
@@ -139,31 +151,31 @@ describe "Model hooks" do
|
|
139
151
|
|
140
152
|
a = Class.new(Sequel::Model)
|
141
153
|
a.class_eval do
|
142
|
-
|
143
|
-
|
154
|
+
after_save {$adds << 'blah'; $flag}
|
155
|
+
after_save {$adds << 'cruel'}
|
144
156
|
end
|
145
157
|
|
146
|
-
a.new.
|
158
|
+
a.new.after_save
|
147
159
|
$adds.should == ['blah', 'cruel']
|
148
160
|
|
149
161
|
# chain should not break on nil
|
150
162
|
$adds = []
|
151
163
|
$flag = nil
|
152
|
-
a.new.
|
164
|
+
a.new.after_save
|
153
165
|
$adds.should == ['blah', 'cruel']
|
154
166
|
|
155
167
|
$adds = []
|
156
168
|
$flag = false
|
157
|
-
a.new.
|
169
|
+
a.new.after_save
|
158
170
|
$adds.should == ['blah']
|
159
171
|
|
160
172
|
b = Class.new(a)
|
161
173
|
b.class_eval do
|
162
|
-
|
174
|
+
after_save {$adds << 'mau'}
|
163
175
|
end
|
164
176
|
|
165
177
|
$adds = []
|
166
|
-
b.new.
|
178
|
+
b.new.after_save
|
167
179
|
$adds.should == ['blah']
|
168
180
|
end
|
169
181
|
end
|
@@ -428,3 +440,46 @@ describe "Model.has_hooks?" do
|
|
428
440
|
@d.has_hooks?(:before_save).should be_false
|
429
441
|
end
|
430
442
|
end
|
443
|
+
|
444
|
+
describe "Model#add_hook_type" do
|
445
|
+
setup do
|
446
|
+
class Foo < Sequel::Model(:items)
|
447
|
+
add_hook_type :before_bar, :after_bar
|
448
|
+
|
449
|
+
def bar
|
450
|
+
return :b if before_bar == false
|
451
|
+
return :a if after_bar == false
|
452
|
+
true
|
453
|
+
end
|
454
|
+
end
|
455
|
+
@f = Class.new(Foo)
|
456
|
+
end
|
457
|
+
|
458
|
+
specify "should have before_bar and after_bar class methods" do
|
459
|
+
@f.should respond_to(:before_bar)
|
460
|
+
@f.should respond_to(:before_bar)
|
461
|
+
end
|
462
|
+
|
463
|
+
specify "should have before_bar and after_bar instance methods" do
|
464
|
+
@f.new.should respond_to(:before_bar)
|
465
|
+
@f.new.should respond_to(:before_bar)
|
466
|
+
end
|
467
|
+
|
468
|
+
specify "it should return true for bar when before_bar and after_bar hooks are returing true" do
|
469
|
+
a = 1
|
470
|
+
@f.before_bar { a += 1}
|
471
|
+
@f.new.bar.should be_true
|
472
|
+
a.should == 2
|
473
|
+
@f.after_bar { a *= 2}
|
474
|
+
@f.new.bar.should be_true
|
475
|
+
a.should == 6
|
476
|
+
end
|
477
|
+
|
478
|
+
specify "it should return nil for bar when before_bar and after_bar hooks are returing false" do
|
479
|
+
@f.new.bar.should be_true
|
480
|
+
@f.after_bar { false }
|
481
|
+
@f.new.bar.should == :a
|
482
|
+
@f.before_bar { false }
|
483
|
+
@f.new.bar.should == :b
|
484
|
+
end
|
485
|
+
end
|
@@ -219,12 +219,12 @@ describe Sequel::Model, ".subset" do
|
|
219
219
|
specify "should create a filter on the underlying dataset" do
|
220
220
|
proc {@c.new_only}.should raise_error(NoMethodError)
|
221
221
|
|
222
|
-
@c.subset(:new_only) {:age < 'new'}
|
222
|
+
@c.subset(:new_only) {:age.sql_number < 'new'}
|
223
223
|
|
224
224
|
@c.new_only.sql.should == "SELECT * FROM items WHERE (age < 'new')"
|
225
225
|
@c.dataset.new_only.sql.should == "SELECT * FROM items WHERE (age < 'new')"
|
226
226
|
|
227
|
-
@c.subset(:pricey) {:price > 100}
|
227
|
+
@c.subset(:pricey) {:price.sql_number > 100}
|
228
228
|
|
229
229
|
@c.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
|
230
230
|
@c.dataset.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
|
@@ -262,10 +262,10 @@ describe Sequel::Model, ".find" do
|
|
262
262
|
end
|
263
263
|
|
264
264
|
specify "should accept filter blocks" do
|
265
|
-
@c.find{:id > 1}.should be_a_kind_of(@c)
|
265
|
+
@c.find{:id.sql_number > 1}.should be_a_kind_of(@c)
|
266
266
|
$sqls.last.should == "SELECT * FROM items WHERE (id > 1) LIMIT 1"
|
267
267
|
|
268
|
-
@c.find {(:x > 1) & (:y < 2)}.should be_a_kind_of(@c)
|
268
|
+
@c.find {(:x.sql_number > 1) & (:y.sql_number < 2)}.should be_a_kind_of(@c)
|
269
269
|
$sqls.last.should == "SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"
|
270
270
|
end
|
271
271
|
|
@@ -54,6 +54,28 @@ describe "Model#save" do
|
|
54
54
|
o.save(:y)
|
55
55
|
o.changed_columns.should == []
|
56
56
|
end
|
57
|
+
|
58
|
+
it "should preserve changed_columns' and @new's value until all hook finish running" do
|
59
|
+
res = nil
|
60
|
+
@c.after_save { res = [changed_columns, @new].flatten}
|
61
|
+
o = @c.new(:x => 1, :y => nil)
|
62
|
+
o[:x] = 2
|
63
|
+
o.save
|
64
|
+
res.should == [:x,true]
|
65
|
+
|
66
|
+
res = nil
|
67
|
+
o = @c.load(:id => 23,:x => 1, :y => nil)
|
68
|
+
o[:x] = 2
|
69
|
+
o.save
|
70
|
+
res.should == [:x,false]
|
71
|
+
|
72
|
+
res = nil
|
73
|
+
o = @c.load(:id => 23,:x => 1, :y => nil)
|
74
|
+
o[:x] = 2
|
75
|
+
o[:y] = 22
|
76
|
+
o.save(:x)
|
77
|
+
res.should == [:x,:y,false]
|
78
|
+
end
|
57
79
|
|
58
80
|
end
|
59
81
|
|
@@ -120,6 +120,39 @@ describe Sequel::Model do
|
|
120
120
|
atts.should == [:xx, :yy]
|
121
121
|
end
|
122
122
|
|
123
|
+
specify "should respect allow_missing option when using multiple attributes" do
|
124
|
+
o = @c.new
|
125
|
+
def o.xx
|
126
|
+
self[:xx]
|
127
|
+
end
|
128
|
+
def o.yy
|
129
|
+
self[:yy]
|
130
|
+
end
|
131
|
+
vals = nil
|
132
|
+
atts = nil
|
133
|
+
@c.validates_each([:xx, :yy], :allow_missing=>true){|obj,a,v| atts=a; vals=v}
|
134
|
+
|
135
|
+
o.values[:xx] = 1
|
136
|
+
o.valid?
|
137
|
+
vals.should == [1,nil]
|
138
|
+
atts.should == [:xx, :yy]
|
139
|
+
|
140
|
+
vals = nil
|
141
|
+
atts = nil
|
142
|
+
o.values.clear
|
143
|
+
o.values[:yy] = 2
|
144
|
+
o.valid?
|
145
|
+
vals.should == [nil, 2]
|
146
|
+
atts.should == [:xx, :yy]
|
147
|
+
|
148
|
+
vals = nil
|
149
|
+
atts = nil
|
150
|
+
o.values.clear
|
151
|
+
o.valid?.should == true
|
152
|
+
vals.should == nil
|
153
|
+
atts.should == nil
|
154
|
+
end
|
155
|
+
|
123
156
|
specify "should overwrite existing validation with the same tag and attribute" do
|
124
157
|
@c.validates_each(:xx, :xx, :tag=>:low) {|o, a, v| o.xxx; o.errors[a] << 'too low' if v < 50}
|
125
158
|
@c.validates_each(:yy, :yy) {|o, a, v| o.yyy; o.errors[a] << 'too low' if v < 50}
|
@@ -243,6 +276,18 @@ describe Sequel::Model do
|
|
243
276
|
@m.should_not be_valid
|
244
277
|
end
|
245
278
|
|
279
|
+
specify "should validate acceptance_of with allow_missing => true" do
|
280
|
+
@c.validates_acceptance_of :value, :allow_missing => true
|
281
|
+
@m.should be_valid
|
282
|
+
end
|
283
|
+
|
284
|
+
specify "should validate acceptance_of with allow_missing => true and allow_nil => false" do
|
285
|
+
@c.validates_acceptance_of :value, :allow_missing => true, :allow_nil => false
|
286
|
+
@m.should be_valid
|
287
|
+
@m.value = nil
|
288
|
+
@m.should_not be_valid
|
289
|
+
end
|
290
|
+
|
246
291
|
specify "should validate acceptance_of with if => true" do
|
247
292
|
@c.validates_acceptance_of :value, :if => :dont_skip
|
248
293
|
@m.value = '0'
|
@@ -300,6 +345,16 @@ describe Sequel::Model do
|
|
300
345
|
@m.should be_valid
|
301
346
|
end
|
302
347
|
|
348
|
+
specify "should validate confirmation_of with allow_missing => true" do
|
349
|
+
@c.send(:attr_accessor, :value_confirmation)
|
350
|
+
@c.validates_acceptance_of :value, :allow_missing => true
|
351
|
+
@m.should be_valid
|
352
|
+
@m.value_confirmation = 'blah'
|
353
|
+
@m.should be_valid
|
354
|
+
@m.value = nil
|
355
|
+
@m.should_not be_valid
|
356
|
+
end
|
357
|
+
|
303
358
|
specify "should validate format_of" do
|
304
359
|
@c.validates_format_of :value, :with => /.+_.+/
|
305
360
|
@m.value = 'abc_'
|
@@ -327,6 +382,13 @@ describe Sequel::Model do
|
|
327
382
|
@m.should be_valid
|
328
383
|
end
|
329
384
|
|
385
|
+
specify "should validate format_of with allow_missing => true" do
|
386
|
+
@c.validates_format_of :value, :allow_missing => true, :with=>/./
|
387
|
+
@m.should be_valid
|
388
|
+
@m.value = nil
|
389
|
+
@m.should_not be_valid
|
390
|
+
end
|
391
|
+
|
330
392
|
specify "should validate length_of with maximum" do
|
331
393
|
@c.validates_length_of :value, :maximum => 5
|
332
394
|
@m.should_not be_valid
|
@@ -386,6 +448,13 @@ describe Sequel::Model do
|
|
386
448
|
@m.should be_valid
|
387
449
|
end
|
388
450
|
|
451
|
+
specify "should validate length_of with allow_missing => true" do
|
452
|
+
@c.validates_length_of :value, :allow_missing => true, :minimum => 5
|
453
|
+
@m.should be_valid
|
454
|
+
@m.value = nil
|
455
|
+
@m.should_not be_valid
|
456
|
+
end
|
457
|
+
|
389
458
|
specify "should allow multiple calls to validates_length_of with different options without overwriting" do
|
390
459
|
@c.validates_length_of :value, :maximum => 5
|
391
460
|
@c.validates_length_of :value, :minimum => 5
|
@@ -450,6 +519,13 @@ describe Sequel::Model do
|
|
450
519
|
@m.should be_valid
|
451
520
|
end
|
452
521
|
|
522
|
+
specify "should validate numericality_of with allow_missing => true" do
|
523
|
+
@c.validates_numericality_of :value, :allow_missing => true
|
524
|
+
@m.should be_valid
|
525
|
+
@m.value = nil
|
526
|
+
@m.should_not be_valid
|
527
|
+
end
|
528
|
+
|
453
529
|
specify "should validate presence_of" do
|
454
530
|
@c.validates_presence_of :value
|
455
531
|
@m.should_not be_valid
|
@@ -475,6 +551,13 @@ describe Sequel::Model do
|
|
475
551
|
@m.should be_valid
|
476
552
|
end
|
477
553
|
|
554
|
+
specify "should validate presence_of with allow_missing => true" do
|
555
|
+
@c.validates_presence_of :value, :allow_missing => true
|
556
|
+
@m.should be_valid
|
557
|
+
@m.value = nil
|
558
|
+
@m.should_not be_valid
|
559
|
+
end
|
560
|
+
|
478
561
|
specify "should validate uniqueness_of with if => true" do
|
479
562
|
@c.validates_uniqueness_of :value, :if => :dont_skip
|
480
563
|
|
@@ -489,10 +572,11 @@ describe Sequel::Model do
|
|
489
572
|
@m.should be_valid
|
490
573
|
end
|
491
574
|
|
492
|
-
specify "should validate with
|
493
|
-
@c.
|
494
|
-
|
575
|
+
specify "should validate uniqueness_of with allow_missing => true" do
|
576
|
+
@c.validates_uniqueness_of :value, :allow_missing => true
|
495
577
|
@m.should be_valid
|
578
|
+
@m.value = nil
|
579
|
+
@m.should_not be_valid
|
496
580
|
end
|
497
581
|
end
|
498
582
|
|
@@ -631,10 +715,6 @@ describe Sequel::Model, "Validations" do
|
|
631
715
|
@person.valid?.should be_true
|
632
716
|
end
|
633
717
|
|
634
|
-
# it "should allow for :with_exactly => /[a-zA-Z]/, which wraps the supplied regex with ^<regex>$" do
|
635
|
-
# pending("TODO: Add this option to Validatable#validates_format_of")
|
636
|
-
# end
|
637
|
-
|
638
718
|
it "should validate length of column" do
|
639
719
|
class ::Person < Sequel::Model
|
640
720
|
validations.clear
|
@@ -667,6 +747,26 @@ describe Sequel::Model, "Validations" do
|
|
667
747
|
@person.should be_valid
|
668
748
|
end
|
669
749
|
|
750
|
+
it "should validate that a column doesn't have a string value" do
|
751
|
+
p = Class.new(Sequel::Model)
|
752
|
+
p.class_eval do
|
753
|
+
columns :age
|
754
|
+
self.raise_on_typecast_failure = false
|
755
|
+
validates_not_string :age
|
756
|
+
@db_schema = {:age=>{:type=>:integer}}
|
757
|
+
end
|
758
|
+
|
759
|
+
@person = p.new :age => "a"
|
760
|
+
@person.should_not be_valid
|
761
|
+
@person.errors.full_messages.should == ['age is not a valid integer']
|
762
|
+
@person.db_schema[:age][:type] = :datetime
|
763
|
+
@person.should_not be_valid
|
764
|
+
@person.errors.full_messages.should == ['age is not a valid datetime']
|
765
|
+
|
766
|
+
@person.age = 20
|
767
|
+
@person.should be_valid
|
768
|
+
end
|
769
|
+
|
670
770
|
it "should validate numericality of column" do
|
671
771
|
class ::Person < Sequel::Model
|
672
772
|
validations.clear
|