sequel 2.11.0 → 2.12.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 +168 -0
- data/README.rdoc +77 -95
- data/Rakefile +100 -80
- data/bin/sequel +2 -1
- data/doc/advanced_associations.rdoc +23 -32
- data/doc/cheat_sheet.rdoc +23 -40
- data/doc/dataset_filtering.rdoc +6 -6
- data/doc/prepared_statements.rdoc +22 -22
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/schema.rdoc +3 -1
- data/doc/sharding.rdoc +8 -8
- data/doc/virtual_rows.rdoc +65 -0
- data/lib/sequel.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
- data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
- data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
- data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
- data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
- data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
- data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
- data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
- data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
- data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
- data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
- data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
- data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
- data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
- data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
- data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
- data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
- data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
- data/lib/sequel/core.rb +221 -0
- data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
- data/lib/{sequel_core → sequel}/database.rb +264 -149
- data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
- data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
- data/lib/sequel/database/schema_sql.rb +224 -0
- data/lib/{sequel_core → sequel}/dataset.rb +78 -236
- data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
- data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
- data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
- data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
- data/lib/sequel/deprecated.rb +593 -0
- data/lib/sequel/deprecated_migration.rb +91 -0
- data/lib/sequel/exceptions.rb +48 -0
- data/lib/sequel/extensions/blank.rb +42 -0
- data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
- data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
- data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
- data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
- data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
- data/lib/sequel/extensions/string_date_time.rb +47 -0
- data/lib/sequel/metaprogramming.rb +43 -0
- data/lib/sequel/model.rb +110 -0
- data/lib/sequel/model/associations.rb +1300 -0
- data/lib/sequel/model/base.rb +937 -0
- data/lib/sequel/model/deprecated.rb +204 -0
- data/lib/sequel/model/deprecated_hooks.rb +103 -0
- data/lib/sequel/model/deprecated_inflector.rb +335 -0
- data/lib/sequel/model/deprecated_validations.rb +388 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
- data/lib/sequel/model/inflections.rb +208 -0
- data/lib/sequel/model/plugins.rb +76 -0
- data/lib/sequel/plugins/caching.rb +122 -0
- data/lib/sequel/plugins/hook_class_methods.rb +122 -0
- data/lib/sequel/plugins/schema.rb +53 -0
- data/lib/sequel/plugins/serialization.rb +117 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
- data/lib/sequel/plugins/validation_class_methods.rb +384 -0
- data/lib/sequel/plugins/validation_helpers.rb +150 -0
- data/lib/{sequel_core → sequel}/sql.rb +125 -190
- data/lib/{sequel_core → sequel}/version.rb +2 -1
- data/lib/sequel_core.rb +1 -172
- data/lib/sequel_model.rb +1 -91
- data/spec/adapters/firebird_spec.rb +5 -5
- data/spec/adapters/informix_spec.rb +1 -1
- data/spec/adapters/mysql_spec.rb +128 -42
- data/spec/adapters/oracle_spec.rb +47 -19
- data/spec/adapters/postgres_spec.rb +64 -52
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +12 -17
- data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
- data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
- data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
- data/spec/{sequel_core → core}/database_spec.rb +135 -99
- data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
- data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
- data/spec/core/migration_spec.rb +263 -0
- data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
- data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
- data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
- data/spec/{sequel_core → core}/schema_spec.rb +8 -10
- data/spec/{sequel_core → core}/spec_helper.rb +29 -2
- data/spec/{sequel_core → core}/version_spec.rb +0 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/caching_spec.rb +201 -0
- data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
- data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
- data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
- data/spec/extensions/serialization_spec.rb +109 -0
- data/spec/extensions/single_table_inheritance_spec.rb +53 -0
- data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
- data/spec/extensions/validation_helpers_spec.rb +291 -0
- data/spec/integration/dataset_test.rb +31 -0
- data/spec/integration/eager_loader_test.rb +17 -30
- data/spec/integration/schema_test.rb +8 -5
- data/spec/integration/spec_helper.rb +17 -0
- data/spec/integration/transaction_test.rb +68 -0
- data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
- data/spec/{sequel_model → model}/associations_spec.rb +23 -10
- data/spec/{sequel_model → model}/base_spec.rb +29 -20
- data/spec/{sequel_model → model}/caching_spec.rb +16 -14
- data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
- data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
- data/spec/model/hooks_spec.rb +472 -0
- data/spec/model/inflector_spec.rb +126 -0
- data/spec/{sequel_model → model}/model_spec.rb +25 -20
- data/spec/model/plugins_spec.rb +142 -0
- data/spec/{sequel_model → model}/record_spec.rb +121 -62
- data/spec/model/schema_spec.rb +92 -0
- data/spec/model/spec_helper.rb +124 -0
- data/spec/model/validations_spec.rb +1080 -0
- metadata +136 -107
- data/lib/sequel_core/core_ext.rb +0 -217
- data/lib/sequel_core/dataset/callback.rb +0 -13
- data/lib/sequel_core/dataset/schema.rb +0 -15
- data/lib/sequel_core/deprecated.rb +0 -26
- data/lib/sequel_core/exceptions.rb +0 -44
- data/lib/sequel_core/schema.rb +0 -2
- data/lib/sequel_core/schema/sql.rb +0 -325
- data/lib/sequel_model/association_reflection.rb +0 -267
- data/lib/sequel_model/associations.rb +0 -499
- data/lib/sequel_model/base.rb +0 -539
- data/lib/sequel_model/caching.rb +0 -82
- data/lib/sequel_model/dataset_methods.rb +0 -26
- data/lib/sequel_model/eager_loading.rb +0 -370
- data/lib/sequel_model/hooks.rb +0 -101
- data/lib/sequel_model/plugins.rb +0 -62
- data/lib/sequel_model/record.rb +0 -568
- data/lib/sequel_model/schema.rb +0 -49
- data/lib/sequel_model/validations.rb +0 -429
- data/spec/sequel_model/plugins_spec.rb +0 -80
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe Sequel::Model, "table_exists?" do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
MODEL_DB.reset
|
|
7
|
+
@model = Class.new(Sequel::Model(:items))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should get the table name and question the model's db if table_exists?" do
|
|
11
|
+
@model.should_receive(:table_name).and_return(:items)
|
|
12
|
+
@model.db.should_receive(:table_exists?)
|
|
13
|
+
@model.table_exists?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe Sequel::Model, "create_table and schema" do
|
|
19
|
+
|
|
20
|
+
before(:each) do
|
|
21
|
+
MODEL_DB.reset
|
|
22
|
+
deprec do
|
|
23
|
+
@model = Class.new(Sequel::Model) do
|
|
24
|
+
set_schema(:items) do
|
|
25
|
+
text :name
|
|
26
|
+
float :price, :null => false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
deprec_specify "should get the create table SQL list from the db and execute it line by line" do
|
|
33
|
+
@model.create_table
|
|
34
|
+
MODEL_DB.sqls.should == ['CREATE TABLE items (name text, price float NOT NULL)']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
deprec_specify "should reload the schema from the database" do
|
|
38
|
+
schem = {:name=>{:type=>:string}, :price=>{:type=>:float}}
|
|
39
|
+
@model.db.should_receive(:schema).with(:items, :reload=>true).and_return(schem.to_a.sort_by{|x| x[0].to_s})
|
|
40
|
+
@model.create_table
|
|
41
|
+
@model.db_schema.should == schem
|
|
42
|
+
@model.instance_variable_get(:@columns).should == [:name, :price]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
deprec_specify "should return the schema generator via schema" do
|
|
46
|
+
@model.schema.should be_a_kind_of(Sequel::Schema::Generator)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
deprec_specify "should use the superclasses schema if it exists" do
|
|
50
|
+
@submodel = Class.new(@model)
|
|
51
|
+
@submodel.schema.should be_a_kind_of(Sequel::Schema::Generator)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
deprec_specify "should return nil if no schema is present" do
|
|
55
|
+
@model = Class.new(Sequel::Model)
|
|
56
|
+
@model.schema.should == nil
|
|
57
|
+
@submodel = Class.new(@model)
|
|
58
|
+
@submodel.schema.should == nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe Sequel::Model, "drop_table" do
|
|
63
|
+
|
|
64
|
+
before(:each) do
|
|
65
|
+
MODEL_DB.reset
|
|
66
|
+
@model = Class.new(Sequel::Model(:items))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
deprec_specify "should get the drop table SQL for the associated table and then execute the SQL." do
|
|
70
|
+
@model.should_receive(:table_name).and_return(:items)
|
|
71
|
+
@model.db.should_receive(:drop_table_sql).with(:items)
|
|
72
|
+
@model.db.should_receive(:execute).and_return(:true)
|
|
73
|
+
@model.drop_table
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe Sequel::Model, "create_table!" do
|
|
79
|
+
|
|
80
|
+
before(:each) do
|
|
81
|
+
MODEL_DB.reset
|
|
82
|
+
@model = Class.new(Sequel::Model(:items))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
deprec_specify "should drop table if it exists and then create the table" do
|
|
86
|
+
@model.should_receive(:drop_table).and_return(true)
|
|
87
|
+
@model.should_receive(:create_table).and_return(true)
|
|
88
|
+
|
|
89
|
+
@model.create_table!
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
unless Object.const_defined?('Sequel')
|
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
|
4
|
+
require 'sequel/core'
|
|
5
|
+
end
|
|
6
|
+
unless Sequel.const_defined?('Model')
|
|
7
|
+
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
|
8
|
+
require 'sequel/model'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Sequel.virtual_row_instance_eval = true
|
|
12
|
+
|
|
13
|
+
module Spec::Example::ExampleMethods
|
|
14
|
+
def deprec
|
|
15
|
+
output = Sequel::Deprecation.output = nil
|
|
16
|
+
begin
|
|
17
|
+
yield
|
|
18
|
+
ensure
|
|
19
|
+
Sequel::Deprecation.output = output
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module Spec::Example::ExampleGroupMethods
|
|
25
|
+
def deprec_specify(*args, &block)
|
|
26
|
+
specify(*args) do
|
|
27
|
+
output = Sequel::Deprecation.output
|
|
28
|
+
Sequel::Deprecation.output = nil
|
|
29
|
+
begin
|
|
30
|
+
instance_eval(&block)
|
|
31
|
+
ensure
|
|
32
|
+
Sequel::Deprecation.output = output
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class MockDataset < Sequel::Dataset
|
|
39
|
+
def insert(*args)
|
|
40
|
+
@db.execute insert_sql(*args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def update(*args)
|
|
44
|
+
@db.execute update_sql(*args)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def delete(*args)
|
|
48
|
+
@db.execute delete_sql(*args)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def fetch_rows(sql)
|
|
52
|
+
return if sql =~ /information_schema/
|
|
53
|
+
@db.execute(sql)
|
|
54
|
+
yield({:id => 1, :x => 1})
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def quoted_identifier(c)
|
|
58
|
+
"\"#{c}\""
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class MockDatabase < Sequel::Database
|
|
63
|
+
@@quote_identifiers = false
|
|
64
|
+
self.identifier_input_method = nil
|
|
65
|
+
self.identifier_output_method = nil
|
|
66
|
+
attr_reader :sqls
|
|
67
|
+
|
|
68
|
+
def execute(sql, opts={})
|
|
69
|
+
@sqls ||= []
|
|
70
|
+
@sqls << sql
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def reset
|
|
74
|
+
@sqls = []
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def schema(table_name, opts)
|
|
78
|
+
if table_name
|
|
79
|
+
[[:id, {:primary_key=>true}]]
|
|
80
|
+
else
|
|
81
|
+
{table_name=>[[:id, {:primary_key=>true}]]}
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def transaction(opts={})
|
|
86
|
+
return yield if @transactions.include?(Thread.current)
|
|
87
|
+
execute('BEGIN')
|
|
88
|
+
begin
|
|
89
|
+
@transactions << Thread.current
|
|
90
|
+
yield
|
|
91
|
+
rescue Exception => e
|
|
92
|
+
execute('ROLLBACK')
|
|
93
|
+
transaction_error(e)
|
|
94
|
+
ensure
|
|
95
|
+
unless e
|
|
96
|
+
execute('COMMIT')
|
|
97
|
+
end
|
|
98
|
+
@transactions.delete(Thread.current)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def dataset(opts=nil); MockDataset.new(self, opts); end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class << Sequel::Model
|
|
106
|
+
alias orig_columns columns
|
|
107
|
+
alias orig_str_columns str_columns
|
|
108
|
+
def columns(*cols)
|
|
109
|
+
return if cols.empty?
|
|
110
|
+
define_method(:columns){cols}
|
|
111
|
+
@dataset.instance_variable_set(:@columns, cols) if @dataset
|
|
112
|
+
define_method(:str_columns){cols.map{|x|x.to_s.freeze}}
|
|
113
|
+
def_column_accessor(*cols)
|
|
114
|
+
@columns = cols
|
|
115
|
+
@db_schema = {}
|
|
116
|
+
cols.each{|c| @db_schema[c] = {}}
|
|
117
|
+
end
|
|
118
|
+
def simple_table
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
Sequel::Model.use_transactions = false
|
|
124
|
+
Sequel::Model.db = MODEL_DB = MockDatabase.new
|
|
@@ -0,0 +1,1080 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe Sequel::Model::Errors do
|
|
4
|
+
before do
|
|
5
|
+
@errors = Sequel::Model::Errors.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
specify "should be clearable using #clear" do
|
|
9
|
+
@errors.add(:a, 'b')
|
|
10
|
+
@errors.should == {:a=>['b']}
|
|
11
|
+
@errors.clear
|
|
12
|
+
@errors.should == {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
specify "should be empty if no errors are added" do
|
|
16
|
+
@errors.should be_empty
|
|
17
|
+
@errors[:blah] << "blah"
|
|
18
|
+
@errors.should_not be_empty
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
specify "should return errors for a specific attribute using #on or #[]" do
|
|
22
|
+
@errors[:blah].should == []
|
|
23
|
+
@errors.on(:blah).should == []
|
|
24
|
+
|
|
25
|
+
@errors[:blah] << 'blah'
|
|
26
|
+
@errors[:blah].should == ['blah']
|
|
27
|
+
@errors.on(:blah).should == ['blah']
|
|
28
|
+
|
|
29
|
+
@errors[:bleu].should == []
|
|
30
|
+
@errors.on(:bleu).should == []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
specify "should accept errors using #[] << or #add" do
|
|
34
|
+
@errors[:blah] << 'blah'
|
|
35
|
+
@errors[:blah].should == ['blah']
|
|
36
|
+
|
|
37
|
+
@errors.add :blah, 'zzzz'
|
|
38
|
+
@errors[:blah].should == ['blah', 'zzzz']
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
specify "should return full messages using #full_messages" do
|
|
42
|
+
@errors.full_messages.should == []
|
|
43
|
+
|
|
44
|
+
@errors[:blow] << 'blieuh'
|
|
45
|
+
@errors[:blow] << 'blich'
|
|
46
|
+
@errors[:blay] << 'bliu'
|
|
47
|
+
msgs = @errors.full_messages
|
|
48
|
+
msgs.size.should == 3
|
|
49
|
+
msgs.should include('blow blieuh', 'blow blich', 'blay bliu')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
specify "should return the number of error messages using #count" do
|
|
53
|
+
@errors.count.should == 0
|
|
54
|
+
@errors.add(:a, 'b')
|
|
55
|
+
@errors.count.should == 1
|
|
56
|
+
@errors.add(:a, 'c')
|
|
57
|
+
@errors.count.should == 2
|
|
58
|
+
@errors.add(:b, 'c')
|
|
59
|
+
@errors.count.should == 3
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
specify "should return the array of error messages for a given attribute using #on" do
|
|
63
|
+
@errors.add(:a, 'b')
|
|
64
|
+
@errors.on(:a).should == ['b']
|
|
65
|
+
@errors.add(:a, 'c')
|
|
66
|
+
@errors.on(:a).should == ['b', 'c']
|
|
67
|
+
@errors.add(:b, 'c')
|
|
68
|
+
@errors.on(:a).should == ['b', 'c']
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
specify "should return nil if there are no error messages for a given attribute using #on" do
|
|
72
|
+
@errors.on(:a).should == nil
|
|
73
|
+
@errors.add(:b, 'b')
|
|
74
|
+
@errors.on(:a).should == nil
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe Sequel::Model do
|
|
79
|
+
before do
|
|
80
|
+
deprec do
|
|
81
|
+
@c = Class.new(Sequel::Model) do
|
|
82
|
+
def self.validates_coolness_of(attr)
|
|
83
|
+
validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
deprec_specify "should respond to validates, validations, has_validations?" do
|
|
90
|
+
@c.should respond_to(:validations)
|
|
91
|
+
@c.should respond_to(:has_validations?)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
deprec_specify "should acccept validation definitions using validates_each" do
|
|
95
|
+
@c.validates_each(:xx, :yy) {|o, a, v| o.errors[a] << 'too low' if v < 50}
|
|
96
|
+
o = @c.new
|
|
97
|
+
o.should_receive(:xx).once.and_return(40)
|
|
98
|
+
o.should_receive(:yy).once.and_return(60)
|
|
99
|
+
o.valid?.should == false
|
|
100
|
+
o.errors.full_messages.should == ['xx too low']
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
deprec_specify "should return true/false for has_validations?" do
|
|
104
|
+
@c.has_validations?.should == false
|
|
105
|
+
@c.validates_each(:xx) {1}
|
|
106
|
+
@c.has_validations?.should == true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
deprec_specify "should validate multiple attributes at once" do
|
|
110
|
+
o = @c.new
|
|
111
|
+
def o.xx
|
|
112
|
+
1
|
|
113
|
+
end
|
|
114
|
+
def o.yy
|
|
115
|
+
2
|
|
116
|
+
end
|
|
117
|
+
vals = nil
|
|
118
|
+
atts = nil
|
|
119
|
+
@c.validates_each([:xx, :yy]){|obj,a,v| atts=a; vals=v}
|
|
120
|
+
o.valid?
|
|
121
|
+
vals.should == [1,2]
|
|
122
|
+
atts.should == [:xx, :yy]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
deprec_specify "should respect allow_missing option when using multiple attributes" do
|
|
126
|
+
o = @c.new
|
|
127
|
+
def o.xx
|
|
128
|
+
self[:xx]
|
|
129
|
+
end
|
|
130
|
+
def o.yy
|
|
131
|
+
self[:yy]
|
|
132
|
+
end
|
|
133
|
+
vals = nil
|
|
134
|
+
atts = nil
|
|
135
|
+
@c.validates_each([:xx, :yy], :allow_missing=>true){|obj,a,v| atts=a; vals=v}
|
|
136
|
+
|
|
137
|
+
o.values[:xx] = 1
|
|
138
|
+
o.valid?
|
|
139
|
+
vals.should == [1,nil]
|
|
140
|
+
atts.should == [:xx, :yy]
|
|
141
|
+
|
|
142
|
+
vals = nil
|
|
143
|
+
atts = nil
|
|
144
|
+
o.values.clear
|
|
145
|
+
o.values[:yy] = 2
|
|
146
|
+
o.valid?
|
|
147
|
+
vals.should == [nil, 2]
|
|
148
|
+
atts.should == [:xx, :yy]
|
|
149
|
+
|
|
150
|
+
vals = nil
|
|
151
|
+
atts = nil
|
|
152
|
+
o.values.clear
|
|
153
|
+
o.valid?.should == true
|
|
154
|
+
vals.should == nil
|
|
155
|
+
atts.should == nil
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
deprec_specify "should overwrite existing validation with the same tag and attribute" do
|
|
159
|
+
@c.validates_each(:xx, :xx, :tag=>:low) {|o, a, v| o.xxx; o.errors[a] << 'too low' if v < 50}
|
|
160
|
+
@c.validates_each(:yy, :yy) {|o, a, v| o.yyy; o.errors[a] << 'too low' if v < 50}
|
|
161
|
+
@c.validates_presence_of(:zz, :zz)
|
|
162
|
+
@c.validates_length_of(:aa, :aa, :tag=>:blah)
|
|
163
|
+
o = @c.new
|
|
164
|
+
def o.zz
|
|
165
|
+
@a ||= 0
|
|
166
|
+
@a += 1
|
|
167
|
+
end
|
|
168
|
+
def o.aa
|
|
169
|
+
@b ||= 0
|
|
170
|
+
@b += 1
|
|
171
|
+
end
|
|
172
|
+
o.should_receive(:xx).once.and_return(40)
|
|
173
|
+
o.should_receive(:yy).once.and_return(60)
|
|
174
|
+
o.should_receive(:xxx).once
|
|
175
|
+
o.should_receive(:yyy).twice
|
|
176
|
+
o.valid?.should == false
|
|
177
|
+
o.zz.should == 2
|
|
178
|
+
o.aa.should == 2
|
|
179
|
+
o.errors.full_messages.should == ['xx too low']
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
deprec_specify "should provide a validates method that takes block with validation definitions" do
|
|
183
|
+
@c.validates do
|
|
184
|
+
coolness_of :blah
|
|
185
|
+
end
|
|
186
|
+
@c.validations[:blah].should_not be_empty
|
|
187
|
+
o = @c.new
|
|
188
|
+
o.should_receive(:blah).once.and_return(nil)
|
|
189
|
+
o.valid?.should == false
|
|
190
|
+
o.errors.full_messages.should == ['blah is not cool']
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
describe Sequel::Model do
|
|
195
|
+
before do
|
|
196
|
+
@c = Class.new(Sequel::Model) do
|
|
197
|
+
columns :score
|
|
198
|
+
def validate
|
|
199
|
+
errors[:score] << 'too low' if score < 87
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
@o = @c.new
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
specify "should supply a #valid? method that returns true if validations pass" do
|
|
207
|
+
@o.score = 50
|
|
208
|
+
@o.should_not be_valid
|
|
209
|
+
@o.score = 100
|
|
210
|
+
@o.should be_valid
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
specify "should provide an errors object" do
|
|
214
|
+
@o.score = 100
|
|
215
|
+
@o.should be_valid
|
|
216
|
+
@o.errors.should be_empty
|
|
217
|
+
|
|
218
|
+
@o.score = 86
|
|
219
|
+
@o.should_not be_valid
|
|
220
|
+
@o.errors[:score].should == ['too low']
|
|
221
|
+
@o.errors[:blah].should be_empty
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
describe 'Sequel::Model::Validation::Generator' do
|
|
226
|
+
before do
|
|
227
|
+
$testit = nil
|
|
228
|
+
|
|
229
|
+
@c = Class.new(Sequel::Model) do
|
|
230
|
+
def self.validates_blah
|
|
231
|
+
$testit = 1324
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
deprec_specify "should instance_eval the block, sending everything to its receiver" do
|
|
237
|
+
@c.class_eval do
|
|
238
|
+
validates do
|
|
239
|
+
blah
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
$testit.should == 1324
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe Sequel::Model do
|
|
247
|
+
before do
|
|
248
|
+
@c = Class.new(Sequel::Model) do
|
|
249
|
+
columns :value
|
|
250
|
+
|
|
251
|
+
def self.filter(*args)
|
|
252
|
+
o = Object.new
|
|
253
|
+
def o.count; 2; end
|
|
254
|
+
o
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def skip; false; end
|
|
258
|
+
def dont_skip; true; end
|
|
259
|
+
end
|
|
260
|
+
@m = @c.new
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
deprec_specify "should validate acceptance_of" do
|
|
264
|
+
@c.validates_acceptance_of :value
|
|
265
|
+
@m.should be_valid
|
|
266
|
+
@m.value = '1'
|
|
267
|
+
@m.should be_valid
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
deprec_specify "should validate acceptance_of with accept" do
|
|
271
|
+
@c.validates_acceptance_of :value, :accept => 'true'
|
|
272
|
+
@m.value = '1'
|
|
273
|
+
@m.should_not be_valid
|
|
274
|
+
@m.value = 'true'
|
|
275
|
+
@m.should be_valid
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
deprec_specify "should validate acceptance_of with allow_nil => false" do
|
|
279
|
+
@c.validates_acceptance_of :value, :allow_nil => false
|
|
280
|
+
@m.should_not be_valid
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
deprec_specify "should validate acceptance_of with allow_missing => true" do
|
|
284
|
+
@c.validates_acceptance_of :value, :allow_missing => true
|
|
285
|
+
@m.should be_valid
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
deprec_specify "should validate acceptance_of with allow_missing => true and allow_nil => false" do
|
|
289
|
+
@c.validates_acceptance_of :value, :allow_missing => true, :allow_nil => false
|
|
290
|
+
@m.should be_valid
|
|
291
|
+
@m.value = nil
|
|
292
|
+
@m.should_not be_valid
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
deprec_specify "should validate acceptance_of with if => true" do
|
|
296
|
+
@c.validates_acceptance_of :value, :if => :dont_skip
|
|
297
|
+
@m.value = '0'
|
|
298
|
+
@m.should_not be_valid
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
deprec_specify "should validate acceptance_of with if => false" do
|
|
302
|
+
@c.validates_acceptance_of :value, :if => :skip
|
|
303
|
+
@m.value = '0'
|
|
304
|
+
@m.should be_valid
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
deprec_specify "should validate acceptance_of with if proc that evaluates to true" do
|
|
308
|
+
@c.validates_acceptance_of :value, :if => proc{true}
|
|
309
|
+
@m.value = '0'
|
|
310
|
+
@m.should_not be_valid
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
deprec_specify "should validate acceptance_of with if proc that evaluates to false" do
|
|
314
|
+
@c.validates_acceptance_of :value, :if => proc{false}
|
|
315
|
+
@m.value = '0'
|
|
316
|
+
@m.should be_valid
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
deprec_specify "should raise an error if :if option is not a Symbol, Proc, or nil" do
|
|
320
|
+
@c.validates_acceptance_of :value, :if => 1
|
|
321
|
+
@m.value = '0'
|
|
322
|
+
proc{@m.valid?}.should raise_error(Sequel::Error)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
deprec_specify "should validate confirmation_of" do
|
|
326
|
+
@c.send(:attr_accessor, :value_confirmation)
|
|
327
|
+
@c.validates_confirmation_of :value
|
|
328
|
+
|
|
329
|
+
@m.value = 'blah'
|
|
330
|
+
@m.should_not be_valid
|
|
331
|
+
|
|
332
|
+
@m.value_confirmation = 'blah'
|
|
333
|
+
@m.should be_valid
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
deprec_specify "should validate confirmation_of with if => true" do
|
|
337
|
+
@c.send(:attr_accessor, :value_confirmation)
|
|
338
|
+
@c.validates_confirmation_of :value, :if => :dont_skip
|
|
339
|
+
|
|
340
|
+
@m.value = 'blah'
|
|
341
|
+
@m.should_not be_valid
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
deprec_specify "should validate confirmation_of with if => false" do
|
|
345
|
+
@c.send(:attr_accessor, :value_confirmation)
|
|
346
|
+
@c.validates_confirmation_of :value, :if => :skip
|
|
347
|
+
|
|
348
|
+
@m.value = 'blah'
|
|
349
|
+
@m.should be_valid
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
deprec_specify "should validate confirmation_of with allow_missing => true" do
|
|
353
|
+
@c.send(:attr_accessor, :value_confirmation)
|
|
354
|
+
@c.validates_acceptance_of :value, :allow_missing => true
|
|
355
|
+
@m.should be_valid
|
|
356
|
+
@m.value_confirmation = 'blah'
|
|
357
|
+
@m.should be_valid
|
|
358
|
+
@m.value = nil
|
|
359
|
+
@m.should_not be_valid
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
deprec_specify "should validate format_of" do
|
|
363
|
+
@c.validates_format_of :value, :with => /.+_.+/
|
|
364
|
+
@m.value = 'abc_'
|
|
365
|
+
@m.should_not be_valid
|
|
366
|
+
@m.value = 'abc_def'
|
|
367
|
+
@m.should be_valid
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
deprec_specify "should raise for validate_format_of without regexp" do
|
|
371
|
+
proc {@c.validates_format_of :value}.should raise_error(ArgumentError)
|
|
372
|
+
proc {@c.validates_format_of :value, :with => :blah}.should raise_error(ArgumentError)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
deprec_specify "should validate format_of with if => true" do
|
|
376
|
+
@c.validates_format_of :value, :with => /_/, :if => :dont_skip
|
|
377
|
+
|
|
378
|
+
@m.value = 'a'
|
|
379
|
+
@m.should_not be_valid
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
deprec_specify "should validate format_of with if => false" do
|
|
383
|
+
@c.validates_format_of :value, :with => /_/, :if => :skip
|
|
384
|
+
|
|
385
|
+
@m.value = 'a'
|
|
386
|
+
@m.should be_valid
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
deprec_specify "should validate format_of with allow_missing => true" do
|
|
390
|
+
@c.validates_format_of :value, :allow_missing => true, :with=>/./
|
|
391
|
+
@m.should be_valid
|
|
392
|
+
@m.value = nil
|
|
393
|
+
@m.should_not be_valid
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
deprec_specify "should validate length_of with maximum" do
|
|
397
|
+
@c.validates_length_of :value, :maximum => 5
|
|
398
|
+
@m.should_not be_valid
|
|
399
|
+
@m.value = '12345'
|
|
400
|
+
@m.should be_valid
|
|
401
|
+
@m.value = '123456'
|
|
402
|
+
@m.should_not be_valid
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
deprec_specify "should validate length_of with minimum" do
|
|
406
|
+
@c.validates_length_of :value, :minimum => 5
|
|
407
|
+
@m.should_not be_valid
|
|
408
|
+
@m.value = '12345'
|
|
409
|
+
@m.should be_valid
|
|
410
|
+
@m.value = '1234'
|
|
411
|
+
@m.should_not be_valid
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
deprec_specify "should validate length_of with within" do
|
|
415
|
+
@c.validates_length_of :value, :within => 2..5
|
|
416
|
+
@m.should_not be_valid
|
|
417
|
+
@m.value = '12345'
|
|
418
|
+
@m.should be_valid
|
|
419
|
+
@m.value = '1'
|
|
420
|
+
@m.should_not be_valid
|
|
421
|
+
@m.value = '123456'
|
|
422
|
+
@m.should_not be_valid
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
deprec_specify "should validate length_of with is" do
|
|
426
|
+
@c.validates_length_of :value, :is => 3
|
|
427
|
+
@m.should_not be_valid
|
|
428
|
+
@m.value = '123'
|
|
429
|
+
@m.should be_valid
|
|
430
|
+
@m.value = '12'
|
|
431
|
+
@m.should_not be_valid
|
|
432
|
+
@m.value = '1234'
|
|
433
|
+
@m.should_not be_valid
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
deprec_specify "should validate length_of with allow_nil" do
|
|
437
|
+
@c.validates_length_of :value, :is => 3, :allow_nil => true
|
|
438
|
+
@m.should be_valid
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
deprec_specify "should validate length_of with if => true" do
|
|
442
|
+
@c.validates_length_of :value, :is => 3, :if => :dont_skip
|
|
443
|
+
|
|
444
|
+
@m.value = 'a'
|
|
445
|
+
@m.should_not be_valid
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
deprec_specify "should validate length_of with if => false" do
|
|
449
|
+
@c.validates_length_of :value, :is => 3, :if => :skip
|
|
450
|
+
|
|
451
|
+
@m.value = 'a'
|
|
452
|
+
@m.should be_valid
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
deprec_specify "should validate length_of with allow_missing => true" do
|
|
456
|
+
@c.validates_length_of :value, :allow_missing => true, :minimum => 5
|
|
457
|
+
@m.should be_valid
|
|
458
|
+
@m.value = nil
|
|
459
|
+
@m.should_not be_valid
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
deprec_specify "should allow multiple calls to validates_length_of with different options without overwriting" do
|
|
463
|
+
@c.validates_length_of :value, :maximum => 5
|
|
464
|
+
@c.validates_length_of :value, :minimum => 5
|
|
465
|
+
@m.should_not be_valid
|
|
466
|
+
@m.value = '12345'
|
|
467
|
+
@m.should be_valid
|
|
468
|
+
@m.value = '123456'
|
|
469
|
+
@m.should_not be_valid
|
|
470
|
+
@m.value = '12345'
|
|
471
|
+
@m.should be_valid
|
|
472
|
+
@m.value = '1234'
|
|
473
|
+
@m.should_not be_valid
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
deprec_specify "should validate numericality_of" do
|
|
477
|
+
@c.validates_numericality_of :value
|
|
478
|
+
@m.value = 'blah'
|
|
479
|
+
@m.should_not be_valid
|
|
480
|
+
@m.value = '123'
|
|
481
|
+
@m.should be_valid
|
|
482
|
+
@m.value = '123.1231'
|
|
483
|
+
@m.should be_valid
|
|
484
|
+
@m.value = '+1'
|
|
485
|
+
@m.should be_valid
|
|
486
|
+
@m.value = '-1'
|
|
487
|
+
@m.should be_valid
|
|
488
|
+
@m.value = '+1.123'
|
|
489
|
+
@m.should be_valid
|
|
490
|
+
@m.value = '-0.123'
|
|
491
|
+
@m.should be_valid
|
|
492
|
+
@m.value = '-0.123E10'
|
|
493
|
+
@m.should be_valid
|
|
494
|
+
@m.value = '32.123e10'
|
|
495
|
+
@m.should be_valid
|
|
496
|
+
@m.value = '+32.123E10'
|
|
497
|
+
@m.should be_valid
|
|
498
|
+
@m.should be_valid
|
|
499
|
+
@m.value = '.0123'
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
deprec_specify "should validate numericality_of with only_integer" do
|
|
503
|
+
@c.validates_numericality_of :value, :only_integer => true
|
|
504
|
+
@m.value = 'blah'
|
|
505
|
+
@m.should_not be_valid
|
|
506
|
+
@m.value = '123'
|
|
507
|
+
@m.should be_valid
|
|
508
|
+
@m.value = '123.1231'
|
|
509
|
+
@m.should_not be_valid
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
deprec_specify "should validate numericality_of with if => true" do
|
|
513
|
+
@c.validates_numericality_of :value, :if => :dont_skip
|
|
514
|
+
|
|
515
|
+
@m.value = 'a'
|
|
516
|
+
@m.should_not be_valid
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
deprec_specify "should validate numericality_of with if => false" do
|
|
520
|
+
@c.validates_numericality_of :value, :if => :skip
|
|
521
|
+
|
|
522
|
+
@m.value = 'a'
|
|
523
|
+
@m.should be_valid
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
deprec_specify "should validate numericality_of with allow_missing => true" do
|
|
527
|
+
@c.validates_numericality_of :value, :allow_missing => true
|
|
528
|
+
@m.should be_valid
|
|
529
|
+
@m.value = nil
|
|
530
|
+
@m.should_not be_valid
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
deprec_specify "should validate presence_of" do
|
|
534
|
+
@c.validates_presence_of :value
|
|
535
|
+
@m.should_not be_valid
|
|
536
|
+
@m.value = ''
|
|
537
|
+
@m.should_not be_valid
|
|
538
|
+
@m.value = 1234
|
|
539
|
+
@m.should be_valid
|
|
540
|
+
@m.value = nil
|
|
541
|
+
@m.should_not be_valid
|
|
542
|
+
@m.value = true
|
|
543
|
+
@m.should be_valid
|
|
544
|
+
@m.value = false
|
|
545
|
+
@m.should be_valid
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
deprec_specify "should validate inclusion_of with an array" do
|
|
549
|
+
@c.validates_inclusion_of :value, :in => [1,2]
|
|
550
|
+
@m.should_not be_valid
|
|
551
|
+
@m.value = 1
|
|
552
|
+
@m.should be_valid
|
|
553
|
+
@m.value = 1.5
|
|
554
|
+
@m.should_not be_valid
|
|
555
|
+
@m.value = 2
|
|
556
|
+
@m.should be_valid
|
|
557
|
+
@m.value = 3
|
|
558
|
+
@m.should_not be_valid
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
deprec_specify "should validate inclusion_of with a range" do
|
|
562
|
+
@c.validates_inclusion_of :value, :in => 1..4
|
|
563
|
+
@m.should_not be_valid
|
|
564
|
+
@m.value = 1
|
|
565
|
+
@m.should be_valid
|
|
566
|
+
@m.value = 1.5
|
|
567
|
+
@m.should be_valid
|
|
568
|
+
@m.value = 0
|
|
569
|
+
@m.should_not be_valid
|
|
570
|
+
@m.value = 5
|
|
571
|
+
@m.should_not be_valid
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
deprec_specify "should raise an error if inclusion_of doesn't receive a valid :in option" do
|
|
575
|
+
lambda {
|
|
576
|
+
@c.validates_inclusion_of :value
|
|
577
|
+
}.should raise_error(ArgumentError)
|
|
578
|
+
|
|
579
|
+
lambda {
|
|
580
|
+
@c.validates_inclusion_of :value, :in => 1
|
|
581
|
+
}.should raise_error(ArgumentError)
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
deprec_specify "should raise an error if inclusion_of handles :allow_nil too" do
|
|
585
|
+
@c.validates_inclusion_of :value, :in => 1..4, :allow_nil => true
|
|
586
|
+
@m.value = nil
|
|
587
|
+
@m.should be_valid
|
|
588
|
+
@m.value = 0
|
|
589
|
+
@m.should_not be_valid
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
deprec_specify "should validate presence_of with if => true" do
|
|
593
|
+
@c.validates_presence_of :value, :if => :dont_skip
|
|
594
|
+
@m.should_not be_valid
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
deprec_specify "should validate presence_of with if => false" do
|
|
598
|
+
@c.validates_presence_of :value, :if => :skip
|
|
599
|
+
@m.should be_valid
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
deprec_specify "should validate presence_of with allow_missing => true" do
|
|
603
|
+
@c.validates_presence_of :value, :allow_missing => true
|
|
604
|
+
@m.should be_valid
|
|
605
|
+
@m.value = nil
|
|
606
|
+
@m.should_not be_valid
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
deprec_specify "should validate uniqueness_of with if => true" do
|
|
610
|
+
@c.validates_uniqueness_of :value, :if => :dont_skip
|
|
611
|
+
|
|
612
|
+
@m.value = 'a'
|
|
613
|
+
@m.should_not be_valid
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
deprec_specify "should validate uniqueness_of with if => false" do
|
|
617
|
+
@c.validates_uniqueness_of :value, :if => :skip
|
|
618
|
+
|
|
619
|
+
@m.value = 'a'
|
|
620
|
+
@m.should be_valid
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
deprec_specify "should validate uniqueness_of with allow_missing => true" do
|
|
624
|
+
@c.validates_uniqueness_of :value, :allow_missing => true
|
|
625
|
+
@m.should be_valid
|
|
626
|
+
@m.value = nil
|
|
627
|
+
@m.should_not be_valid
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
context "Superclass validations" do
|
|
632
|
+
before do
|
|
633
|
+
deprec do
|
|
634
|
+
@c1 = Class.new(Sequel::Model) do
|
|
635
|
+
columns :value
|
|
636
|
+
validates_length_of :value, :minimum => 5
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
@c2 = Class.new(@c1) do
|
|
640
|
+
columns :value
|
|
641
|
+
validates_format_of :value, :with => /^[a-z]+$/
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
deprec_specify "should be checked when validating" do
|
|
647
|
+
o = @c2.new
|
|
648
|
+
o.value = 'ab'
|
|
649
|
+
o.valid?.should == false
|
|
650
|
+
o.errors.full_messages.should == [
|
|
651
|
+
'value is too short'
|
|
652
|
+
]
|
|
653
|
+
|
|
654
|
+
o.value = '12'
|
|
655
|
+
o.valid?.should == false
|
|
656
|
+
o.errors.full_messages.should == [
|
|
657
|
+
'value is too short',
|
|
658
|
+
'value is invalid'
|
|
659
|
+
]
|
|
660
|
+
|
|
661
|
+
o.value = 'abcde'
|
|
662
|
+
o.valid?.should be_true
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
deprec_specify "should be skipped if skip_superclass_validations is called" do
|
|
666
|
+
@c2.skip_superclass_validations
|
|
667
|
+
|
|
668
|
+
o = @c2.new
|
|
669
|
+
o.value = 'ab'
|
|
670
|
+
o.valid?.should be_true
|
|
671
|
+
|
|
672
|
+
o.value = '12'
|
|
673
|
+
o.valid?.should == false
|
|
674
|
+
o.errors.full_messages.should == [
|
|
675
|
+
'value is invalid'
|
|
676
|
+
]
|
|
677
|
+
|
|
678
|
+
o.value = 'abcde'
|
|
679
|
+
o.valid?.should be_true
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
context ".validates with block" do
|
|
684
|
+
deprec_specify "should support calling .each" do
|
|
685
|
+
@c = Class.new(Sequel::Model) do
|
|
686
|
+
columns :vvv
|
|
687
|
+
validates do
|
|
688
|
+
each :vvv do |o, a, v|
|
|
689
|
+
o.errors[a] << "is less than zero" if v.to_i < 0
|
|
690
|
+
end
|
|
691
|
+
end
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
o = @c.new
|
|
695
|
+
o.vvv = 1
|
|
696
|
+
o.should be_valid
|
|
697
|
+
o.vvv = -1
|
|
698
|
+
o.should_not be_valid
|
|
699
|
+
end
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
describe Sequel::Model, "Validations" do
|
|
703
|
+
|
|
704
|
+
before(:all) do
|
|
705
|
+
class ::Person < Sequel::Model
|
|
706
|
+
columns :id,:name,:first_name,:last_name,:middle_name,:initials,:age, :terms
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
class ::Smurf < Person
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
class ::Cow < Sequel::Model
|
|
713
|
+
columns :id, :name, :got_milk
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
class ::User < Sequel::Model
|
|
717
|
+
columns :id, :username, :password
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
class ::Address < Sequel::Model
|
|
721
|
+
columns :id, :zip_code
|
|
722
|
+
end
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
deprec_specify "should validate the acceptance of a column" do
|
|
726
|
+
class ::Cow < Sequel::Model
|
|
727
|
+
validations.clear
|
|
728
|
+
validates_acceptance_of :got_milk, :accept => 'blah', :allow_nil => false
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
@cow = Cow.new
|
|
732
|
+
@cow.should_not be_valid
|
|
733
|
+
@cow.errors.full_messages.should == ["got_milk is not accepted"]
|
|
734
|
+
|
|
735
|
+
@cow.got_milk = "blah"
|
|
736
|
+
@cow.should be_valid
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
deprec_specify "should validate the confirmation of a column" do
|
|
740
|
+
class ::User < Sequel::Model
|
|
741
|
+
def password_confirmation
|
|
742
|
+
"test"
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
validations.clear
|
|
746
|
+
validates_confirmation_of :password
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
@user = User.new
|
|
750
|
+
@user.should_not be_valid
|
|
751
|
+
@user.errors.full_messages.should == ["password is not confirmed"]
|
|
752
|
+
|
|
753
|
+
@user.password = "test"
|
|
754
|
+
@user.should be_valid
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
deprec_specify "should validate format of column" do
|
|
758
|
+
class ::Person < Sequel::Model
|
|
759
|
+
validates_format_of :first_name, :with => /^[a-zA-Z]+$/
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
@person = Person.new :first_name => "Lancelot99"
|
|
763
|
+
@person.valid?.should be_false
|
|
764
|
+
@person = Person.new :first_name => "Anita"
|
|
765
|
+
@person.valid?.should be_true
|
|
766
|
+
end
|
|
767
|
+
|
|
768
|
+
deprec_specify "should validate length of column" do
|
|
769
|
+
class ::Person < Sequel::Model
|
|
770
|
+
validations.clear
|
|
771
|
+
validates_length_of :first_name, :maximum => 30
|
|
772
|
+
validates_length_of :last_name, :minimum => 30
|
|
773
|
+
validates_length_of :middle_name, :within => 1..5
|
|
774
|
+
validates_length_of :initials, :is => 2
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
@person = Person.new(
|
|
778
|
+
:first_name => "Anamethatiswaytofreakinglongandwayoverthirtycharacters",
|
|
779
|
+
:last_name => "Alastnameunderthirtychars",
|
|
780
|
+
:initials => "LGC",
|
|
781
|
+
:middle_name => "danger"
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
@person.should_not be_valid
|
|
785
|
+
@person.errors.full_messages.size.should == 4
|
|
786
|
+
@person.errors.full_messages.should include(
|
|
787
|
+
'first_name is too long',
|
|
788
|
+
'last_name is too short',
|
|
789
|
+
'middle_name is the wrong length',
|
|
790
|
+
'initials is the wrong length'
|
|
791
|
+
)
|
|
792
|
+
|
|
793
|
+
@person.first_name = "Lancelot"
|
|
794
|
+
@person.last_name = "1234567890123456789012345678901"
|
|
795
|
+
@person.initials = "LC"
|
|
796
|
+
@person.middle_name = "Will"
|
|
797
|
+
@person.should be_valid
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
deprec_specify "should validate that a column doesn't have a string value" do
|
|
801
|
+
p = Class.new(Sequel::Model)
|
|
802
|
+
p.class_eval do
|
|
803
|
+
columns :age, :price, :confirmed
|
|
804
|
+
self.raise_on_typecast_failure = false
|
|
805
|
+
validates_not_string :age
|
|
806
|
+
validates_not_string :confirmed
|
|
807
|
+
validates_not_string :price, :message=>'is not valid'
|
|
808
|
+
@db_schema = {:age=>{:type=>:integer}}
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
@person = p.new
|
|
812
|
+
@person.should be_valid
|
|
813
|
+
|
|
814
|
+
@person.confirmed = 't'
|
|
815
|
+
@person.should_not be_valid
|
|
816
|
+
@person.errors.full_messages.should == ['confirmed is a string']
|
|
817
|
+
@person.confirmed = true
|
|
818
|
+
@person.should be_valid
|
|
819
|
+
|
|
820
|
+
@person.age = 'a'
|
|
821
|
+
@person.should_not be_valid
|
|
822
|
+
@person.errors.full_messages.should == ['age is not a valid integer']
|
|
823
|
+
@person.db_schema[:age][:type] = :datetime
|
|
824
|
+
@person.should_not be_valid
|
|
825
|
+
@person.errors.full_messages.should == ['age is not a valid datetime']
|
|
826
|
+
@person.age = 20
|
|
827
|
+
@person.should be_valid
|
|
828
|
+
|
|
829
|
+
@person.price = 'a'
|
|
830
|
+
@person.should_not be_valid
|
|
831
|
+
@person.errors.full_messages.should == ['price is not valid']
|
|
832
|
+
@person.price = 20
|
|
833
|
+
@person.should be_valid
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
deprec_specify "should validate numericality of column" do
|
|
837
|
+
class ::Person < Sequel::Model
|
|
838
|
+
validations.clear
|
|
839
|
+
validates_numericality_of :age
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
@person = Person.new :age => "Twenty"
|
|
843
|
+
@person.should_not be_valid
|
|
844
|
+
@person.errors.full_messages.should == ['age is not a number']
|
|
845
|
+
|
|
846
|
+
@person.age = 20
|
|
847
|
+
@person.should be_valid
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
deprec_specify "should validate the presence of a column" do
|
|
851
|
+
class ::Cow < Sequel::Model
|
|
852
|
+
validations.clear
|
|
853
|
+
validates_presence_of :name
|
|
854
|
+
end
|
|
855
|
+
|
|
856
|
+
@cow = Cow.new
|
|
857
|
+
@cow.should_not be_valid
|
|
858
|
+
@cow.errors.full_messages.should == ['name is not present']
|
|
859
|
+
|
|
860
|
+
@cow.name = "Betsy"
|
|
861
|
+
@cow.should be_valid
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
deprec_specify "should validate the uniqueness of a column" do
|
|
865
|
+
class ::User < Sequel::Model
|
|
866
|
+
validations.clear
|
|
867
|
+
validates do
|
|
868
|
+
uniqueness_of :username
|
|
869
|
+
end
|
|
870
|
+
end
|
|
871
|
+
User.dataset.extend(Module.new {
|
|
872
|
+
def fetch_rows(sql)
|
|
873
|
+
@db << sql
|
|
874
|
+
|
|
875
|
+
case sql
|
|
876
|
+
when /COUNT.*username = '0records'/
|
|
877
|
+
yield({:v => 0})
|
|
878
|
+
when /COUNT.*username = '2records'/
|
|
879
|
+
yield({:v => 2})
|
|
880
|
+
when /COUNT.*username = '1record'/
|
|
881
|
+
yield({:v => 1})
|
|
882
|
+
when /username = '1record'/
|
|
883
|
+
yield({:id => 3, :username => "1record", :password => "test"})
|
|
884
|
+
end
|
|
885
|
+
end
|
|
886
|
+
})
|
|
887
|
+
|
|
888
|
+
@user = User.new(:username => "2records", :password => "anothertest")
|
|
889
|
+
@user.should_not be_valid
|
|
890
|
+
@user.errors.full_messages.should == ['username is already taken']
|
|
891
|
+
|
|
892
|
+
@user = User.new(:username => "1record", :password => "anothertest")
|
|
893
|
+
@user.should_not be_valid
|
|
894
|
+
@user.errors.full_messages.should == ['username is already taken']
|
|
895
|
+
|
|
896
|
+
@user = User.load(:id=>4, :username => "1record", :password => "anothertest")
|
|
897
|
+
@user.should_not be_valid
|
|
898
|
+
@user.errors.full_messages.should == ['username is already taken']
|
|
899
|
+
|
|
900
|
+
@user = User.load(:id=>3, :username => "1record", :password => "anothertest")
|
|
901
|
+
@user.should be_valid
|
|
902
|
+
@user.errors.full_messages.should == []
|
|
903
|
+
|
|
904
|
+
@user = User.new(:username => "0records", :password => "anothertest")
|
|
905
|
+
@user.should be_valid
|
|
906
|
+
@user.errors.full_messages.should == []
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
deprec_specify "should validate the uniqueness of multiple columns" do
|
|
910
|
+
class ::User < Sequel::Model
|
|
911
|
+
validations.clear
|
|
912
|
+
validates do
|
|
913
|
+
uniqueness_of [:username, :password]
|
|
914
|
+
end
|
|
915
|
+
end
|
|
916
|
+
User.dataset.extend(Module.new {
|
|
917
|
+
def fetch_rows(sql)
|
|
918
|
+
@db << sql
|
|
919
|
+
|
|
920
|
+
case sql
|
|
921
|
+
when /COUNT.*username = '0records'/
|
|
922
|
+
yield({:v => 0})
|
|
923
|
+
when /COUNT.*username = '2records'/
|
|
924
|
+
yield({:v => 2})
|
|
925
|
+
when /COUNT.*username = '1record'/
|
|
926
|
+
yield({:v => 1})
|
|
927
|
+
when /username = '1record'/
|
|
928
|
+
if sql =~ /password = 'anothertest'/
|
|
929
|
+
yield({:id => 3, :username => "1record", :password => "anothertest"})
|
|
930
|
+
else
|
|
931
|
+
yield({:id => 4, :username => "1record", :password => "test"})
|
|
932
|
+
end
|
|
933
|
+
end
|
|
934
|
+
end
|
|
935
|
+
})
|
|
936
|
+
|
|
937
|
+
@user = User.new(:username => "2records", :password => "anothertest")
|
|
938
|
+
@user.should_not be_valid
|
|
939
|
+
@user.errors.full_messages.should == ['username and password is already taken']
|
|
940
|
+
|
|
941
|
+
@user = User.new(:username => "1record", :password => "anothertest")
|
|
942
|
+
@user.should_not be_valid
|
|
943
|
+
@user.errors.full_messages.should == ['username and password is already taken']
|
|
944
|
+
|
|
945
|
+
@user = User.load(:id=>4, :username => "1record", :password => "anothertest")
|
|
946
|
+
@user.should_not be_valid
|
|
947
|
+
@user.errors.full_messages.should == ['username and password is already taken']
|
|
948
|
+
|
|
949
|
+
@user = User.load(:id=>3, :username => "1record", :password => "test")
|
|
950
|
+
@user.should_not be_valid
|
|
951
|
+
@user.errors.full_messages.should == ['username and password is already taken']
|
|
952
|
+
|
|
953
|
+
@user = User.load(:id=>3, :username => "1record", :password => "anothertest")
|
|
954
|
+
@user.should be_valid
|
|
955
|
+
@user.errors.full_messages.should == []
|
|
956
|
+
|
|
957
|
+
@user = User.new(:username => "0records", :password => "anothertest")
|
|
958
|
+
@user.should be_valid
|
|
959
|
+
@user.errors.full_messages.should == []
|
|
960
|
+
end
|
|
961
|
+
|
|
962
|
+
deprec_specify "should have a validates block that contains multiple validations" do
|
|
963
|
+
class ::Person < Sequel::Model
|
|
964
|
+
validations.clear
|
|
965
|
+
validates do
|
|
966
|
+
format_of :first_name, :with => /^[a-zA-Z]+$/
|
|
967
|
+
length_of :first_name, :maximum => 30
|
|
968
|
+
end
|
|
969
|
+
end
|
|
970
|
+
|
|
971
|
+
Person.validations[:first_name].size.should == 2
|
|
972
|
+
|
|
973
|
+
@person = Person.new :first_name => "Lancelot99"
|
|
974
|
+
@person.valid?.should be_false
|
|
975
|
+
|
|
976
|
+
@person2 = Person.new :first_name => "Wayne"
|
|
977
|
+
@person2.valid?.should be_true
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
deprec_specify "should allow 'longhand' validations direcly within the model." do
|
|
981
|
+
lambda {
|
|
982
|
+
class ::Person < Sequel::Model
|
|
983
|
+
validations.clear
|
|
984
|
+
validates_length_of :first_name, :maximum => 30
|
|
985
|
+
end
|
|
986
|
+
}.should_not raise_error
|
|
987
|
+
Person.validations.length.should eql(1)
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
deprec_specify "should define a has_validations? method which returns true if the model has validations, false otherwise" do
|
|
991
|
+
class ::Person < Sequel::Model
|
|
992
|
+
validations.clear
|
|
993
|
+
validates do
|
|
994
|
+
format_of :first_name, :with => /\w+/
|
|
995
|
+
length_of :first_name, :maximum => 30
|
|
996
|
+
end
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
class ::Smurf < Person
|
|
1000
|
+
validations.clear
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
Person.should have_validations
|
|
1004
|
+
Smurf.should_not have_validations
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
deprec_specify "should validate correctly instances initialized with string keys" do
|
|
1008
|
+
class ::Can < Sequel::Model
|
|
1009
|
+
columns :id, :name
|
|
1010
|
+
|
|
1011
|
+
validates_length_of :name, :minimum => 4
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
Can.new('name' => 'ab').should_not be_valid
|
|
1015
|
+
Can.new('name' => 'abcd').should be_valid
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
end
|
|
1019
|
+
|
|
1020
|
+
describe "Model#save!" do
|
|
1021
|
+
before do
|
|
1022
|
+
@c = Class.new(Sequel::Model(:people)) do
|
|
1023
|
+
def columns; [:id]; end
|
|
1024
|
+
|
|
1025
|
+
validates_each :id do |o, a, v|
|
|
1026
|
+
o.errors[a] << 'blah' unless v == 5
|
|
1027
|
+
end
|
|
1028
|
+
end
|
|
1029
|
+
@m = @c.load(:id => 4)
|
|
1030
|
+
MODEL_DB.reset
|
|
1031
|
+
end
|
|
1032
|
+
|
|
1033
|
+
deprec_specify "should save regardless of validations" do
|
|
1034
|
+
@m.should_not be_valid
|
|
1035
|
+
@m.save!
|
|
1036
|
+
MODEL_DB.sqls.should == ['UPDATE people SET id = 4 WHERE (id = 4)']
|
|
1037
|
+
end
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
describe "Model#save" do
|
|
1041
|
+
before do
|
|
1042
|
+
@c = Class.new(Sequel::Model(:people)) do
|
|
1043
|
+
columns :id
|
|
1044
|
+
|
|
1045
|
+
def validate
|
|
1046
|
+
errors[:id] << 'blah' unless id == 5
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
@m = @c.load(:id => 4)
|
|
1050
|
+
MODEL_DB.reset
|
|
1051
|
+
end
|
|
1052
|
+
|
|
1053
|
+
specify "should save only if validations pass" do
|
|
1054
|
+
@m.raise_on_save_failure = false
|
|
1055
|
+
@m.should_not be_valid
|
|
1056
|
+
@m.save
|
|
1057
|
+
MODEL_DB.sqls.should be_empty
|
|
1058
|
+
|
|
1059
|
+
@m.id = 5
|
|
1060
|
+
@m.should be_valid
|
|
1061
|
+
@m.save.should_not be_false
|
|
1062
|
+
MODEL_DB.sqls.should == ['UPDATE people SET id = 5 WHERE (id = 5)']
|
|
1063
|
+
end
|
|
1064
|
+
|
|
1065
|
+
specify "should skip validations if the :validate=>false option is used" do
|
|
1066
|
+
@m.raise_on_save_failure = false
|
|
1067
|
+
@m.should_not be_valid
|
|
1068
|
+
@m.save(:validate=>false)
|
|
1069
|
+
MODEL_DB.sqls.should == ['UPDATE people SET id = 4 WHERE (id = 4)']
|
|
1070
|
+
end
|
|
1071
|
+
|
|
1072
|
+
specify "should raise error if validations fail and raise_on_save_faiure is true" do
|
|
1073
|
+
proc{@m.save}.should raise_error(Sequel::ValidationFailed)
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
specify "should return nil if validations fail and raise_on_save_faiure is false" do
|
|
1077
|
+
@m.raise_on_save_failure = false
|
|
1078
|
+
@m.save.should == nil
|
|
1079
|
+
end
|
|
1080
|
+
end
|