sequel 3.47.0 → 3.48.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 +230 -0
- data/README.rdoc +31 -40
- data/Rakefile +1 -14
- data/doc/active_record.rdoc +29 -29
- data/doc/association_basics.rdoc +4 -13
- data/doc/cheat_sheet.rdoc +8 -6
- data/doc/code_order.rdoc +89 -0
- data/doc/core_extensions.rdoc +3 -3
- data/doc/dataset_basics.rdoc +7 -8
- data/doc/dataset_filtering.rdoc +7 -2
- data/doc/mass_assignment.rdoc +2 -3
- data/doc/migration.rdoc +8 -8
- data/doc/model_hooks.rdoc +11 -7
- data/doc/object_model.rdoc +2 -2
- data/doc/opening_databases.rdoc +5 -14
- data/doc/prepared_statements.rdoc +5 -9
- data/doc/querying.rdoc +23 -28
- data/doc/reflection.rdoc +11 -0
- data/doc/release_notes/3.48.0.txt +477 -0
- data/doc/schema_modification.rdoc +12 -5
- data/doc/security.rdoc +2 -2
- data/doc/sharding.rdoc +1 -2
- data/doc/sql.rdoc +10 -13
- data/doc/testing.rdoc +8 -4
- data/doc/transactions.rdoc +2 -2
- data/doc/validations.rdoc +40 -17
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +25 -20
- data/lib/sequel/adapters/ado/access.rb +1 -0
- data/lib/sequel/adapters/ado/mssql.rb +1 -0
- data/lib/sequel/adapters/db2.rb +9 -7
- data/lib/sequel/adapters/dbi.rb +16 -16
- data/lib/sequel/adapters/do.rb +17 -18
- data/lib/sequel/adapters/do/mysql.rb +1 -0
- data/lib/sequel/adapters/do/postgres.rb +2 -0
- data/lib/sequel/adapters/do/sqlite.rb +1 -0
- data/lib/sequel/adapters/firebird.rb +5 -7
- data/lib/sequel/adapters/ibmdb.rb +23 -20
- data/lib/sequel/adapters/informix.rb +8 -2
- data/lib/sequel/adapters/jdbc.rb +39 -35
- data/lib/sequel/adapters/jdbc/as400.rb +1 -0
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
- data/lib/sequel/adapters/jdbc/db2.rb +1 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
- data/lib/sequel/adapters/jdbc/h2.rb +1 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
- data/lib/sequel/adapters/jdbc/informix.rb +1 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
- data/lib/sequel/adapters/jdbc/progress.rb +1 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
- data/lib/sequel/adapters/mock.rb +30 -31
- data/lib/sequel/adapters/mysql.rb +6 -7
- data/lib/sequel/adapters/mysql2.rb +5 -6
- data/lib/sequel/adapters/odbc.rb +22 -20
- data/lib/sequel/adapters/odbc/mssql.rb +1 -0
- data/lib/sequel/adapters/openbase.rb +4 -1
- data/lib/sequel/adapters/oracle.rb +10 -8
- data/lib/sequel/adapters/postgres.rb +12 -10
- data/lib/sequel/adapters/shared/access.rb +6 -0
- data/lib/sequel/adapters/shared/cubrid.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +2 -0
- data/lib/sequel/adapters/shared/firebird.rb +2 -0
- data/lib/sequel/adapters/shared/informix.rb +2 -0
- data/lib/sequel/adapters/shared/mssql.rb +14 -8
- data/lib/sequel/adapters/shared/mysql.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +2 -0
- data/lib/sequel/adapters/shared/postgres.rb +14 -4
- data/lib/sequel/adapters/shared/progress.rb +1 -0
- data/lib/sequel/adapters/shared/sqlite.rb +4 -3
- data/lib/sequel/adapters/sqlite.rb +6 -7
- data/lib/sequel/adapters/swift.rb +20 -21
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +2 -0
- data/lib/sequel/adapters/swift/sqlite.rb +1 -0
- data/lib/sequel/adapters/tinytds.rb +5 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +57 -50
- data/lib/sequel/database/connecting.rb +9 -10
- data/lib/sequel/database/dataset.rb +11 -6
- data/lib/sequel/database/dataset_defaults.rb +61 -69
- data/lib/sequel/database/features.rb +21 -0
- data/lib/sequel/database/misc.rb +23 -3
- data/lib/sequel/database/query.rb +13 -7
- data/lib/sequel/database/schema_methods.rb +6 -6
- data/lib/sequel/database/transactions.rb +1 -0
- data/lib/sequel/dataset/actions.rb +51 -38
- data/lib/sequel/dataset/features.rb +1 -0
- data/lib/sequel/dataset/graph.rb +9 -33
- data/lib/sequel/dataset/misc.rb +30 -5
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +91 -27
- data/lib/sequel/dataset/sql.rb +40 -6
- data/lib/sequel/deprecated.rb +74 -0
- data/lib/sequel/deprecated_core_extensions.rb +135 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -5
- data/lib/sequel/extensions/core_extensions.rb +10 -3
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
- data/lib/sequel/extensions/filter_having.rb +58 -0
- data/lib/sequel/extensions/graph_each.rb +63 -0
- data/lib/sequel/extensions/hash_aliases.rb +44 -0
- data/lib/sequel/extensions/looser_typecasting.rb +14 -3
- data/lib/sequel/extensions/migration.rb +2 -3
- data/lib/sequel/extensions/named_timezones.rb +14 -1
- data/lib/sequel/extensions/null_dataset.rb +7 -1
- data/lib/sequel/extensions/pagination.rb +15 -5
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
- data/lib/sequel/extensions/pg_json.rb +7 -7
- data/lib/sequel/extensions/pg_range_ops.rb +8 -2
- data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
- data/lib/sequel/extensions/pretty_table.rb +13 -4
- data/lib/sequel/extensions/query.rb +21 -4
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
- data/lib/sequel/extensions/schema_caching.rb +10 -7
- data/lib/sequel/extensions/schema_dumper.rb +35 -48
- data/lib/sequel/extensions/select_remove.rb +13 -4
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
- data/lib/sequel/extensions/set_overrides.rb +43 -0
- data/lib/sequel/extensions/to_dot.rb +6 -0
- data/lib/sequel/model.rb +12 -6
- data/lib/sequel/model/associations.rb +80 -38
- data/lib/sequel/model/base.rb +137 -52
- data/lib/sequel/model/errors.rb +7 -2
- data/lib/sequel/plugins/active_model.rb +13 -0
- data/lib/sequel/plugins/after_initialize.rb +43 -0
- data/lib/sequel/plugins/association_proxies.rb +63 -7
- data/lib/sequel/plugins/auto_validations.rb +56 -16
- data/lib/sequel/plugins/blacklist_security.rb +63 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
- data/lib/sequel/plugins/constraint_validations.rb +50 -8
- data/lib/sequel/plugins/dataset_associations.rb +2 -0
- data/lib/sequel/plugins/hook_class_methods.rb +7 -1
- data/lib/sequel/plugins/identity_map.rb +4 -0
- data/lib/sequel/plugins/json_serializer.rb +32 -13
- data/lib/sequel/plugins/optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/scissors.rb +33 -0
- data/lib/sequel/plugins/serialization.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
- data/lib/sequel/plugins/tree.rb +5 -1
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +15 -11
- data/lib/sequel/plugins/xml_serializer.rb +12 -3
- data/lib/sequel/sql.rb +12 -2
- data/lib/sequel/timezones.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/mssql_spec.rb +24 -57
- data/spec/adapters/postgres_spec.rb +27 -55
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/bin_spec.rb +251 -0
- data/spec/core/database_spec.rb +46 -32
- data/spec/core/dataset_spec.rb +233 -181
- data/spec/core/deprecated_spec.rb +78 -0
- data/spec/core/expression_filters_spec.rb +3 -4
- data/spec/core/mock_adapter_spec.rb +9 -9
- data/spec/core/object_graph_spec.rb +9 -19
- data/spec/core/schema_spec.rb +3 -1
- data/spec/core/spec_helper.rb +19 -0
- data/spec/core_extensions_spec.rb +80 -30
- data/spec/extensions/after_initialize_spec.rb +24 -0
- data/spec/extensions/association_proxies_spec.rb +37 -1
- data/spec/extensions/auto_validations_spec.rb +20 -4
- data/spec/extensions/blacklist_security_spec.rb +87 -0
- data/spec/extensions/boolean_readers_spec.rb +2 -1
- data/spec/extensions/class_table_inheritance_spec.rb +7 -0
- data/spec/extensions/columns_introspection_spec.rb +3 -3
- data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
- data/spec/extensions/core_refinements_spec.rb +7 -7
- data/spec/extensions/dataset_associations_spec.rb +2 -2
- data/spec/extensions/date_arithmetic_spec.rb +1 -1
- data/spec/extensions/defaults_setter_spec.rb +2 -1
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
- data/spec/extensions/filter_having_spec.rb +40 -0
- data/spec/extensions/graph_each_spec.rb +109 -0
- data/spec/extensions/hash_aliases_spec.rb +16 -0
- data/spec/extensions/hook_class_methods_spec.rb +2 -2
- data/spec/extensions/identity_map_spec.rb +3 -3
- data/spec/extensions/json_serializer_spec.rb +19 -19
- data/spec/extensions/lazy_attributes_spec.rb +1 -0
- data/spec/extensions/list_spec.rb +13 -13
- data/spec/extensions/looser_typecasting_spec.rb +10 -3
- data/spec/extensions/many_through_many_spec.rb +1 -1
- data/spec/extensions/migration_spec.rb +7 -7
- data/spec/extensions/named_timezones_spec.rb +6 -0
- data/spec/extensions/nested_attributes_spec.rb +2 -2
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
- data/spec/extensions/pg_range_ops_spec.rb +4 -2
- data/spec/extensions/pg_row_plugin_spec.rb +1 -1
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_caching_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +27 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/scissors_spec.rb +26 -0
- data/spec/extensions/select_remove_spec.rb +1 -1
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
- data/spec/extensions/set_overrides_spec.rb +45 -0
- data/spec/extensions/single_table_inheritance_spec.rb +10 -0
- data/spec/extensions/spec_helper.rb +24 -1
- data/spec/extensions/static_cache_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +2 -1
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +3 -2
- data/spec/extensions/update_primary_key_spec.rb +2 -2
- data/spec/extensions/validation_class_methods_spec.rb +19 -19
- data/spec/extensions/validation_helpers_spec.rb +30 -21
- data/spec/extensions/xml_serializer_spec.rb +5 -5
- data/spec/integration/associations_test.rb +10 -30
- data/spec/integration/dataset_test.rb +20 -24
- data/spec/integration/eager_loader_test.rb +5 -5
- data/spec/integration/model_test.rb +3 -3
- data/spec/integration/plugin_test.rb +7 -39
- data/spec/integration/schema_test.rb +4 -38
- data/spec/integration/spec_helper.rb +2 -1
- data/spec/model/association_reflection_spec.rb +70 -5
- data/spec/model/associations_spec.rb +11 -11
- data/spec/model/base_spec.rb +25 -8
- data/spec/model/class_dataset_methods_spec.rb +143 -0
- data/spec/model/dataset_methods_spec.rb +1 -1
- data/spec/model/eager_loading_spec.rb +25 -25
- data/spec/model/hooks_spec.rb +1 -1
- data/spec/model/model_spec.rb +22 -7
- data/spec/model/plugins_spec.rb +1 -6
- data/spec/model/record_spec.rb +37 -29
- data/spec/model/spec_helper.rb +23 -1
- data/spec/model/validations_spec.rb +15 -17
- metadata +32 -3
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::AfterInitialize" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock(:host=>'mysql', :numrows=>1)
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:test]))
|
|
7
|
+
@c.class_eval do
|
|
8
|
+
columns :id, :name
|
|
9
|
+
plugin :after_initialize
|
|
10
|
+
def after_initialize
|
|
11
|
+
self.name *= 2
|
|
12
|
+
self.id *= 3 if id
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should have after_initialize hook be called for new objects" do
|
|
18
|
+
@c.new(:name=>'foo').values.should == {:name=>'foofoo'}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should have after_initialize hook be called for objects loaded from the database" do
|
|
22
|
+
@c.call(:id=>1, :name=>'foo').values.should == {:id=>3, :name=>'foofoo'}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -6,7 +6,7 @@ describe "Sequel::Plugins::AssociationProxies" do
|
|
|
6
6
|
end
|
|
7
7
|
class ::Item < Sequel::Model
|
|
8
8
|
plugin :association_proxies
|
|
9
|
-
many_to_many :tags
|
|
9
|
+
many_to_many :tags, :extend=>Module.new{def size; count end}
|
|
10
10
|
end
|
|
11
11
|
@i = Item.load(:id=>1)
|
|
12
12
|
@t = @i.tags
|
|
@@ -29,6 +29,33 @@ describe "Sequel::Plugins::AssociationProxies" do
|
|
|
29
29
|
@i.associations.has_key?(:tags).should == false
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
it "should accept block to plugin to specify which methods to proxy to dataset" do
|
|
33
|
+
Item.plugin :association_proxies do |opts|
|
|
34
|
+
opts[:method] == :where || opts[:arguments].length == 2 || opts[:block]
|
|
35
|
+
end
|
|
36
|
+
@i.associations.has_key?(:tags).should == false
|
|
37
|
+
@t.where(:a=>1).sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
|
|
38
|
+
@t.filter('a = ?', 1).sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
|
|
39
|
+
@t.filter{{:a=>1}}.sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
|
|
40
|
+
|
|
41
|
+
@i.associations.has_key?(:tags).should == false
|
|
42
|
+
Item.plugin :association_proxies do |opts|
|
|
43
|
+
proxy_arg = opts[:proxy_argument]
|
|
44
|
+
proxy_block = opts[:proxy_block]
|
|
45
|
+
cached = opts[:instance].associations[opts[:reflection][:name]]
|
|
46
|
+
is_size = opts[:method] == :size
|
|
47
|
+
is_size && !cached && !proxy_arg && !proxy_block
|
|
48
|
+
end
|
|
49
|
+
@t.size.should == 1
|
|
50
|
+
Item.db.sqls.should == ["SELECT count(*) AS count FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) LIMIT 1"]
|
|
51
|
+
@i.tags{|ds| ds}.size.should == 1
|
|
52
|
+
Item.db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1))"]
|
|
53
|
+
@i.tags(true).size.should == 1
|
|
54
|
+
Item.db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1))"]
|
|
55
|
+
@t.size.should == 1
|
|
56
|
+
Item.db.sqls.should == []
|
|
57
|
+
end
|
|
58
|
+
|
|
32
59
|
it "should reload the cached association if sent an array method and the reload flag was given" do
|
|
33
60
|
@t.select{|x| false}.should == []
|
|
34
61
|
Item.db.sqls.length.should == 1
|
|
@@ -47,4 +74,13 @@ describe "Sequel::Plugins::AssociationProxies" do
|
|
|
47
74
|
Tag.one_to_one :item
|
|
48
75
|
proc{Tag.load(:id=>1, :item_id=>2).item.filter(:a=>1)}.should raise_error(NoMethodError)
|
|
49
76
|
end
|
|
77
|
+
|
|
78
|
+
it "should work correctly in subclasses" do
|
|
79
|
+
i = Class.new(Item).load(:id=>1)
|
|
80
|
+
i.associations.has_key?(:tags).should == false
|
|
81
|
+
i.tags.select{|x| false}.should == []
|
|
82
|
+
i.associations.has_key?(:tags).should == true
|
|
83
|
+
i.tags.filter(:a=>1).sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
|
|
84
|
+
end
|
|
85
|
+
|
|
50
86
|
end
|
|
@@ -7,17 +7,19 @@ describe "Sequel::Plugins::AutoValidations" do
|
|
|
7
7
|
def db.schema(t, *)
|
|
8
8
|
t = t.first_source if t.is_a?(Sequel::Dataset)
|
|
9
9
|
return [] if t != :test
|
|
10
|
-
[[:id, {:primary_key=>true, :type=>:integer}],
|
|
10
|
+
[[:id, {:primary_key=>true, :type=>:integer, :allow_null=>false}],
|
|
11
11
|
[:name, {:primary_key=>false, :type=>:string, :allow_null=>false}],
|
|
12
12
|
[:num, {:primary_key=>false, :type=>:integer, :allow_null=>true}],
|
|
13
|
-
[:d, {:primary_key=>false, :type=>:date, :allow_null=>false}]
|
|
13
|
+
[:d, {:primary_key=>false, :type=>:date, :allow_null=>false}],
|
|
14
|
+
[:nnd, {:primary_key=>false, :type=>:string, :allow_null=>false, :ruby_default=>'nnd'}]]
|
|
14
15
|
end
|
|
16
|
+
def db.supports_index_parsing?() true end
|
|
15
17
|
def db.indexes(t, *)
|
|
16
18
|
return [] if t != :test
|
|
17
19
|
{:a=>{:columns=>[:name, :num], :unique=>true}, :b=>{:columns=>[:num], :unique=>false}}
|
|
18
20
|
end
|
|
19
21
|
@c = Class.new(Sequel::Model(db[:test]))
|
|
20
|
-
@c.send(:def_column_accessor, :id, :name, :num, :d)
|
|
22
|
+
@c.send(:def_column_accessor, :id, :name, :num, :d, :nnd)
|
|
21
23
|
@c.raise_on_typecast_failure = false
|
|
22
24
|
@c.plugin :auto_validations
|
|
23
25
|
@m = @c.new
|
|
@@ -41,10 +43,24 @@ describe "Sequel::Plugins::AutoValidations" do
|
|
|
41
43
|
@m.errors.should == {[:name, :num]=>["is already taken"]}
|
|
42
44
|
end
|
|
43
45
|
|
|
46
|
+
it "should support :not_null=>:presence option" do
|
|
47
|
+
@c.plugin :auto_validations, :not_null=>:presence
|
|
48
|
+
@m.set(:d=>Date.today, :num=>'')
|
|
49
|
+
@m.valid?.should be_false
|
|
50
|
+
@m.errors.should == {:name=>["is not present"]}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should automatically validate explicit nil values for columns with not nil defaults" do
|
|
54
|
+
@m.set(:d=>Date.today, :name=>1, :nnd=>nil)
|
|
55
|
+
@m.id = nil
|
|
56
|
+
@m.valid?.should be_false
|
|
57
|
+
@m.errors.should == {:id=>["is not present"], :nnd=>["is not present"]}
|
|
58
|
+
end
|
|
59
|
+
|
|
44
60
|
it "should allow skipping validations by type" do
|
|
45
61
|
@c = Class.new(@c)
|
|
46
62
|
@m = @c.new
|
|
47
|
-
@c.skip_auto_validations(:
|
|
63
|
+
@c.skip_auto_validations(:not_null)
|
|
48
64
|
@m.valid?.should be_true
|
|
49
65
|
|
|
50
66
|
@m.set(:d=>'/', :num=>'a', :name=>'1')
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe Sequel::Model, "#(set|update)_except" do
|
|
4
|
+
before do
|
|
5
|
+
@c = Class.new(Sequel::Model(:items))
|
|
6
|
+
@c.class_eval do
|
|
7
|
+
plugin :blacklist_security
|
|
8
|
+
set_primary_key :id
|
|
9
|
+
columns :x, :y, :z, :id
|
|
10
|
+
set_restricted_columns :y
|
|
11
|
+
end
|
|
12
|
+
@c.strict_param_setting = false
|
|
13
|
+
@o1 = @c.new
|
|
14
|
+
MODEL_DB.reset
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should raise errors if not all hash fields can be set and strict_param_setting is true" do
|
|
18
|
+
@c.strict_param_setting = true
|
|
19
|
+
proc{@c.new.set_except({:x => 1, :y => 2, :z=>3, :id=>4}, :x, :y)}.should raise_error(Sequel::Error)
|
|
20
|
+
proc{@c.new.set_except({:x => 1, :y => 2, :z=>3}, :x, :y)}.should raise_error(Sequel::Error)
|
|
21
|
+
(o = @c.new).set_except({:z => 3}, :x, :y)
|
|
22
|
+
o.values.should == {:z=>3}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "#set_except should not set given attributes or the primary key" do
|
|
26
|
+
@o1.set_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
|
|
27
|
+
@o1.values.should == {:x => 1}
|
|
28
|
+
@o1.set_except({:x => 4, :y => 2, :z=>3, :id=>4}, :y, :z)
|
|
29
|
+
@o1.values.should == {:x => 4}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "#update_except should not update given attributes" do
|
|
33
|
+
@o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
|
|
34
|
+
MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
35
|
+
@c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
|
|
36
|
+
MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe Sequel::Model, ".restricted_columns " do
|
|
41
|
+
before do
|
|
42
|
+
@c = Class.new(Sequel::Model(:blahblah))
|
|
43
|
+
@c.class_eval do
|
|
44
|
+
plugin :blacklist_security
|
|
45
|
+
columns :x, :y, :z
|
|
46
|
+
end
|
|
47
|
+
@c.strict_param_setting = false
|
|
48
|
+
@c.instance_variable_set(:@columns, [:x, :y, :z])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should set the restricted columns correctly" do
|
|
52
|
+
@c.restricted_columns.should == nil
|
|
53
|
+
@c.set_restricted_columns :x
|
|
54
|
+
@c.restricted_columns.should == [:x]
|
|
55
|
+
@c.set_restricted_columns :x, :y
|
|
56
|
+
@c.restricted_columns.should == [:x, :y]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should not set restricted columns by default" do
|
|
60
|
+
@c.set_restricted_columns :z
|
|
61
|
+
i = @c.new(:x => 1, :y => 2, :z => 3)
|
|
62
|
+
i.values.should == {:x => 1, :y => 2}
|
|
63
|
+
i.set(:x => 4, :y => 5, :z => 6)
|
|
64
|
+
i.values.should == {:x => 4, :y => 5}
|
|
65
|
+
|
|
66
|
+
@c.instance_dataset._fetch = @c.dataset._fetch = {:x => 7}
|
|
67
|
+
i = @c.new
|
|
68
|
+
i.update(:x => 7, :z => 9)
|
|
69
|
+
i.values.should == {:x => 7}
|
|
70
|
+
MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should have allowed take precedence over restricted" do
|
|
74
|
+
@c.set_allowed_columns :x, :y
|
|
75
|
+
@c.set_restricted_columns :y, :z
|
|
76
|
+
i = @c.new(:x => 1, :y => 2, :z => 3)
|
|
77
|
+
i.values.should == {:x => 1, :y => 2}
|
|
78
|
+
i.set(:x => 4, :y => 5, :z => 6)
|
|
79
|
+
i.values.should == {:x => 4, :y => 5}
|
|
80
|
+
|
|
81
|
+
@c.instance_dataset._fetch = @c.dataset._fetch = {:y => 7}
|
|
82
|
+
i = @c.new
|
|
83
|
+
i.update(:y => 7, :z => 9)
|
|
84
|
+
i.values.should == {:y => 7}
|
|
85
|
+
MODEL_DB.sqls.should == ["INSERT INTO blahblah (y) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -2,7 +2,8 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe Sequel::Model, "BooleanReaders plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@db = Sequel::Database.new
|
|
5
|
+
@db = Sequel::Database.new
|
|
6
|
+
def @db.supports_schema_parsing?() true end
|
|
6
7
|
def @db.schema(*args)
|
|
7
8
|
[[:id, {}], [:z, {:type=>:integer, :db_type=>'tinyint(1)'}], [:b, {:type=>:boolean, :db_type=>'boolean'}]]
|
|
8
9
|
end
|
|
@@ -3,6 +3,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
3
3
|
describe "class_table_inheritance plugin" do
|
|
4
4
|
before do
|
|
5
5
|
@db = Sequel.mock(:autoid=>proc{|sql| 1})
|
|
6
|
+
def @db.supports_schema_parsing?() true end
|
|
6
7
|
def @db.schema(table, opts={})
|
|
7
8
|
{:employees=>[[:id, {:primary_key=>true, :type=>:integer}], [:name, {:type=>:string}], [:kind, {:type=>:string}]],
|
|
8
9
|
:managers=>[[:id, {:type=>:integer}], [:num_staff, {:type=>:integer}]],
|
|
@@ -54,6 +55,12 @@ describe "class_table_inheritance plugin" do
|
|
|
54
55
|
Staff.simple_table.should == nil
|
|
55
56
|
end
|
|
56
57
|
|
|
58
|
+
specify "should have working row_proc if using set_dataset in subclass to remove columns" do
|
|
59
|
+
Manager.set_dataset(Manager.dataset.select(*(Manager.columns - [:blah])))
|
|
60
|
+
Manager.dataset._fetch = {:id=>1, :kind=>'Executive'}
|
|
61
|
+
Manager[1].should == Executive.load(:id=>1, :kind=>'Executive')
|
|
62
|
+
end
|
|
63
|
+
|
|
57
64
|
specify "should use a joined dataset in subclasses" do
|
|
58
65
|
Employee.dataset.sql.should == 'SELECT * FROM employees'
|
|
59
66
|
Manager.dataset.sql.should == 'SELECT * FROM employees INNER JOIN managers USING (id)'
|
|
@@ -8,8 +8,6 @@ describe "Sequel::Dataset.introspect_all_columns" do
|
|
|
8
8
|
# Handle case where introspect_all_columns has already been called
|
|
9
9
|
alias columns columns_without_introspection unless instance_methods(false).map{|x| x.to_s}.include?('columns')
|
|
10
10
|
end
|
|
11
|
-
Sequel::Dataset.introspect_all_columns
|
|
12
|
-
@db.reset
|
|
13
11
|
end
|
|
14
12
|
after do
|
|
15
13
|
class Sequel::Dataset
|
|
@@ -17,7 +15,9 @@ describe "Sequel::Dataset.introspect_all_columns" do
|
|
|
17
15
|
end
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
qspecify "should turn on column introspection by default" do
|
|
19
|
+
Sequel::Dataset.introspect_all_columns
|
|
20
|
+
@db.reset
|
|
21
21
|
@ds.select(:x).columns.should == [:x]
|
|
22
22
|
@db.sqls.length.should == 0
|
|
23
23
|
end
|
|
@@ -20,7 +20,7 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
20
20
|
set_fetch({})
|
|
21
21
|
@ds = @db[:items]
|
|
22
22
|
@ds.instance_variable_set(:@columns, [:name])
|
|
23
|
-
@ds2 =
|
|
23
|
+
@ds2 = Sequel.mock[:items2]
|
|
24
24
|
@ds2.instance_variable_set(:@columns, [:name])
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -31,8 +31,9 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
31
31
|
it "should parse constraint validations when loading plugin" do
|
|
32
32
|
@c = model_class
|
|
33
33
|
@db.sqls.should == ["SELECT * FROM sequel_constraint_validations"]
|
|
34
|
-
@db.constraint_validations.should == {
|
|
34
|
+
@db.constraint_validations.should == {"items"=>[{:allow_nil=>nil, :constraint_name=>nil, :message=>nil, :validation_type=>"presence", :column=>"name", :argument=>nil, :table=>"items"}]}
|
|
35
35
|
@c.constraint_validations.should == [[:validates_presence, :name]]
|
|
36
|
+
@c.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
it "should parse constraint validations with a custom constraint validations table" do
|
|
@@ -40,8 +41,9 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
40
41
|
@db.sqls
|
|
41
42
|
c.plugin :constraint_validations, :constraint_validations_table=>:foo
|
|
42
43
|
@db.sqls.should == ["SELECT * FROM foo"]
|
|
43
|
-
@db.constraint_validations.should == {
|
|
44
|
+
@db.constraint_validations.should == {"items"=>[{:allow_nil=>nil, :constraint_name=>nil, :message=>nil, :validation_type=>"presence", :column=>"name", :argument=>nil, :table=>"items"}]}
|
|
44
45
|
c.constraint_validations.should == [[:validates_presence, :name]]
|
|
46
|
+
c.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
it "should populate constraint_validations when subclassing" do
|
|
@@ -52,6 +54,20 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
52
54
|
sc.set_dataset @ds
|
|
53
55
|
@db.sqls.should == []
|
|
54
56
|
sc.constraint_validations.should == [[:validates_presence, :name]]
|
|
57
|
+
sc.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should handle plugin being loaded in subclass when superclass uses a custom constraint validations table" do
|
|
61
|
+
c = Class.new(Sequel::Model(@db))
|
|
62
|
+
c.plugin :constraint_validations, :constraint_validations_table=>:foo
|
|
63
|
+
@db.sqls.should == ["SELECT * FROM foo"]
|
|
64
|
+
sc = Class.new(c)
|
|
65
|
+
sc.plugin :constraint_validations
|
|
66
|
+
sc.constraint_validations_table.should == :foo
|
|
67
|
+
sc.set_dataset @ds
|
|
68
|
+
@db.sqls.should == []
|
|
69
|
+
sc.constraint_validations.should == [[:validates_presence, :name]]
|
|
70
|
+
sc.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
55
71
|
end
|
|
56
72
|
|
|
57
73
|
it "should populate constraint_validations when changing the model's dataset" do
|
|
@@ -64,114 +80,174 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
64
80
|
sc.set_dataset @ds
|
|
65
81
|
@db.sqls.should == []
|
|
66
82
|
sc.constraint_validations.should == [[:validates_presence, :name]]
|
|
83
|
+
sc.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
67
84
|
end
|
|
68
85
|
|
|
69
86
|
it "should reparse constraint validations when changing the model's database" do
|
|
70
87
|
c = Class.new(Sequel::Model(@ds2))
|
|
71
88
|
c.plugin :constraint_validations
|
|
72
|
-
@db.sqls.should == ["SELECT * FROM sequel_constraint_validations"]
|
|
89
|
+
@ds2.db.sqls.should == ["SELECT * FROM sequel_constraint_validations"]
|
|
73
90
|
sc = Class.new(c)
|
|
74
91
|
sc.set_dataset @ds
|
|
75
92
|
@db.sqls.should == ["SELECT * FROM sequel_constraint_validations"]
|
|
76
93
|
sc.constraint_validations.should == [[:validates_presence, :name]]
|
|
94
|
+
sc.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
77
95
|
end
|
|
78
96
|
|
|
79
97
|
it "should reparse constraint validations when changing the model's database with a custom constraint validations table" do
|
|
80
98
|
c = Class.new(Sequel::Model(@ds2))
|
|
81
99
|
c.plugin :constraint_validations, :constraint_validations_table=>:foo
|
|
82
|
-
@db.sqls.should == ["SELECT * FROM foo"]
|
|
100
|
+
@ds2.db.sqls.should == ["SELECT * FROM foo"]
|
|
83
101
|
sc = Class.new(c)
|
|
84
102
|
sc.set_dataset @ds
|
|
85
103
|
@db.sqls.should == ["SELECT * FROM foo"]
|
|
86
104
|
sc.constraint_validations.should == [[:validates_presence, :name]]
|
|
105
|
+
sc.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
87
106
|
end
|
|
88
107
|
|
|
89
108
|
it "should correctly retrieve :message option from constraint validations table" do
|
|
90
109
|
model_class(:message=>'foo').constraint_validations.should == [[:validates_presence, :name, {:message=>'foo'}]]
|
|
110
|
+
@c.constraint_validation_reflections.should == {:name=>[[:presence, {:message=>'foo'}]]}
|
|
91
111
|
end
|
|
92
112
|
|
|
93
113
|
it "should correctly retrieve :allow_nil option from constraint validations table" do
|
|
94
114
|
model_class(:allow_nil=>true).constraint_validations.should == [[:validates_presence, :name, {:allow_nil=>true}]]
|
|
115
|
+
@c.constraint_validation_reflections.should == {:name=>[[:presence, {:allow_nil=>true}]]}
|
|
95
116
|
end
|
|
96
117
|
|
|
97
118
|
it "should handle presence validation" do
|
|
98
119
|
model_class(:validation_type=>'presence').constraint_validations.should == [[:validates_presence, :name]]
|
|
120
|
+
@c.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
99
121
|
end
|
|
100
122
|
|
|
101
123
|
it "should handle exact_length validation" do
|
|
102
124
|
model_class(:validation_type=>'exact_length', :argument=>'5').constraint_validations.should == [[:validates_exact_length, 5, :name]]
|
|
125
|
+
@c.constraint_validation_reflections.should == {:name=>[[:exact_length, {:argument=>5}]]}
|
|
103
126
|
end
|
|
104
127
|
|
|
105
128
|
it "should handle min_length validation" do
|
|
106
129
|
model_class(:validation_type=>'min_length', :argument=>'5').constraint_validations.should == [[:validates_min_length, 5, :name]]
|
|
130
|
+
@c.constraint_validation_reflections.should == {:name=>[[:min_length, {:argument=>5}]]}
|
|
107
131
|
end
|
|
108
132
|
|
|
109
133
|
it "should handle max_length validation" do
|
|
110
134
|
model_class(:validation_type=>'max_length', :argument=>'5').constraint_validations.should == [[:validates_max_length, 5, :name]]
|
|
135
|
+
@c.constraint_validation_reflections.should == {:name=>[[:max_length, {:argument=>5}]]}
|
|
111
136
|
end
|
|
112
137
|
|
|
113
138
|
it "should handle length_range validation" do
|
|
114
139
|
model_class(:validation_type=>'length_range', :argument=>'3..5').constraint_validations.should == [[:validates_length_range, 3..5, :name]]
|
|
140
|
+
@c.constraint_validation_reflections.should == {:name=>[[:length_range, {:argument=>3..5}]]}
|
|
115
141
|
end
|
|
116
142
|
|
|
117
143
|
it "should handle length_range validation with an exclusive end" do
|
|
118
144
|
model_class(:validation_type=>'length_range', :argument=>'3...5').constraint_validations.should == [[:validates_length_range, 3...5, :name]]
|
|
145
|
+
@c.constraint_validation_reflections.should == {:name=>[[:length_range, {:argument=>3...5}]]}
|
|
119
146
|
end
|
|
120
147
|
|
|
121
148
|
it "should handle format validation" do
|
|
122
149
|
model_class(:validation_type=>'format', :argument=>'^foo.*').constraint_validations.should == [[:validates_format, /^foo.*/, :name]]
|
|
150
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/^foo.*/}]]}
|
|
123
151
|
end
|
|
124
152
|
|
|
125
153
|
it "should handle format validation with case insensitive format" do
|
|
126
154
|
model_class(:validation_type=>'iformat', :argument=>'^foo.*').constraint_validations.should == [[:validates_format, /^foo.*/i, :name]]
|
|
155
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/^foo.*/i}]]}
|
|
127
156
|
end
|
|
128
157
|
|
|
129
158
|
it "should handle includes validation with array of strings" do
|
|
130
159
|
model_class(:validation_type=>'includes_str_array', :argument=>'a,b,c').constraint_validations.should == [[:validates_includes, %w'a b c', :name]]
|
|
160
|
+
@c.constraint_validation_reflections.should == {:name=>[[:includes, {:argument=>%w'a b c'}]]}
|
|
131
161
|
end
|
|
132
162
|
|
|
133
163
|
it "should handle includes validation with array of integers" do
|
|
134
164
|
model_class(:validation_type=>'includes_int_array', :argument=>'1,2,3').constraint_validations.should == [[:validates_includes, [1, 2, 3], :name]]
|
|
165
|
+
@c.constraint_validation_reflections.should == {:name=>[[:includes, {:argument=>[1, 2, 3]}]]}
|
|
135
166
|
end
|
|
136
167
|
|
|
137
168
|
it "should handle includes validation with inclusive range of integers" do
|
|
138
169
|
model_class(:validation_type=>'includes_int_range', :argument=>'3..5').constraint_validations.should == [[:validates_includes, 3..5, :name]]
|
|
170
|
+
@c.constraint_validation_reflections.should == {:name=>[[:includes, {:argument=>3..5}]]}
|
|
139
171
|
end
|
|
140
172
|
|
|
141
173
|
it "should handle includes validation with exclusive range of integers" do
|
|
142
174
|
model_class(:validation_type=>'includes_int_range', :argument=>'3...5').constraint_validations.should == [[:validates_includes, 3...5, :name]]
|
|
175
|
+
@c.constraint_validation_reflections.should == {:name=>[[:includes, {:argument=>3...5}]]}
|
|
143
176
|
end
|
|
144
177
|
|
|
145
178
|
it "should handle like validation" do
|
|
146
179
|
model_class(:validation_type=>'like', :argument=>'foo').constraint_validations.should == [[:validates_format, /\Afoo\z/, :name]]
|
|
180
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/\Afoo\z/}]]}
|
|
147
181
|
end
|
|
148
182
|
|
|
149
183
|
it "should handle ilike validation" do
|
|
150
184
|
model_class(:validation_type=>'ilike', :argument=>'foo').constraint_validations.should == [[:validates_format, /\Afoo\z/i, :name]]
|
|
185
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/\Afoo\z/i}]]}
|
|
151
186
|
end
|
|
152
187
|
|
|
153
188
|
it "should handle like validation with % metacharacter" do
|
|
154
189
|
model_class(:validation_type=>'like', :argument=>'%foo%').constraint_validations.should == [[:validates_format, /\A.*foo.*\z/, :name]]
|
|
190
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/\A.*foo.*\z/}]]}
|
|
155
191
|
end
|
|
156
192
|
|
|
157
193
|
it "should handle like validation with %% metacharacter" do
|
|
158
194
|
model_class(:validation_type=>'like', :argument=>'%%foo%%').constraint_validations.should == [[:validates_format, /\A%foo%\z/, :name]]
|
|
195
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/\A%foo%\z/}]]}
|
|
159
196
|
end
|
|
160
197
|
|
|
161
198
|
it "should handle like validation with _ metacharacter" do
|
|
162
199
|
model_class(:validation_type=>'like', :argument=>'f_o').constraint_validations.should == [[:validates_format, /\Af.o\z/, :name]]
|
|
200
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/\Af.o\z/}]]}
|
|
163
201
|
end
|
|
164
202
|
|
|
165
203
|
it "should handle like validation with Regexp metacharacter" do
|
|
166
204
|
model_class(:validation_type=>'like', :argument=>'\wfoo\d').constraint_validations.should == [[:validates_format, /\A\\wfoo\\d\z/, :name]]
|
|
205
|
+
@c.constraint_validation_reflections.should == {:name=>[[:format, {:argument=>/\A\\wfoo\\d\z/}]]}
|
|
167
206
|
end
|
|
168
207
|
|
|
169
208
|
it "should handle unique validation" do
|
|
170
209
|
model_class(:validation_type=>'unique').constraint_validations.should == [[:validates_unique, [:name]]]
|
|
210
|
+
@c.constraint_validation_reflections.should == {:name=>[[:unique, {}]]}
|
|
171
211
|
end
|
|
172
212
|
|
|
173
213
|
it "should handle unique validation with multiple columns" do
|
|
174
214
|
model_class(:validation_type=>'unique', :column=>'name,id').constraint_validations.should == [[:validates_unique, [:name, :id]]]
|
|
215
|
+
@c.constraint_validation_reflections.should == {[:name, :id]=>[[:unique, {}]]}
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it "should handle :validation_options" do
|
|
219
|
+
c = model_class(:validation_type=>'unique', :column=>'name')
|
|
220
|
+
c.plugin :constraint_validations, :validation_options=>{:unique=>{:message=>'is bad'}}
|
|
221
|
+
c.constraint_validations.should == [[:validates_unique, [:name], {:message=>'is bad'}]]
|
|
222
|
+
c.constraint_validation_reflections.should == {:name=>[[:unique, {:message=>'is bad'}]]}
|
|
223
|
+
c.dataset._fetch = {:count=>1}
|
|
224
|
+
o = c.new(:name=>'a')
|
|
225
|
+
o.valid?.should == false
|
|
226
|
+
o.errors.full_messages.should == ['name is bad']
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "should handle :validation_options merging with constraint validation options" do
|
|
230
|
+
c = model_class(:validation_type=>'unique', :column=>'name', :allow_nil=>true)
|
|
231
|
+
c.plugin :constraint_validations, :validation_options=>{:unique=>{:message=>'is bad'}}
|
|
232
|
+
c.constraint_validations.should == [[:validates_unique, [:name], {:message=>'is bad', :allow_nil=>true}]]
|
|
233
|
+
c.constraint_validation_reflections.should == {:name=>[[:unique, {:message=>'is bad', :allow_nil=>true}]]}
|
|
234
|
+
c.dataset._fetch = {:count=>1}
|
|
235
|
+
o = c.new(:name=>'a')
|
|
236
|
+
o.valid?.should == false
|
|
237
|
+
o.errors.full_messages.should == ['name is bad']
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "should handle :validation_options merging with subclasses" do
|
|
241
|
+
c = model_class(:validation_type=>'unique', :column=>'name')
|
|
242
|
+
c.plugin :constraint_validations, :validation_options=>{:unique=>{:message=>'is bad', :allow_nil=>true}}
|
|
243
|
+
sc = Class.new(c)
|
|
244
|
+
sc.plugin :constraint_validations, :validation_options=>{:unique=>{:allow_missing=>true, :allow_nil=>false}}
|
|
245
|
+
sc.constraint_validations.should == [[:validates_unique, [:name], {:message=>'is bad', :allow_missing=>true, :allow_nil=>false}]]
|
|
246
|
+
sc.constraint_validation_reflections.should == {:name=>[[:unique, {:message=>'is bad', :allow_missing=>true, :allow_nil=>false}]]}
|
|
247
|
+
sc.dataset._fetch = {:count=>1}
|
|
248
|
+
o = sc.new(:name=>'a')
|
|
249
|
+
o.valid?.should == false
|
|
250
|
+
o.errors.full_messages.should == ['name is bad']
|
|
175
251
|
end
|
|
176
252
|
|
|
177
253
|
it "should used parsed constraint validations when validating" do
|
|
@@ -185,6 +261,7 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
185
261
|
c = Class.new(Sequel::Model(@db[Sequel.identifier(:sch__items)]))
|
|
186
262
|
c.plugin :constraint_validations
|
|
187
263
|
c.constraint_validations.should == [[:validates_presence, :name]]
|
|
264
|
+
c.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
188
265
|
end
|
|
189
266
|
|
|
190
267
|
it "should handle a table name specified as SQL::QualifiedIdentifier" do
|
|
@@ -192,5 +269,6 @@ describe "Sequel::Plugins::ConstraintValidations" do
|
|
|
192
269
|
c = Class.new(Sequel::Model(@db[Sequel.qualify(:sch, :items)]))
|
|
193
270
|
c.plugin :constraint_validations
|
|
194
271
|
c.constraint_validations.should == [[:validates_presence, :name]]
|
|
272
|
+
c.constraint_validation_reflections.should == {:name=>[[:presence, {}]]}
|
|
195
273
|
end
|
|
196
274
|
end
|