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.
Files changed (78) hide show
  1. data/CHANGELOG +56 -0
  2. data/{README → README.rdoc} +85 -57
  3. data/Rakefile +10 -5
  4. data/bin/sequel +7 -16
  5. data/doc/advanced_associations.rdoc +5 -17
  6. data/doc/cheat_sheet.rdoc +18 -20
  7. data/doc/dataset_filtering.rdoc +8 -32
  8. data/doc/schema.rdoc +20 -0
  9. data/lib/sequel_core.rb +35 -1
  10. data/lib/sequel_core/adapters/ado.rb +1 -1
  11. data/lib/sequel_core/adapters/db2.rb +2 -2
  12. data/lib/sequel_core/adapters/dbi.rb +2 -11
  13. data/lib/sequel_core/adapters/do.rb +205 -0
  14. data/lib/sequel_core/adapters/do/mysql.rb +38 -0
  15. data/lib/sequel_core/adapters/do/postgres.rb +92 -0
  16. data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
  17. data/lib/sequel_core/adapters/firebird.rb +298 -0
  18. data/lib/sequel_core/adapters/informix.rb +10 -1
  19. data/lib/sequel_core/adapters/jdbc.rb +78 -19
  20. data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
  21. data/lib/sequel_core/adapters/jdbc/mysql.rb +10 -0
  22. data/lib/sequel_core/adapters/jdbc/postgresql.rb +7 -3
  23. data/lib/sequel_core/adapters/mysql.rb +53 -77
  24. data/lib/sequel_core/adapters/odbc.rb +1 -1
  25. data/lib/sequel_core/adapters/openbase.rb +1 -1
  26. data/lib/sequel_core/adapters/oracle.rb +2 -2
  27. data/lib/sequel_core/adapters/postgres.rb +16 -14
  28. data/lib/sequel_core/adapters/shared/mysql.rb +44 -9
  29. data/lib/sequel_core/adapters/shared/oracle.rb +4 -5
  30. data/lib/sequel_core/adapters/shared/postgres.rb +86 -82
  31. data/lib/sequel_core/adapters/shared/sqlite.rb +39 -24
  32. data/lib/sequel_core/adapters/sqlite.rb +11 -1
  33. data/lib/sequel_core/connection_pool.rb +10 -2
  34. data/lib/sequel_core/core_sql.rb +13 -3
  35. data/lib/sequel_core/database.rb +131 -30
  36. data/lib/sequel_core/database/schema.rb +5 -5
  37. data/lib/sequel_core/dataset.rb +31 -6
  38. data/lib/sequel_core/dataset/convenience.rb +11 -11
  39. data/lib/sequel_core/dataset/query.rb +2 -2
  40. data/lib/sequel_core/dataset/sql.rb +6 -6
  41. data/lib/sequel_core/exceptions.rb +4 -0
  42. data/lib/sequel_core/migration.rb +4 -4
  43. data/lib/sequel_core/schema/generator.rb +19 -3
  44. data/lib/sequel_core/schema/sql.rb +24 -20
  45. data/lib/sequel_core/sql.rb +13 -16
  46. data/lib/sequel_core/version.rb +11 -0
  47. data/lib/sequel_model.rb +2 -0
  48. data/lib/sequel_model/base.rb +2 -2
  49. data/lib/sequel_model/hooks.rb +46 -7
  50. data/lib/sequel_model/record.rb +11 -9
  51. data/lib/sequel_model/schema.rb +1 -1
  52. data/lib/sequel_model/validations.rb +72 -61
  53. data/spec/adapters/firebird_spec.rb +371 -0
  54. data/spec/adapters/mysql_spec.rb +118 -62
  55. data/spec/adapters/oracle_spec.rb +5 -5
  56. data/spec/adapters/postgres_spec.rb +33 -18
  57. data/spec/adapters/sqlite_spec.rb +2 -2
  58. data/spec/integration/dataset_test.rb +3 -3
  59. data/spec/integration/schema_test.rb +55 -5
  60. data/spec/integration/spec_helper.rb +11 -0
  61. data/spec/integration/type_test.rb +59 -16
  62. data/spec/sequel_core/connection_pool_spec.rb +14 -0
  63. data/spec/sequel_core/core_sql_spec.rb +24 -14
  64. data/spec/sequel_core/database_spec.rb +96 -11
  65. data/spec/sequel_core/dataset_spec.rb +97 -37
  66. data/spec/sequel_core/expression_filters_spec.rb +51 -40
  67. data/spec/sequel_core/object_graph_spec.rb +2 -2
  68. data/spec/sequel_core/schema_generator_spec.rb +31 -6
  69. data/spec/sequel_core/schema_spec.rb +25 -9
  70. data/spec/sequel_core/spec_helper.rb +4 -1
  71. data/spec/sequel_core/version_spec.rb +7 -0
  72. data/spec/sequel_model/associations_spec.rb +1 -1
  73. data/spec/sequel_model/hooks_spec.rb +68 -13
  74. data/spec/sequel_model/model_spec.rb +4 -4
  75. data/spec/sequel_model/record_spec.rb +22 -0
  76. data/spec/sequel_model/spec_helper.rb +2 -1
  77. data/spec/sequel_model/validations_spec.rb +107 -7
  78. 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 == :integer
50
+ @columns[3][:type].should == Integer
51
51
  @columns[6][:name].should == :node_id
52
- @columns[6][:type].should == :integer
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, ':fred > 100'
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 => [':fred > 100']},
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 => :integer, :primary_key=>true, :auto_increment=>true},
137
- {:op => :add_column, :name => :node_id, :type => :integer, :table=>:nodes},
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
- @@upcase_identifiers = false
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 ||= []
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "Sequel.version" do
4
+ specify "should be in the form X.Y.Z with all being numbers" do
5
+ Sequel.version.should =~ /\A\d+\.\d+\.\d+\z/
6
+ end
7
+ end
@@ -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 == ['hyiyie', 'byiyie']
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
- before_save {$adds << '123'}
116
+ after_save {$adds << '123'}
105
117
  end
106
118
 
107
119
  b = Class.new(a)
108
120
  b.class_eval do
109
- before_save {$adds << '456'}
110
- before_save {$adds << '789'}
121
+ after_save {$adds << '456'}
122
+ after_save {$adds << '789'}
111
123
  end
112
124
 
113
- b.new.before_save
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
- before_save {$adds << 'blah'; $flag}
143
- before_save {$adds << 'cruel'}
154
+ after_save {$adds << 'blah'; $flag}
155
+ after_save {$adds << 'cruel'}
144
156
  end
145
157
 
146
- a.new.before_save
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.before_save
164
+ a.new.after_save
153
165
  $adds.should == ['blah', 'cruel']
154
166
 
155
167
  $adds = []
156
168
  $flag = false
157
- a.new.before_save
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
- before_save {$adds << 'mau'}
174
+ after_save {$adds << 'mau'}
163
175
  end
164
176
 
165
177
  $adds = []
166
- b.new.before_save
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
 
@@ -34,7 +34,8 @@ end
34
34
 
35
35
  class MockDatabase < Sequel::Database
36
36
  @@quote_identifiers = false
37
- @@upcase_identifiers = false
37
+ self.identifier_input_method = nil
38
+ self.identifier_output_method = nil
38
39
  attr_reader :sqls
39
40
 
40
41
  def execute(sql, opts={})
@@ -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 :if => block" do
493
- @c.validates_presence_of :value, :if => proc {false}
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