sequel 4.22.0 → 4.23.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.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +6 -0
- data/Rakefile +59 -81
- data/doc/migration.rdoc +2 -0
- data/doc/release_notes/4.23.0.txt +65 -0
- data/doc/sharding.rdoc +16 -14
- data/doc/testing.rdoc +61 -77
- data/lib/sequel/adapters/jdbc.rb +1 -0
- data/lib/sequel/adapters/mock.rb +0 -1
- data/lib/sequel/adapters/postgres.rb +1 -0
- data/lib/sequel/adapters/postgresql.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +9 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/transactions.rb +2 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +12 -12
- data/lib/sequel/extensions/date_arithmetic.rb +0 -4
- data/lib/sequel/extensions/pagination.rb +14 -2
- data/lib/sequel/extensions/pg_enum.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/delay_add_association.rb +50 -0
- data/lib/sequel/plugins/list.rb +2 -2
- data/lib/sequel/plugins/nested_attributes.rb +8 -28
- data/lib/sequel/plugins/update_refresh.rb +50 -0
- data/lib/sequel/plugins/validate_associated.rb +55 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +29 -29
- data/spec/adapters/firebird_spec.rb +97 -103
- data/spec/adapters/informix_spec.rb +25 -25
- data/spec/adapters/mssql_spec.rb +156 -172
- data/spec/adapters/mysql_spec.rb +334 -359
- data/spec/adapters/oracle_spec.rb +67 -69
- data/spec/adapters/postgres_spec.rb +1298 -1249
- data/spec/adapters/spec_helper.rb +2 -35
- data/spec/adapters/sqlanywhere_spec.rb +39 -39
- data/spec/adapters/sqlite_spec.rb +203 -200
- data/spec/bin_spec.rb +57 -59
- data/spec/core/connection_pool_spec.rb +402 -401
- data/spec/core/database_spec.rb +953 -944
- data/spec/core/dataset_spec.rb +2178 -2168
- data/spec/core/deprecated_spec.rb +19 -19
- data/spec/core/expression_filters_spec.rb +415 -415
- data/spec/core/mock_adapter_spec.rb +212 -212
- data/spec/core/object_graph_spec.rb +73 -73
- data/spec/core/placeholder_literalizer_spec.rb +71 -71
- data/spec/core/schema_generator_spec.rb +44 -44
- data/spec/core/schema_spec.rb +470 -472
- data/spec/core/spec_helper.rb +5 -20
- data/spec/core/version_spec.rb +2 -2
- data/spec/core_extensions_spec.rb +320 -320
- data/spec/extensions/accessed_columns_spec.rb +12 -12
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +2 -2
- data/spec/extensions/arbitrary_servers_spec.rb +23 -23
- data/spec/extensions/association_dependencies_spec.rb +34 -34
- data/spec/extensions/association_pks_spec.rb +98 -98
- data/spec/extensions/association_proxies_spec.rb +33 -33
- data/spec/extensions/auto_validations_spec.rb +46 -46
- data/spec/extensions/blacklist_security_spec.rb +19 -18
- data/spec/extensions/blank_spec.rb +36 -36
- data/spec/extensions/boolean_readers_spec.rb +36 -36
- data/spec/extensions/caching_spec.rb +82 -82
- data/spec/extensions/class_table_inheritance_spec.rb +72 -72
- data/spec/extensions/column_conflicts_spec.rb +19 -14
- data/spec/extensions/column_select_spec.rb +19 -19
- data/spec/extensions/columns_introspection_spec.rb +43 -43
- data/spec/extensions/composition_spec.rb +64 -64
- data/spec/extensions/connection_validator_spec.rb +92 -90
- data/spec/extensions/constraint_validations_plugin_spec.rb +92 -92
- data/spec/extensions/constraint_validations_spec.rb +80 -80
- data/spec/extensions/core_refinements_spec.rb +220 -220
- data/spec/extensions/csv_serializer_spec.rb +44 -44
- data/spec/extensions/current_datetime_timestamp_spec.rb +8 -8
- data/spec/extensions/dataset_associations_spec.rb +65 -65
- data/spec/extensions/dataset_source_alias_spec.rb +16 -16
- data/spec/extensions/date_arithmetic_spec.rb +51 -58
- data/spec/extensions/defaults_setter_spec.rb +19 -19
- data/spec/extensions/delay_add_association_spec.rb +52 -0
- data/spec/extensions/dirty_spec.rb +51 -51
- data/spec/extensions/eager_each_spec.rb +8 -8
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +10 -10
- data/spec/extensions/error_splitter_spec.rb +2 -2
- data/spec/extensions/error_sql_spec.rb +4 -4
- data/spec/extensions/eval_inspect_spec.rb +3 -3
- data/spec/extensions/filter_having_spec.rb +8 -8
- data/spec/extensions/force_encoding_spec.rb +30 -30
- data/spec/extensions/from_block_spec.rb +7 -7
- data/spec/extensions/graph_each_spec.rb +19 -19
- data/spec/extensions/hash_aliases_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +100 -100
- data/spec/extensions/inflector_spec.rb +54 -54
- data/spec/extensions/input_transformer_spec.rb +10 -10
- data/spec/extensions/insert_returning_select_spec.rb +8 -8
- data/spec/extensions/instance_filters_spec.rb +26 -26
- data/spec/extensions/instance_hooks_spec.rb +85 -85
- data/spec/extensions/json_serializer_spec.rb +68 -68
- data/spec/extensions/lazy_attributes_spec.rb +49 -49
- data/spec/extensions/list_spec.rb +77 -75
- data/spec/extensions/looser_typecasting_spec.rb +16 -16
- data/spec/extensions/many_through_many_spec.rb +627 -627
- data/spec/extensions/meta_def_spec.rb +7 -7
- data/spec/extensions/migration_spec.rb +217 -217
- data/spec/extensions/modification_detection_spec.rb +20 -20
- data/spec/extensions/mssql_optimistic_locking_spec.rb +21 -21
- data/spec/extensions/named_timezones_spec.rb +18 -18
- data/spec/extensions/nested_attributes_spec.rb +107 -107
- data/spec/extensions/null_dataset_spec.rb +24 -24
- data/spec/extensions/optimistic_locking_spec.rb +21 -21
- data/spec/extensions/pagination_spec.rb +52 -52
- data/spec/extensions/pg_array_associations_spec.rb +273 -273
- data/spec/extensions/pg_array_ops_spec.rb +52 -52
- data/spec/extensions/pg_array_spec.rb +152 -152
- data/spec/extensions/pg_enum_spec.rb +13 -13
- data/spec/extensions/pg_hstore_ops_spec.rb +63 -63
- data/spec/extensions/pg_hstore_spec.rb +84 -84
- data/spec/extensions/pg_inet_spec.rb +15 -15
- data/spec/extensions/pg_interval_spec.rb +29 -29
- data/spec/extensions/pg_json_ops_spec.rb +86 -84
- data/spec/extensions/pg_json_spec.rb +104 -104
- data/spec/extensions/pg_loose_count_spec.rb +6 -6
- data/spec/extensions/pg_range_ops_spec.rb +24 -24
- data/spec/extensions/pg_range_spec.rb +143 -143
- data/spec/extensions/pg_row_ops_spec.rb +14 -14
- data/spec/extensions/pg_row_plugin_spec.rb +12 -12
- data/spec/extensions/pg_row_spec.rb +118 -118
- data/spec/extensions/pg_static_cache_updater_spec.rb +28 -28
- data/spec/extensions/pg_typecast_on_load_spec.rb +21 -21
- data/spec/extensions/prepared_statements_associations_spec.rb +42 -42
- data/spec/extensions/prepared_statements_safe_spec.rb +18 -18
- data/spec/extensions/prepared_statements_spec.rb +28 -28
- data/spec/extensions/prepared_statements_with_pk_spec.rb +11 -11
- data/spec/extensions/pretty_table_spec.rb +16 -16
- data/spec/extensions/query_literals_spec.rb +37 -37
- data/spec/extensions/query_spec.rb +32 -32
- data/spec/extensions/rcte_tree_spec.rb +141 -141
- data/spec/extensions/round_timestamps_spec.rb +21 -21
- data/spec/extensions/schema_caching_spec.rb +8 -8
- data/spec/extensions/schema_dumper_spec.rb +78 -78
- data/spec/extensions/schema_spec.rb +31 -27
- data/spec/extensions/scissors_spec.rb +3 -3
- data/spec/extensions/select_remove_spec.rb +14 -14
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +28 -28
- data/spec/extensions/serialization_modification_detection_spec.rb +33 -33
- data/spec/extensions/serialization_spec.rb +79 -78
- data/spec/extensions/server_block_spec.rb +17 -17
- data/spec/extensions/set_overrides_spec.rb +30 -30
- data/spec/extensions/sharding_spec.rb +65 -65
- data/spec/extensions/shared_caching_spec.rb +29 -29
- data/spec/extensions/single_table_inheritance_spec.rb +79 -79
- data/spec/extensions/skip_create_refresh_spec.rb +3 -3
- data/spec/extensions/spec_helper.rb +4 -29
- data/spec/extensions/split_array_nil_spec.rb +9 -9
- data/spec/extensions/split_values_spec.rb +7 -7
- data/spec/extensions/sql_expr_spec.rb +32 -32
- data/spec/extensions/static_cache_spec.rb +123 -123
- data/spec/extensions/string_date_time_spec.rb +34 -34
- data/spec/extensions/string_stripper_spec.rb +15 -15
- data/spec/extensions/subclasses_spec.rb +31 -31
- data/spec/extensions/table_select_spec.rb +15 -15
- data/spec/extensions/tactical_eager_loading_spec.rb +23 -23
- data/spec/extensions/thread_local_timezones_spec.rb +13 -13
- data/spec/extensions/timestamps_spec.rb +40 -40
- data/spec/extensions/to_dot_spec.rb +34 -34
- data/spec/extensions/touch_spec.rb +52 -52
- data/spec/extensions/tree_spec.rb +72 -72
- data/spec/extensions/typecast_on_load_spec.rb +25 -25
- data/spec/extensions/unlimited_update_spec.rb +2 -2
- data/spec/extensions/update_or_create_spec.rb +36 -36
- data/spec/extensions/update_primary_key_spec.rb +35 -35
- data/spec/extensions/update_refresh_spec.rb +41 -0
- data/spec/extensions/validate_associated_spec.rb +52 -0
- data/spec/extensions/validation_class_methods_spec.rb +314 -317
- data/spec/extensions/validation_helpers_spec.rb +195 -195
- data/spec/extensions/xml_serializer_spec.rb +48 -48
- data/spec/guards_helper.rb +55 -0
- data/spec/integration/associations_test.rb +1089 -1088
- data/spec/integration/database_test.rb +29 -29
- data/spec/integration/dataset_test.rb +661 -661
- data/spec/integration/eager_loader_test.rb +147 -147
- data/spec/integration/migrator_test.rb +122 -122
- data/spec/integration/model_test.rb +70 -70
- data/spec/integration/plugin_test.rb +682 -640
- data/spec/integration/prepared_statement_test.rb +172 -172
- data/spec/integration/schema_test.rb +245 -245
- data/spec/integration/spec_helper.rb +1 -64
- data/spec/integration/timezone_test.rb +17 -17
- data/spec/integration/transaction_test.rb +87 -87
- data/spec/integration/type_test.rb +33 -33
- data/spec/model/association_reflection_spec.rb +130 -121
- data/spec/model/associations_spec.rb +1112 -1113
- data/spec/model/base_spec.rb +197 -196
- data/spec/model/class_dataset_methods_spec.rb +118 -118
- data/spec/model/dataset_methods_spec.rb +49 -49
- data/spec/model/eager_loading_spec.rb +705 -702
- data/spec/model/hooks_spec.rb +169 -168
- data/spec/model/inflector_spec.rb +5 -5
- data/spec/model/model_spec.rb +287 -297
- data/spec/model/plugins_spec.rb +47 -47
- data/spec/model/record_spec.rb +534 -535
- data/spec/model/spec_helper.rb +3 -21
- data/spec/model/validations_spec.rb +72 -70
- data/spec/spec_config.rb +8 -0
- metadata +41 -9
- data/lib/sequel/adapters/fdbsql.rb +0 -286
- data/lib/sequel/adapters/jdbc/fdbsql.rb +0 -66
- data/lib/sequel/adapters/openbase.rb +0 -54
- data/lib/sequel/adapters/shared/fdbsql.rb +0 -550
- data/spec/adapters/fdbsql_spec.rb +0 -429
- data/spec/rspec_helper.rb +0 -22
|
@@ -1,105 +1,107 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
3
|
+
connection_validator_specs = shared_description do
|
|
4
|
+
describe "connection validator" do
|
|
5
|
+
before do
|
|
6
|
+
@db.extend(Module.new do
|
|
7
|
+
def disconnect_connection(conn)
|
|
8
|
+
@sqls << 'disconnect'
|
|
9
|
+
end
|
|
10
|
+
def valid_connection?(conn)
|
|
11
|
+
super
|
|
12
|
+
conn.valid
|
|
13
|
+
end
|
|
14
|
+
def connect(server)
|
|
15
|
+
conn = super
|
|
16
|
+
conn.extend(Module.new do
|
|
17
|
+
attr_accessor :valid
|
|
18
|
+
end)
|
|
19
|
+
conn.valid = true
|
|
20
|
+
conn
|
|
21
|
+
end
|
|
22
|
+
end)
|
|
23
|
+
@db.extension(:connection_validator)
|
|
24
|
+
end
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
it "should still allow new connections" do
|
|
27
|
+
@db.synchronize{|c| c}.must_be_kind_of(Sequel::Mock::Connection)
|
|
28
|
+
end
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
it "should only validate if connection idle longer than timeout" do
|
|
31
|
+
c1 = @db.synchronize{|c| c}
|
|
32
|
+
@db.sqls.must_equal []
|
|
33
|
+
@db.synchronize{|c| c}.must_be_same_as(c1)
|
|
34
|
+
@db.sqls.must_equal []
|
|
35
|
+
@db.pool.connection_validation_timeout = -1
|
|
36
|
+
@db.synchronize{|c| c}.must_be_same_as(c1)
|
|
37
|
+
@db.sqls.must_equal ['SELECT NULL']
|
|
38
|
+
@db.pool.connection_validation_timeout = 1
|
|
39
|
+
@db.synchronize{|c| c}.must_be_same_as(c1)
|
|
40
|
+
@db.sqls.must_equal []
|
|
41
|
+
@db.synchronize{|c| c}.must_be_same_as(c1)
|
|
42
|
+
@db.sqls.must_equal []
|
|
43
|
+
end
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
it "should disconnect connection if not valid" do
|
|
46
|
+
c1 = @db.synchronize{|c| c}
|
|
47
|
+
@db.sqls.must_equal []
|
|
48
|
+
c1.valid = false
|
|
49
|
+
@db.pool.connection_validation_timeout = -1
|
|
50
|
+
c2 = @db.synchronize{|c| c}
|
|
51
|
+
@db.sqls.must_equal ['SELECT NULL', 'disconnect']
|
|
52
|
+
c2.wont_be_same_as(c1)
|
|
53
|
+
end
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
it "should disconnect multiple connections repeatedly if they are not valid" do
|
|
56
|
+
q, q1 = Queue.new, Queue.new
|
|
57
|
+
c1 = nil
|
|
58
|
+
c2 = nil
|
|
59
|
+
@db.pool.connection_validation_timeout = -1
|
|
60
|
+
@db.synchronize do |c|
|
|
61
|
+
Thread.new do
|
|
62
|
+
@db.synchronize do |cc|
|
|
63
|
+
c2 = cc
|
|
64
|
+
end
|
|
65
|
+
q1.pop
|
|
66
|
+
q.push nil
|
|
63
67
|
end
|
|
64
|
-
q1.
|
|
65
|
-
q.
|
|
68
|
+
q1.push nil
|
|
69
|
+
q.pop
|
|
70
|
+
c1 = c
|
|
66
71
|
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
c1.valid = false
|
|
73
|
+
c2.valid = false
|
|
74
|
+
|
|
75
|
+
c3 = @db.synchronize{|c| c}
|
|
76
|
+
@db.sqls.must_equal ['SELECT NULL', 'disconnect', 'SELECT NULL', 'disconnect']
|
|
77
|
+
c3.wont_be_same_as(c1)
|
|
78
|
+
c3.wont_be_same_as(c2)
|
|
70
79
|
end
|
|
71
|
-
c1.valid = false
|
|
72
|
-
c2.valid = false
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
it "should not leak connection references" do
|
|
82
|
+
c1 = @db.synchronize do |c|
|
|
83
|
+
@db.pool.instance_variable_get(:@connection_timestamps).must_equal({})
|
|
84
|
+
c
|
|
85
|
+
end
|
|
86
|
+
@db.pool.instance_variable_get(:@connection_timestamps).must_include(c1)
|
|
79
87
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@db.
|
|
83
|
-
|
|
88
|
+
c1.valid = false
|
|
89
|
+
@db.pool.connection_validation_timeout = -1
|
|
90
|
+
c2 = @db.synchronize do |c|
|
|
91
|
+
@db.pool.instance_variable_get(:@connection_timestamps).must_equal({})
|
|
92
|
+
c
|
|
93
|
+
end
|
|
94
|
+
c2.wont_be_same_as(c1)
|
|
95
|
+
@db.pool.instance_variable_get(:@connection_timestamps).wont_include(c1)
|
|
96
|
+
@db.pool.instance_variable_get(:@connection_timestamps).must_include(c2)
|
|
84
97
|
end
|
|
85
|
-
@db.pool.instance_variable_get(:@connection_timestamps).should have_key(c1)
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
@db.
|
|
91
|
-
c
|
|
99
|
+
it "should handle case where determining validity requires a connection" do
|
|
100
|
+
@db.meta_def(:valid_connection?){|c| synchronize{}; true}
|
|
101
|
+
@db.pool.connection_validation_timeout = -1
|
|
102
|
+
c1 = @db.synchronize{|c| c}
|
|
103
|
+
@db.synchronize{|c| c}.must_be_same_as(c1)
|
|
92
104
|
end
|
|
93
|
-
c2.should_not equal(c1)
|
|
94
|
-
@db.pool.instance_variable_get(:@connection_timestamps).should_not have_key(c1)
|
|
95
|
-
@db.pool.instance_variable_get(:@connection_timestamps).should have_key(c2)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
it "should handle case where determining validity requires a connection" do
|
|
99
|
-
@db.meta_def(:valid_connection?){|c| synchronize{}; true}
|
|
100
|
-
@db.pool.connection_validation_timeout = -1
|
|
101
|
-
c1 = @db.synchronize{|c| c}
|
|
102
|
-
@db.synchronize{|c| c}.should equal(c1)
|
|
103
105
|
end
|
|
104
106
|
end
|
|
105
107
|
|
|
@@ -107,12 +109,12 @@ describe "Sequel::ConnectionValidator with threaded pool" do
|
|
|
107
109
|
before do
|
|
108
110
|
@db = Sequel.mock
|
|
109
111
|
end
|
|
110
|
-
|
|
112
|
+
include connection_validator_specs
|
|
111
113
|
end
|
|
112
114
|
describe "Sequel::ConnectionValidator with sharded threaded pool" do
|
|
113
115
|
before do
|
|
114
116
|
@db = Sequel.mock(:servers=>{})
|
|
115
117
|
end
|
|
116
|
-
|
|
118
|
+
include connection_validator_specs
|
|
117
119
|
end
|
|
118
120
|
|
|
@@ -25,49 +25,49 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
it "should load the validation_helpers plugin into the class" do
|
|
28
|
-
model_class.new.
|
|
28
|
+
model_class.new.must_respond_to(:validates_presence)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it "should parse constraint validations when loading plugin" do
|
|
32
32
|
@c = model_class
|
|
33
|
-
@db.sqls.
|
|
34
|
-
@db.constraint_validations.
|
|
35
|
-
@c.constraint_validations.
|
|
36
|
-
@c.constraint_validation_reflections.
|
|
33
|
+
@db.sqls.must_equal ["SELECT * FROM sequel_constraint_validations"]
|
|
34
|
+
@db.constraint_validations.must_equal("items"=>[{:allow_nil=>nil, :constraint_name=>nil, :message=>nil, :validation_type=>"presence", :column=>"name", :argument=>nil, :table=>"items"}])
|
|
35
|
+
@c.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
36
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it "should parse constraint validations with a custom constraint validations table" do
|
|
40
40
|
c = Class.new(Sequel::Model(@db[:items]))
|
|
41
41
|
@db.sqls
|
|
42
42
|
c.plugin :constraint_validations, :constraint_validations_table=>:foo
|
|
43
|
-
@db.sqls.
|
|
44
|
-
@db.constraint_validations.
|
|
45
|
-
c.constraint_validations.
|
|
46
|
-
c.constraint_validation_reflections.
|
|
43
|
+
@db.sqls.must_equal ["SELECT * FROM foo"]
|
|
44
|
+
@db.constraint_validations.must_equal("items"=>[{:allow_nil=>nil, :constraint_name=>nil, :message=>nil, :validation_type=>"presence", :column=>"name", :argument=>nil, :table=>"items"}])
|
|
45
|
+
c.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
46
|
+
c.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
it "should populate constraint_validations when subclassing" do
|
|
50
50
|
c = Class.new(Sequel::Model(@db))
|
|
51
51
|
c.plugin :constraint_validations
|
|
52
|
-
@db.sqls.
|
|
52
|
+
@db.sqls.must_equal ["SELECT * FROM sequel_constraint_validations"]
|
|
53
53
|
sc = Class.new(c)
|
|
54
54
|
sc.set_dataset @ds
|
|
55
|
-
@db.sqls.
|
|
56
|
-
sc.constraint_validations.
|
|
57
|
-
sc.constraint_validation_reflections.
|
|
55
|
+
@db.sqls.must_equal []
|
|
56
|
+
sc.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
57
|
+
sc.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
it "should handle plugin being loaded in subclass when superclass uses a custom constraint validations table" do
|
|
61
61
|
c = Class.new(Sequel::Model(@db))
|
|
62
62
|
c.plugin :constraint_validations, :constraint_validations_table=>:foo
|
|
63
|
-
@db.sqls.
|
|
63
|
+
@db.sqls.must_equal ["SELECT * FROM foo"]
|
|
64
64
|
sc = Class.new(c)
|
|
65
65
|
sc.plugin :constraint_validations
|
|
66
|
-
sc.constraint_validations_table.
|
|
66
|
+
sc.constraint_validations_table.must_equal :foo
|
|
67
67
|
sc.set_dataset @ds
|
|
68
|
-
@db.sqls.
|
|
69
|
-
sc.constraint_validations.
|
|
70
|
-
sc.constraint_validation_reflections.
|
|
68
|
+
@db.sqls.must_equal []
|
|
69
|
+
sc.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
70
|
+
sc.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
it "should populate constraint_validations when changing the model's dataset" do
|
|
@@ -75,166 +75,166 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
75
75
|
c.columns :name
|
|
76
76
|
@db.sqls
|
|
77
77
|
c.plugin :constraint_validations
|
|
78
|
-
@db.sqls.
|
|
78
|
+
@db.sqls.must_equal ["SELECT * FROM sequel_constraint_validations"]
|
|
79
79
|
sc = Class.new(c)
|
|
80
80
|
sc.set_dataset @ds
|
|
81
|
-
@db.sqls.
|
|
82
|
-
sc.constraint_validations.
|
|
83
|
-
sc.constraint_validation_reflections.
|
|
81
|
+
@db.sqls.must_equal []
|
|
82
|
+
sc.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
83
|
+
sc.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
it "should reparse constraint validations when changing the model's database" do
|
|
87
87
|
c = Class.new(Sequel::Model(@ds2))
|
|
88
88
|
c.plugin :constraint_validations
|
|
89
|
-
@ds2.db.sqls.
|
|
89
|
+
@ds2.db.sqls.must_equal ["SELECT * FROM sequel_constraint_validations"]
|
|
90
90
|
sc = Class.new(c)
|
|
91
91
|
sc.set_dataset @ds
|
|
92
|
-
@db.sqls.
|
|
93
|
-
sc.constraint_validations.
|
|
94
|
-
sc.constraint_validation_reflections.
|
|
92
|
+
@db.sqls.must_equal ["SELECT * FROM sequel_constraint_validations"]
|
|
93
|
+
sc.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
94
|
+
sc.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
it "should reparse constraint validations when changing the model's database with a custom constraint validations table" do
|
|
98
98
|
c = Class.new(Sequel::Model(@ds2))
|
|
99
99
|
c.plugin :constraint_validations, :constraint_validations_table=>:foo
|
|
100
|
-
@ds2.db.sqls.
|
|
100
|
+
@ds2.db.sqls.must_equal ["SELECT * FROM foo"]
|
|
101
101
|
sc = Class.new(c)
|
|
102
102
|
sc.set_dataset @ds
|
|
103
|
-
@db.sqls.
|
|
104
|
-
sc.constraint_validations.
|
|
105
|
-
sc.constraint_validation_reflections.
|
|
103
|
+
@db.sqls.must_equal ["SELECT * FROM foo"]
|
|
104
|
+
sc.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
105
|
+
sc.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
it "should correctly retrieve :message option from constraint validations table" do
|
|
109
|
-
model_class(:message=>'foo').constraint_validations.
|
|
110
|
-
@c.constraint_validation_reflections.
|
|
109
|
+
model_class(:message=>'foo').constraint_validations.must_equal [[:validates_presence, :name, {:message=>'foo'}]]
|
|
110
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:presence, {:message=>'foo'}]])
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
it "should correctly retrieve :allow_nil option from constraint validations table" do
|
|
114
|
-
model_class(:allow_nil=>true).constraint_validations.
|
|
115
|
-
@c.constraint_validation_reflections.
|
|
114
|
+
model_class(:allow_nil=>true).constraint_validations.must_equal [[:validates_presence, :name, {:allow_nil=>true}]]
|
|
115
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:presence, {:allow_nil=>true}]])
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
it "should handle presence validation" do
|
|
119
|
-
model_class(:validation_type=>'presence').constraint_validations.
|
|
120
|
-
@c.constraint_validation_reflections.
|
|
119
|
+
model_class(:validation_type=>'presence').constraint_validations.must_equal [[:validates_presence, :name]]
|
|
120
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
it "should handle exact_length validation" do
|
|
124
|
-
model_class(:validation_type=>'exact_length', :argument=>'5').constraint_validations.
|
|
125
|
-
@c.constraint_validation_reflections.
|
|
124
|
+
model_class(:validation_type=>'exact_length', :argument=>'5').constraint_validations.must_equal [[:validates_exact_length, 5, :name]]
|
|
125
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:exact_length, {:argument=>5}]])
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
it "should handle min_length validation" do
|
|
129
|
-
model_class(:validation_type=>'min_length', :argument=>'5').constraint_validations.
|
|
130
|
-
@c.constraint_validation_reflections.
|
|
129
|
+
model_class(:validation_type=>'min_length', :argument=>'5').constraint_validations.must_equal [[:validates_min_length, 5, :name]]
|
|
130
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:min_length, {:argument=>5}]])
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
it "should handle max_length validation" do
|
|
134
|
-
model_class(:validation_type=>'max_length', :argument=>'5').constraint_validations.
|
|
135
|
-
@c.constraint_validation_reflections.
|
|
134
|
+
model_class(:validation_type=>'max_length', :argument=>'5').constraint_validations.must_equal [[:validates_max_length, 5, :name]]
|
|
135
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:max_length, {:argument=>5}]])
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
it "should handle length_range validation" do
|
|
139
|
-
model_class(:validation_type=>'length_range', :argument=>'3..5').constraint_validations.
|
|
140
|
-
@c.constraint_validation_reflections.
|
|
139
|
+
model_class(:validation_type=>'length_range', :argument=>'3..5').constraint_validations.must_equal [[:validates_length_range, 3..5, :name]]
|
|
140
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:length_range, {:argument=>3..5}]])
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
it "should handle length_range validation with an exclusive end" do
|
|
144
|
-
model_class(:validation_type=>'length_range', :argument=>'3...5').constraint_validations.
|
|
145
|
-
@c.constraint_validation_reflections.
|
|
144
|
+
model_class(:validation_type=>'length_range', :argument=>'3...5').constraint_validations.must_equal [[:validates_length_range, 3...5, :name]]
|
|
145
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:length_range, {:argument=>3...5}]])
|
|
146
146
|
end
|
|
147
147
|
|
|
148
148
|
it "should handle format validation" do
|
|
149
|
-
model_class(:validation_type=>'format', :argument=>'^foo.*').constraint_validations.
|
|
150
|
-
@c.constraint_validation_reflections.
|
|
149
|
+
model_class(:validation_type=>'format', :argument=>'^foo.*').constraint_validations.must_equal [[:validates_format, /^foo.*/, :name]]
|
|
150
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/^foo.*/}]])
|
|
151
151
|
end
|
|
152
152
|
|
|
153
153
|
it "should handle format validation with case insensitive format" do
|
|
154
|
-
model_class(:validation_type=>'iformat', :argument=>'^foo.*').constraint_validations.
|
|
155
|
-
@c.constraint_validation_reflections.
|
|
154
|
+
model_class(:validation_type=>'iformat', :argument=>'^foo.*').constraint_validations.must_equal [[:validates_format, /^foo.*/i, :name]]
|
|
155
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/^foo.*/i}]])
|
|
156
156
|
end
|
|
157
157
|
|
|
158
158
|
it "should handle includes validation with array of strings" do
|
|
159
|
-
model_class(:validation_type=>'includes_str_array', :argument=>'a,b,c').constraint_validations.
|
|
160
|
-
@c.constraint_validation_reflections.
|
|
159
|
+
model_class(:validation_type=>'includes_str_array', :argument=>'a,b,c').constraint_validations.must_equal [[:validates_includes, %w'a b c', :name]]
|
|
160
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:includes, {:argument=>%w'a b c'}]])
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
it "should handle includes validation with array of integers" do
|
|
164
|
-
model_class(:validation_type=>'includes_int_array', :argument=>'1,2,3').constraint_validations.
|
|
165
|
-
@c.constraint_validation_reflections.
|
|
164
|
+
model_class(:validation_type=>'includes_int_array', :argument=>'1,2,3').constraint_validations.must_equal [[:validates_includes, [1, 2, 3], :name]]
|
|
165
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:includes, {:argument=>[1, 2, 3]}]])
|
|
166
166
|
end
|
|
167
167
|
|
|
168
168
|
it "should handle includes validation with inclusive range of integers" do
|
|
169
|
-
model_class(:validation_type=>'includes_int_range', :argument=>'3..5').constraint_validations.
|
|
170
|
-
@c.constraint_validation_reflections.
|
|
169
|
+
model_class(:validation_type=>'includes_int_range', :argument=>'3..5').constraint_validations.must_equal [[:validates_includes, 3..5, :name]]
|
|
170
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:includes, {:argument=>3..5}]])
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
it "should handle includes validation with exclusive range of integers" do
|
|
174
|
-
model_class(:validation_type=>'includes_int_range', :argument=>'3...5').constraint_validations.
|
|
175
|
-
@c.constraint_validation_reflections.
|
|
174
|
+
model_class(:validation_type=>'includes_int_range', :argument=>'3...5').constraint_validations.must_equal [[:validates_includes, 3...5, :name]]
|
|
175
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:includes, {:argument=>3...5}]])
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
it "should handle like validation" do
|
|
179
|
-
model_class(:validation_type=>'like', :argument=>'foo').constraint_validations.
|
|
180
|
-
@c.constraint_validation_reflections.
|
|
179
|
+
model_class(:validation_type=>'like', :argument=>'foo').constraint_validations.must_equal [[:validates_format, /\Afoo\z/, :name]]
|
|
180
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/\Afoo\z/}]])
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
it "should handle ilike validation" do
|
|
184
|
-
model_class(:validation_type=>'ilike', :argument=>'foo').constraint_validations.
|
|
185
|
-
@c.constraint_validation_reflections.
|
|
184
|
+
model_class(:validation_type=>'ilike', :argument=>'foo').constraint_validations.must_equal [[:validates_format, /\Afoo\z/i, :name]]
|
|
185
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/\Afoo\z/i}]])
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
it "should handle like validation with % metacharacter" do
|
|
189
|
-
model_class(:validation_type=>'like', :argument=>'%foo%').constraint_validations.
|
|
190
|
-
@c.constraint_validation_reflections.
|
|
189
|
+
model_class(:validation_type=>'like', :argument=>'%foo%').constraint_validations.must_equal [[:validates_format, /\A.*foo.*\z/, :name]]
|
|
190
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/\A.*foo.*\z/}]])
|
|
191
191
|
end
|
|
192
192
|
|
|
193
193
|
it "should handle like validation with %% metacharacter" do
|
|
194
|
-
model_class(:validation_type=>'like', :argument=>'%%foo%%').constraint_validations.
|
|
195
|
-
@c.constraint_validation_reflections.
|
|
194
|
+
model_class(:validation_type=>'like', :argument=>'%%foo%%').constraint_validations.must_equal [[:validates_format, /\A%foo%\z/, :name]]
|
|
195
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/\A%foo%\z/}]])
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
it "should handle like validation with _ metacharacter" do
|
|
199
|
-
model_class(:validation_type=>'like', :argument=>'f_o').constraint_validations.
|
|
200
|
-
@c.constraint_validation_reflections.
|
|
199
|
+
model_class(:validation_type=>'like', :argument=>'f_o').constraint_validations.must_equal [[:validates_format, /\Af.o\z/, :name]]
|
|
200
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/\Af.o\z/}]])
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
it "should handle like validation with Regexp metacharacter" do
|
|
204
|
-
model_class(:validation_type=>'like', :argument=>'\wfoo\d').constraint_validations.
|
|
205
|
-
@c.constraint_validation_reflections.
|
|
204
|
+
model_class(:validation_type=>'like', :argument=>'\wfoo\d').constraint_validations.must_equal [[:validates_format, /\A\\wfoo\\d\z/, :name]]
|
|
205
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:format, {:argument=>/\A\\wfoo\\d\z/}]])
|
|
206
206
|
end
|
|
207
207
|
|
|
208
208
|
it "should handle unique validation" do
|
|
209
|
-
model_class(:validation_type=>'unique').constraint_validations.
|
|
210
|
-
@c.constraint_validation_reflections.
|
|
209
|
+
model_class(:validation_type=>'unique').constraint_validations.must_equal [[:validates_unique, [:name]]]
|
|
210
|
+
@c.constraint_validation_reflections.must_equal(:name=>[[:unique, {}]])
|
|
211
211
|
end
|
|
212
212
|
|
|
213
213
|
it "should handle unique validation with multiple columns" do
|
|
214
|
-
model_class(:validation_type=>'unique', :column=>'name,id').constraint_validations.
|
|
215
|
-
@c.constraint_validation_reflections.
|
|
214
|
+
model_class(:validation_type=>'unique', :column=>'name,id').constraint_validations.must_equal [[:validates_unique, [:name, :id]]]
|
|
215
|
+
@c.constraint_validation_reflections.must_equal([:name, :id]=>[[:unique, {}]])
|
|
216
216
|
end
|
|
217
217
|
|
|
218
218
|
it "should handle :validation_options" do
|
|
219
219
|
c = model_class(:validation_type=>'unique', :column=>'name')
|
|
220
220
|
c.plugin :constraint_validations, :validation_options=>{:unique=>{:message=>'is bad'}}
|
|
221
|
-
c.constraint_validations.
|
|
222
|
-
c.constraint_validation_reflections.
|
|
221
|
+
c.constraint_validations.must_equal [[:validates_unique, [:name], {:message=>'is bad'}]]
|
|
222
|
+
c.constraint_validation_reflections.must_equal(:name=>[[:unique, {:message=>'is bad'}]])
|
|
223
223
|
c.dataset._fetch = {:count=>1}
|
|
224
224
|
o = c.new(:name=>'a')
|
|
225
|
-
o.valid?.
|
|
226
|
-
o.errors.full_messages.
|
|
225
|
+
o.valid?.must_equal false
|
|
226
|
+
o.errors.full_messages.must_equal ['name is bad']
|
|
227
227
|
end
|
|
228
228
|
|
|
229
229
|
it "should handle :validation_options merging with constraint validation options" do
|
|
230
230
|
c = model_class(:validation_type=>'unique', :column=>'name', :allow_nil=>true)
|
|
231
231
|
c.plugin :constraint_validations, :validation_options=>{:unique=>{:message=>'is bad'}}
|
|
232
|
-
c.constraint_validations.
|
|
233
|
-
c.constraint_validation_reflections.
|
|
232
|
+
c.constraint_validations.must_equal [[:validates_unique, [:name], {:message=>'is bad', :allow_nil=>true}]]
|
|
233
|
+
c.constraint_validation_reflections.must_equal(:name=>[[:unique, {:message=>'is bad', :allow_nil=>true}]])
|
|
234
234
|
c.dataset._fetch = {:count=>1}
|
|
235
235
|
o = c.new(:name=>'a')
|
|
236
|
-
o.valid?.
|
|
237
|
-
o.errors.full_messages.
|
|
236
|
+
o.valid?.must_equal false
|
|
237
|
+
o.errors.full_messages.must_equal ['name is bad']
|
|
238
238
|
end
|
|
239
239
|
|
|
240
240
|
it "should handle :validation_options merging with subclasses" do
|
|
@@ -242,33 +242,33 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
242
242
|
c.plugin :constraint_validations, :validation_options=>{:unique=>{:message=>'is bad', :allow_nil=>true}}
|
|
243
243
|
sc = Class.new(c)
|
|
244
244
|
sc.plugin :constraint_validations, :validation_options=>{:unique=>{:allow_missing=>true, :allow_nil=>false}}
|
|
245
|
-
sc.constraint_validations.
|
|
246
|
-
sc.constraint_validation_reflections.
|
|
245
|
+
sc.constraint_validations.must_equal [[:validates_unique, [:name], {:message=>'is bad', :allow_missing=>true, :allow_nil=>false}]]
|
|
246
|
+
sc.constraint_validation_reflections.must_equal(:name=>[[:unique, {:message=>'is bad', :allow_missing=>true, :allow_nil=>false}]])
|
|
247
247
|
sc.dataset._fetch = {:count=>1}
|
|
248
248
|
o = sc.new(:name=>'a')
|
|
249
|
-
o.valid?.
|
|
250
|
-
o.errors.full_messages.
|
|
249
|
+
o.valid?.must_equal false
|
|
250
|
+
o.errors.full_messages.must_equal ['name is bad']
|
|
251
251
|
end
|
|
252
252
|
|
|
253
253
|
it "should used parsed constraint validations when validating" do
|
|
254
254
|
o = model_class.new
|
|
255
|
-
o.valid?.
|
|
256
|
-
o.errors.full_messages.
|
|
255
|
+
o.valid?.must_equal false
|
|
256
|
+
o.errors.full_messages.must_equal ['name is not present']
|
|
257
257
|
end
|
|
258
258
|
|
|
259
259
|
it "should handle a table name specified as SQL::Identifier" do
|
|
260
260
|
set_fetch(:table=>'sch__items')
|
|
261
261
|
c = Class.new(Sequel::Model(@db[Sequel.identifier(:sch__items)]))
|
|
262
262
|
c.plugin :constraint_validations
|
|
263
|
-
c.constraint_validations.
|
|
264
|
-
c.constraint_validation_reflections.
|
|
263
|
+
c.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
264
|
+
c.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
265
265
|
end
|
|
266
266
|
|
|
267
267
|
it "should handle a table name specified as SQL::QualifiedIdentifier" do
|
|
268
268
|
set_fetch(:table=>'sch.items')
|
|
269
269
|
c = Class.new(Sequel::Model(@db[Sequel.qualify(:sch, :items)]))
|
|
270
270
|
c.plugin :constraint_validations
|
|
271
|
-
c.constraint_validations.
|
|
272
|
-
c.constraint_validation_reflections.
|
|
271
|
+
c.constraint_validations.must_equal [[:validates_presence, :name]]
|
|
272
|
+
c.constraint_validation_reflections.must_equal(:name=>[[:presence, {}]])
|
|
273
273
|
end
|
|
274
274
|
end
|