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
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
unless Object.const_defined?('Sequel')
|
|
3
3
|
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
|
4
|
-
require '
|
|
4
|
+
require 'sequel/core'
|
|
5
5
|
end
|
|
6
6
|
unless Sequel.const_defined?('Model')
|
|
7
7
|
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
|
8
|
-
require '
|
|
8
|
+
require 'sequel/model'
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
Sequel.virtual_row_instance_eval = true
|
|
12
|
+
|
|
13
|
+
extensions = %w'string_date_time inflector pagination query pretty_table blank migration'
|
|
14
|
+
plugins = {:hook_class_methods=>[], :schema=>[], :validation_class_methods=>[]}
|
|
15
|
+
|
|
16
|
+
extensions.each{|e| require "sequel/extensions/#{e}"}
|
|
17
|
+
plugins.each{|p, opts| Sequel::Model.plugin(p, *opts)}
|
|
18
|
+
|
|
11
19
|
class MockDataset < Sequel::Dataset
|
|
12
20
|
def insert(*args)
|
|
13
21
|
@db.execute insert_sql(*args)
|
|
@@ -55,9 +63,9 @@ class MockDatabase < Sequel::Database
|
|
|
55
63
|
end
|
|
56
64
|
end
|
|
57
65
|
|
|
58
|
-
def transaction; yield; end
|
|
66
|
+
def transaction(opts={}); yield; end
|
|
59
67
|
|
|
60
|
-
def dataset; MockDataset.new(self); end
|
|
68
|
+
def dataset(opts=nil); MockDataset.new(self, opts); end
|
|
61
69
|
end
|
|
62
70
|
|
|
63
71
|
class << Sequel::Model
|
|
@@ -79,3 +87,4 @@ class << Sequel::Model
|
|
|
79
87
|
end
|
|
80
88
|
|
|
81
89
|
Sequel::Model.db = MODEL_DB = MockDatabase.new
|
|
90
|
+
Sequel::Model.use_transactions = false
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
2
|
+
|
|
3
|
+
context "String#to_time" do
|
|
4
|
+
specify "should convert the string into a Time object" do
|
|
5
|
+
"2007-07-11".to_time.should == Time.parse("2007-07-11")
|
|
6
|
+
"06:30".to_time.should == Time.parse("06:30")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
specify "should raise InvalidValue for an invalid time" do
|
|
10
|
+
proc {'0000-00-00'.to_time}.should raise_error(Sequel::InvalidValue)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "String#to_date" do
|
|
15
|
+
after do
|
|
16
|
+
Sequel.convert_two_digit_years = true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
specify "should convert the string into a Date object" do
|
|
20
|
+
"2007-07-11".to_date.should == Date.parse("2007-07-11")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
specify "should convert 2 digit years by default" do
|
|
24
|
+
"July 11, 07".to_date.should == Date.parse("2007-07-11")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
specify "should not convert 2 digit years if set not to" do
|
|
28
|
+
Sequel.convert_two_digit_years = false
|
|
29
|
+
"July 11, 07".to_date.should == Date.parse("0007-07-11")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
specify "should raise InvalidValue for an invalid date" do
|
|
33
|
+
proc {'0000-00-00'.to_date}.should raise_error(Sequel::InvalidValue)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "String#to_datetime" do
|
|
38
|
+
after do
|
|
39
|
+
Sequel.convert_two_digit_years = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
specify "should convert the string into a DateTime object" do
|
|
43
|
+
"2007-07-11 10:11:12a".to_datetime.should == DateTime.parse("2007-07-11 10:11:12a")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
specify "should convert 2 digit years by default" do
|
|
47
|
+
"July 11, 07 10:11:12a".to_datetime.should == DateTime.parse("2007-07-11 10:11:12a")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
specify "should not convert 2 digit years if set not to" do
|
|
51
|
+
Sequel.convert_two_digit_years = false
|
|
52
|
+
"July 11, 07 10:11:12a".to_datetime.should == DateTime.parse("0007-07-11 10:11:12a")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
specify "should raise InvalidValue for an invalid date" do
|
|
56
|
+
proc {'0000-00-00'.to_datetime}.should raise_error(Sequel::InvalidValue)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "String#to_sequel_time" do
|
|
61
|
+
after do
|
|
62
|
+
Sequel.datetime_class = Time
|
|
63
|
+
Sequel.convert_two_digit_years = true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
specify "should convert the string into a Time object by default" do
|
|
67
|
+
"2007-07-11 10:11:12a".to_sequel_time.class.should == Time
|
|
68
|
+
"2007-07-11 10:11:12a".to_sequel_time.should == Time.parse("2007-07-11 10:11:12a")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
specify "should convert the string into a DateTime object if that is set" do
|
|
72
|
+
Sequel.datetime_class = DateTime
|
|
73
|
+
"2007-07-11 10:11:12a".to_sequel_time.class.should == DateTime
|
|
74
|
+
"2007-07-11 10:11:12a".to_sequel_time.should == DateTime.parse("2007-07-11 10:11:12a")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
specify "should convert 2 digit years by default if using DateTime class" do
|
|
78
|
+
Sequel.datetime_class = DateTime
|
|
79
|
+
"July 11, 07 10:11:12a".to_sequel_time.should == DateTime.parse("2007-07-11 10:11:12a")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
specify "should not convert 2 digit years if set not to when using DateTime class" do
|
|
83
|
+
Sequel.datetime_class = DateTime
|
|
84
|
+
Sequel.convert_two_digit_years = false
|
|
85
|
+
"July 11, 07 10:11:12a".to_sequel_time.should == DateTime.parse("0007-07-11 10:11:12a")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
specify "should raise InvalidValue for an invalid time" do
|
|
89
|
+
proc {'0000-00-00'.to_sequel_time}.should raise_error(Sequel::InvalidValue)
|
|
90
|
+
Sequel.datetime_class = DateTime
|
|
91
|
+
proc {'0000-00-00'.to_sequel_time}.should raise_error(Sequel::InvalidValue)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -1,82 +1,7 @@
|
|
|
1
1
|
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
2
2
|
|
|
3
|
-
describe Sequel::Model::Validation::Errors do
|
|
4
|
-
setup do
|
|
5
|
-
@errors = Sequel::Model::Validation::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
3
|
describe Sequel::Model do
|
|
79
|
-
|
|
4
|
+
before do
|
|
80
5
|
@c = Class.new(Sequel::Model) do
|
|
81
6
|
def self.validates_coolness_of(attr)
|
|
82
7
|
validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
|
|
@@ -190,7 +115,7 @@ describe Sequel::Model do
|
|
|
190
115
|
end
|
|
191
116
|
|
|
192
117
|
describe Sequel::Model do
|
|
193
|
-
|
|
118
|
+
before do
|
|
194
119
|
@c = Class.new(Sequel::Model) do
|
|
195
120
|
columns :score
|
|
196
121
|
validates_each :score do |o, a, v|
|
|
@@ -220,8 +145,8 @@ describe Sequel::Model do
|
|
|
220
145
|
end
|
|
221
146
|
end
|
|
222
147
|
|
|
223
|
-
describe Sequel::
|
|
224
|
-
|
|
148
|
+
describe Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator do
|
|
149
|
+
before do
|
|
225
150
|
$testit = nil
|
|
226
151
|
|
|
227
152
|
@c = Class.new(Sequel::Model) do
|
|
@@ -232,7 +157,7 @@ describe Sequel::Model::Validation::Generator do
|
|
|
232
157
|
end
|
|
233
158
|
|
|
234
159
|
specify "should instance_eval the block, sending everything to its receiver" do
|
|
235
|
-
|
|
160
|
+
@c.validates do
|
|
236
161
|
blah
|
|
237
162
|
end
|
|
238
163
|
$testit.should == 1324
|
|
@@ -240,7 +165,7 @@ describe Sequel::Model::Validation::Generator do
|
|
|
240
165
|
end
|
|
241
166
|
|
|
242
167
|
describe Sequel::Model do
|
|
243
|
-
|
|
168
|
+
before do
|
|
244
169
|
@c = Class.new(Sequel::Model) do
|
|
245
170
|
columns :value
|
|
246
171
|
|
|
@@ -625,7 +550,7 @@ describe Sequel::Model do
|
|
|
625
550
|
end
|
|
626
551
|
|
|
627
552
|
context "Superclass validations" do
|
|
628
|
-
|
|
553
|
+
before do
|
|
629
554
|
@c1 = Class.new(Sequel::Model) do
|
|
630
555
|
columns :value
|
|
631
556
|
validates_length_of :value, :minimum => 5
|
|
@@ -1011,28 +936,8 @@ describe Sequel::Model, "Validations" do
|
|
|
1011
936
|
|
|
1012
937
|
end
|
|
1013
938
|
|
|
1014
|
-
describe "Model#save!" do
|
|
1015
|
-
setup do
|
|
1016
|
-
@c = Class.new(Sequel::Model(:people)) do
|
|
1017
|
-
def columns; [:id]; end
|
|
1018
|
-
|
|
1019
|
-
validates_each :id do |o, a, v|
|
|
1020
|
-
o.errors[a] << 'blah' unless v == 5
|
|
1021
|
-
end
|
|
1022
|
-
end
|
|
1023
|
-
@m = @c.load(:id => 4)
|
|
1024
|
-
MODEL_DB.reset
|
|
1025
|
-
end
|
|
1026
|
-
|
|
1027
|
-
specify "should save regardless of validations" do
|
|
1028
|
-
@m.should_not be_valid
|
|
1029
|
-
@m.save!
|
|
1030
|
-
MODEL_DB.sqls.should == ['UPDATE people SET id = 4 WHERE (id = 4)']
|
|
1031
|
-
end
|
|
1032
|
-
end
|
|
1033
|
-
|
|
1034
939
|
describe "Model#save" do
|
|
1035
|
-
|
|
940
|
+
before do
|
|
1036
941
|
@c = Class.new(Sequel::Model(:people)) do
|
|
1037
942
|
columns :id
|
|
1038
943
|
|
|
@@ -1056,6 +961,13 @@ describe "Model#save" do
|
|
|
1056
961
|
MODEL_DB.sqls.should == ['UPDATE people SET id = 5 WHERE (id = 5)']
|
|
1057
962
|
end
|
|
1058
963
|
|
|
964
|
+
specify "should skip validations if the :validate=>false option is used" do
|
|
965
|
+
@m.raise_on_save_failure = false
|
|
966
|
+
@m.should_not be_valid
|
|
967
|
+
@m.save(:validate=>false)
|
|
968
|
+
MODEL_DB.sqls.should == ['UPDATE people SET id = 4 WHERE (id = 4)']
|
|
969
|
+
end
|
|
970
|
+
|
|
1059
971
|
specify "should raise error if validations fail and raise_on_save_faiure is true" do
|
|
1060
972
|
proc{@m.save}.should raise_error(Sequel::ValidationFailed)
|
|
1061
973
|
end
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::ValidationHelpers" do
|
|
4
|
+
before do
|
|
5
|
+
@c = Class.new(Sequel::Model) do
|
|
6
|
+
def self.set_validations(&block)
|
|
7
|
+
define_method(:validate, &block)
|
|
8
|
+
end
|
|
9
|
+
columns :value
|
|
10
|
+
end
|
|
11
|
+
@c.plugin :validation_helpers
|
|
12
|
+
@m = @c.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
specify "should take an :allow_blank option" do
|
|
16
|
+
@c.set_validations{validates_format(/.+_.+/, :value, :allow_blank=>true)}
|
|
17
|
+
@m.value = 'abc_'
|
|
18
|
+
@m.should_not be_valid
|
|
19
|
+
@m.value = '1_1'
|
|
20
|
+
@m.should be_valid
|
|
21
|
+
o = Object.new
|
|
22
|
+
@m.value = o
|
|
23
|
+
@m.should_not be_valid
|
|
24
|
+
def o.blank?
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
@m.should be_valid
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
specify "should take an :allow_missing option" do
|
|
31
|
+
@c.set_validations{validates_format(/.+_.+/, :value, :allow_missing=>true)}
|
|
32
|
+
@m.values.clear
|
|
33
|
+
@m.should be_valid
|
|
34
|
+
@m.value = nil
|
|
35
|
+
@m.should_not be_valid
|
|
36
|
+
@m.value = '1_1'
|
|
37
|
+
@m.should be_valid
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
specify "should take an :allow_nil option" do
|
|
41
|
+
@c.set_validations{validates_format(/.+_.+/, :value, :allow_nil=>true)}
|
|
42
|
+
@m.value = 'abc_'
|
|
43
|
+
@m.should_not be_valid
|
|
44
|
+
@m.value = '1_1'
|
|
45
|
+
@m.should be_valid
|
|
46
|
+
@m.value = nil
|
|
47
|
+
@m.should be_valid
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
specify "should take a :message option" do
|
|
51
|
+
@c.set_validations{validates_format(/.+_.+/, :value, :message=>"is so blah")}
|
|
52
|
+
@m.value = 'abc_'
|
|
53
|
+
@m.should_not be_valid
|
|
54
|
+
@m.errors.full_messages.should == ['value is so blah']
|
|
55
|
+
@m.value = '1_1'
|
|
56
|
+
@m.should be_valid
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
specify "should take multiple attributes in the same call" do
|
|
60
|
+
@c.columns :value, :value2
|
|
61
|
+
@c.set_validations{validates_presence([:value, :value2])}
|
|
62
|
+
@m.should_not be_valid
|
|
63
|
+
@m.value = 1
|
|
64
|
+
@m.should_not be_valid
|
|
65
|
+
@m.value2 = 1
|
|
66
|
+
@m.should be_valid
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
specify "should support validates_exact_length" do
|
|
70
|
+
@c.set_validations{validates_exact_length(3, :value)}
|
|
71
|
+
@m.should_not be_valid
|
|
72
|
+
@m.value = '123'
|
|
73
|
+
@m.should be_valid
|
|
74
|
+
@m.value = '12'
|
|
75
|
+
@m.should_not be_valid
|
|
76
|
+
@m.value = '1234'
|
|
77
|
+
@m.should_not be_valid
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
specify "should support validate_format" do
|
|
81
|
+
@c.set_validations{validates_format(/.+_.+/, :value)}
|
|
82
|
+
@m.value = 'abc_'
|
|
83
|
+
@m.should_not be_valid
|
|
84
|
+
@m.value = 'abc_def'
|
|
85
|
+
@m.should be_valid
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
specify "should support validates_includes with an array" do
|
|
89
|
+
@c.set_validations{validates_includes([1,2], :value)}
|
|
90
|
+
@m.should_not be_valid
|
|
91
|
+
@m.value = 1
|
|
92
|
+
@m.should be_valid
|
|
93
|
+
@m.value = 1.5
|
|
94
|
+
@m.should_not be_valid
|
|
95
|
+
@m.value = 2
|
|
96
|
+
@m.should be_valid
|
|
97
|
+
@m.value = 3
|
|
98
|
+
@m.should_not be_valid
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
specify "should support validates_includes with a range" do
|
|
102
|
+
@c.set_validations{validates_includes(1..4, :value)}
|
|
103
|
+
@m.should_not be_valid
|
|
104
|
+
@m.value = 1
|
|
105
|
+
@m.should be_valid
|
|
106
|
+
@m.value = 1.5
|
|
107
|
+
@m.should be_valid
|
|
108
|
+
@m.value = 0
|
|
109
|
+
@m.should_not be_valid
|
|
110
|
+
@m.value = 5
|
|
111
|
+
@m.should_not be_valid
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
specify "should supports validates_integer" do
|
|
115
|
+
@c.set_validations{validates_integer(:value)}
|
|
116
|
+
@m.value = 'blah'
|
|
117
|
+
@m.should_not be_valid
|
|
118
|
+
@m.value = '123'
|
|
119
|
+
@m.should be_valid
|
|
120
|
+
@m.value = '123.1231'
|
|
121
|
+
@m.should_not be_valid
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
specify "should support validates_length_range" do
|
|
125
|
+
@c.set_validations{validates_length_range(2..5, :value)}
|
|
126
|
+
@m.should_not be_valid
|
|
127
|
+
@m.value = '12345'
|
|
128
|
+
@m.should be_valid
|
|
129
|
+
@m.value = '1'
|
|
130
|
+
@m.should_not be_valid
|
|
131
|
+
@m.value = '123456'
|
|
132
|
+
@m.should_not be_valid
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
specify "should support validates_max_length" do
|
|
136
|
+
@c.set_validations{validates_max_length(5, :value)}
|
|
137
|
+
@m.should_not be_valid
|
|
138
|
+
@m.value = '12345'
|
|
139
|
+
@m.should be_valid
|
|
140
|
+
@m.value = '123456'
|
|
141
|
+
@m.should_not be_valid
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
specify "should support validates_min_length" do
|
|
145
|
+
@c.set_validations{validates_min_length(5, :value)}
|
|
146
|
+
@m.should_not be_valid
|
|
147
|
+
@m.value = '12345'
|
|
148
|
+
@m.should be_valid
|
|
149
|
+
@m.value = '1234'
|
|
150
|
+
@m.should_not be_valid
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
specify "should support validates_not_string" do
|
|
154
|
+
@c.set_validations{validates_not_string(:value)}
|
|
155
|
+
@m.value = 123
|
|
156
|
+
@m.should be_valid
|
|
157
|
+
@m.value = '123'
|
|
158
|
+
@m.should_not be_valid
|
|
159
|
+
@m.errors.full_messages.should == ['value is a string']
|
|
160
|
+
@m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
|
|
161
|
+
@m.should_not be_valid
|
|
162
|
+
@m.errors.full_messages.should == ['value is not a valid integer']
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
specify "should support validates_numeric" do
|
|
166
|
+
@c.set_validations{validates_numeric(:value)}
|
|
167
|
+
@m.value = 'blah'
|
|
168
|
+
@m.should_not be_valid
|
|
169
|
+
@m.value = '123'
|
|
170
|
+
@m.should be_valid
|
|
171
|
+
@m.value = '123.1231'
|
|
172
|
+
@m.should be_valid
|
|
173
|
+
@m.value = '+1'
|
|
174
|
+
@m.should be_valid
|
|
175
|
+
@m.value = '-1'
|
|
176
|
+
@m.should be_valid
|
|
177
|
+
@m.value = '+1.123'
|
|
178
|
+
@m.should be_valid
|
|
179
|
+
@m.value = '-0.123'
|
|
180
|
+
@m.should be_valid
|
|
181
|
+
@m.value = '-0.123E10'
|
|
182
|
+
@m.should be_valid
|
|
183
|
+
@m.value = '32.123e10'
|
|
184
|
+
@m.should be_valid
|
|
185
|
+
@m.value = '+32.123E10'
|
|
186
|
+
@m.should be_valid
|
|
187
|
+
@m.should be_valid
|
|
188
|
+
@m.value = '.0123'
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
specify "should support validates_presence" do
|
|
192
|
+
@c.set_validations{validates_presence(:value)}
|
|
193
|
+
@m.should_not be_valid
|
|
194
|
+
@m.value = ''
|
|
195
|
+
@m.should_not be_valid
|
|
196
|
+
@m.value = 1234
|
|
197
|
+
@m.should be_valid
|
|
198
|
+
@m.value = nil
|
|
199
|
+
@m.should_not be_valid
|
|
200
|
+
@m.value = true
|
|
201
|
+
@m.should be_valid
|
|
202
|
+
@m.value = false
|
|
203
|
+
@m.should be_valid
|
|
204
|
+
@m.value = Time.now
|
|
205
|
+
@m.should be_valid
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "should support validates_unique with a single attribute" do
|
|
209
|
+
@c.columns(:id, :username, :password)
|
|
210
|
+
@c.set_dataset MODEL_DB[:items]
|
|
211
|
+
@c.set_validations{validates_unique(:username)}
|
|
212
|
+
@c.dataset.extend(Module.new {
|
|
213
|
+
def fetch_rows(sql)
|
|
214
|
+
@db << sql
|
|
215
|
+
|
|
216
|
+
case sql
|
|
217
|
+
when /COUNT.*username = '0records'/
|
|
218
|
+
yield({:v => 0})
|
|
219
|
+
when /COUNT.*username = '1record'/
|
|
220
|
+
yield({:v => 1})
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
@user = @c.new(:username => "0records", :password => "anothertest")
|
|
226
|
+
@user.should be_valid
|
|
227
|
+
@user = @c.load(:id=>3, :username => "0records", :password => "anothertest")
|
|
228
|
+
@user.should be_valid
|
|
229
|
+
|
|
230
|
+
@user = @c.new(:username => "1record", :password => "anothertest")
|
|
231
|
+
@user.should_not be_valid
|
|
232
|
+
@user.errors.full_messages.should == ['username is already taken']
|
|
233
|
+
@user = @c.load(:id=>4, :username => "1record", :password => "anothertest")
|
|
234
|
+
@user.should_not be_valid
|
|
235
|
+
@user.errors.full_messages.should == ['username is already taken']
|
|
236
|
+
|
|
237
|
+
ds1 = @c.dataset.filter([[:username, '0records']])
|
|
238
|
+
ds2 = ds1.exclude(:id=>1)
|
|
239
|
+
@c.dataset.should_receive(:filter).with([[:username, '0records']]).twice.and_return(ds1)
|
|
240
|
+
ds1.should_receive(:exclude).with(:id=>1).once.and_return(ds2)
|
|
241
|
+
|
|
242
|
+
@user = @c.load(:id=>1, :username => "0records", :password => "anothertest")
|
|
243
|
+
@user.should be_valid
|
|
244
|
+
MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE ((username = '0records') AND (id != 1)) LIMIT 1"
|
|
245
|
+
@user = @c.new(:username => "0records", :password => "anothertest")
|
|
246
|
+
@user.should be_valid
|
|
247
|
+
MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE (username = '0records') LIMIT 1"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it "should support validates_unique with multiple attributes" do
|
|
251
|
+
@c.columns(:id, :username, :password)
|
|
252
|
+
@c.set_dataset MODEL_DB[:items]
|
|
253
|
+
@c.set_validations{validates_unique([:username, :password])}
|
|
254
|
+
@c.dataset.extend(Module.new {
|
|
255
|
+
def fetch_rows(sql)
|
|
256
|
+
@db << sql
|
|
257
|
+
|
|
258
|
+
case sql
|
|
259
|
+
when /COUNT.*username = '0records'/
|
|
260
|
+
yield({:v => 0})
|
|
261
|
+
when /COUNT.*username = '1record'/
|
|
262
|
+
yield({:v => 1})
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
@user = @c.new(:username => "0records", :password => "anothertest")
|
|
268
|
+
@user.should be_valid
|
|
269
|
+
@user = @c.load(:id=>3, :username => "0records", :password => "anothertest")
|
|
270
|
+
@user.should be_valid
|
|
271
|
+
|
|
272
|
+
@user = @c.new(:username => "1record", :password => "anothertest")
|
|
273
|
+
@user.should_not be_valid
|
|
274
|
+
@user.errors.full_messages.should == ['username and password is already taken']
|
|
275
|
+
@user = @c.load(:id=>4, :username => "1record", :password => "anothertest")
|
|
276
|
+
@user.should_not be_valid
|
|
277
|
+
@user.errors.full_messages.should == ['username and password is already taken']
|
|
278
|
+
|
|
279
|
+
ds1 = @c.dataset.filter([[:username, '0records'], [:password, 'anothertest']])
|
|
280
|
+
ds2 = ds1.exclude(:id=>1)
|
|
281
|
+
@c.dataset.should_receive(:filter).with([[:username, '0records'], [:password, 'anothertest']]).twice.and_return(ds1)
|
|
282
|
+
ds1.should_receive(:exclude).with(:id=>1).once.and_return(ds2)
|
|
283
|
+
|
|
284
|
+
@user = @c.load(:id=>1, :username => "0records", :password => "anothertest")
|
|
285
|
+
@user.should be_valid
|
|
286
|
+
MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE (((username = '0records') AND (password = 'anothertest')) AND (id != 1)) LIMIT 1"
|
|
287
|
+
@user = @c.new(:username => "0records", :password => "anothertest")
|
|
288
|
+
@user.should be_valid
|
|
289
|
+
MODEL_DB.sqls.last.should == "SELECT COUNT(*) FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"
|
|
290
|
+
end
|
|
291
|
+
end
|