sequel 3.48.0 → 4.0.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 +114 -0
- data/Rakefile +10 -7
- data/doc/association_basics.rdoc +25 -23
- data/doc/code_order.rdoc +7 -0
- data/doc/core_extensions.rdoc +0 -10
- data/doc/object_model.rdoc +4 -1
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/4.0.0.txt +262 -0
- data/doc/security.rdoc +0 -28
- data/doc/testing.rdoc +8 -14
- data/lib/sequel/adapters/ado.rb +7 -11
- data/lib/sequel/adapters/ado/access.rb +8 -8
- data/lib/sequel/adapters/ado/mssql.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +6 -6
- data/lib/sequel/adapters/cubrid.rb +7 -7
- data/lib/sequel/adapters/db2.rb +5 -9
- data/lib/sequel/adapters/dbi.rb +2 -6
- data/lib/sequel/adapters/do.rb +4 -4
- data/lib/sequel/adapters/firebird.rb +4 -4
- data/lib/sequel/adapters/ibmdb.rb +8 -8
- data/lib/sequel/adapters/informix.rb +2 -10
- data/lib/sequel/adapters/jdbc.rb +17 -17
- data/lib/sequel/adapters/jdbc/as400.rb +2 -2
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
- data/lib/sequel/adapters/jdbc/informix.rb +1 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
- data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
- data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
- data/lib/sequel/adapters/mock.rb +7 -7
- data/lib/sequel/adapters/mysql.rb +3 -3
- data/lib/sequel/adapters/mysql2.rb +4 -4
- data/lib/sequel/adapters/odbc.rb +2 -6
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -5
- data/lib/sequel/adapters/oracle.rb +13 -17
- data/lib/sequel/adapters/postgres.rb +20 -25
- data/lib/sequel/adapters/shared/cubrid.rb +3 -3
- data/lib/sequel/adapters/shared/db2.rb +2 -2
- data/lib/sequel/adapters/shared/firebird.rb +7 -7
- data/lib/sequel/adapters/shared/mssql.rb +9 -9
- data/lib/sequel/adapters/shared/mysql.rb +29 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
- data/lib/sequel/adapters/shared/oracle.rb +22 -13
- data/lib/sequel/adapters/shared/postgres.rb +61 -46
- data/lib/sequel/adapters/shared/sqlite.rb +9 -9
- data/lib/sequel/adapters/sqlite.rb +17 -11
- data/lib/sequel/adapters/swift.rb +3 -3
- data/lib/sequel/adapters/swift/mysql.rb +1 -1
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +8 -8
- data/lib/sequel/ast_transformer.rb +3 -1
- data/lib/sequel/connection_pool.rb +4 -2
- data/lib/sequel/connection_pool/sharded_single.rb +2 -2
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
- data/lib/sequel/connection_pool/threaded.rb +7 -7
- data/lib/sequel/core.rb +4 -67
- data/lib/sequel/database.rb +1 -0
- data/lib/sequel/database/connecting.rb +2 -8
- data/lib/sequel/database/dataset.rb +2 -7
- data/lib/sequel/database/dataset_defaults.rb +0 -18
- data/lib/sequel/database/features.rb +4 -4
- data/lib/sequel/database/misc.rb +6 -8
- data/lib/sequel/database/query.rb +5 -61
- data/lib/sequel/database/schema_generator.rb +22 -20
- data/lib/sequel/database/schema_methods.rb +48 -20
- data/lib/sequel/database/transactions.rb +7 -17
- data/lib/sequel/dataset.rb +2 -0
- data/lib/sequel/dataset/actions.rb +23 -91
- data/lib/sequel/dataset/features.rb +1 -4
- data/lib/sequel/dataset/graph.rb +3 -47
- data/lib/sequel/dataset/misc.rb +4 -33
- data/lib/sequel/dataset/prepared_statements.rb +3 -1
- data/lib/sequel/dataset/query.rb +116 -240
- data/lib/sequel/dataset/sql.rb +19 -97
- data/lib/sequel/deprecated.rb +0 -16
- data/lib/sequel/exceptions.rb +0 -3
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/columns_introspection.rb +1 -12
- data/lib/sequel/extensions/constraint_validations.rb +3 -3
- data/lib/sequel/extensions/core_extensions.rb +0 -9
- data/lib/sequel/extensions/date_arithmetic.rb +1 -2
- data/lib/sequel/extensions/graph_each.rb +11 -0
- data/lib/sequel/extensions/migration.rb +5 -5
- data/lib/sequel/extensions/null_dataset.rb +11 -13
- data/lib/sequel/extensions/pagination.rb +3 -6
- data/lib/sequel/extensions/pg_array.rb +6 -4
- data/lib/sequel/extensions/pg_array_ops.rb +35 -1
- data/lib/sequel/extensions/pg_json.rb +12 -2
- data/lib/sequel/extensions/pg_json_ops.rb +266 -0
- data/lib/sequel/extensions/pg_range.rb +2 -2
- data/lib/sequel/extensions/pg_range_ops.rb +0 -8
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/pretty_table.rb +0 -4
- data/lib/sequel/extensions/query.rb +3 -8
- data/lib/sequel/extensions/schema_caching.rb +0 -7
- data/lib/sequel/extensions/schema_dumper.rb +10 -17
- data/lib/sequel/extensions/select_remove.rb +0 -4
- data/lib/sequel/extensions/set_overrides.rb +28 -0
- data/lib/sequel/extensions/to_dot.rb +6 -10
- data/lib/sequel/model.rb +6 -7
- data/lib/sequel/model/associations.rb +127 -182
- data/lib/sequel/model/base.rb +88 -211
- data/lib/sequel/model/errors.rb +0 -13
- data/lib/sequel/model/plugins.rb +2 -2
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/after_initialize.rb +11 -17
- data/lib/sequel/plugins/association_autoreloading.rb +1 -47
- data/lib/sequel/plugins/association_dependencies.rb +2 -2
- data/lib/sequel/plugins/auto_validations.rb +2 -8
- data/lib/sequel/plugins/blacklist_security.rb +32 -2
- data/lib/sequel/plugins/caching.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/composition.rb +10 -8
- data/lib/sequel/plugins/constraint_validations.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +4 -0
- data/lib/sequel/plugins/defaults_setter.rb +8 -6
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/force_encoding.rb +13 -8
- data/lib/sequel/plugins/hook_class_methods.rb +1 -7
- data/lib/sequel/plugins/json_serializer.rb +13 -74
- data/lib/sequel/plugins/lazy_attributes.rb +2 -4
- data/lib/sequel/plugins/list.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +4 -11
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +3 -5
- data/lib/sequel/plugins/pg_array_associations.rb +453 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +5 -4
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +7 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -2
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +19 -4
- data/lib/sequel/plugins/validation_class_methods.rb +0 -30
- data/lib/sequel/plugins/validation_helpers.rb +13 -31
- data/lib/sequel/plugins/xml_serializer.rb +18 -57
- data/lib/sequel/sql.rb +20 -22
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/db2_spec.rb +14 -23
- data/spec/adapters/firebird_spec.rb +25 -29
- data/spec/adapters/informix_spec.rb +11 -14
- data/spec/adapters/mssql_spec.rb +71 -77
- data/spec/adapters/mysql_spec.rb +165 -172
- data/spec/adapters/oracle_spec.rb +36 -39
- data/spec/adapters/postgres_spec.rb +175 -100
- data/spec/adapters/spec_helper.rb +13 -11
- data/spec/adapters/sqlite_spec.rb +36 -44
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +55 -55
- data/spec/core/dataset_spec.rb +45 -249
- data/spec/core/deprecated_spec.rb +0 -8
- data/spec/core/expression_filters_spec.rb +23 -5
- data/spec/core/object_graph_spec.rb +4 -66
- data/spec/core/schema_spec.rb +35 -12
- data/spec/core/spec_helper.rb +3 -2
- data/spec/core_extensions_spec.rb +17 -19
- data/spec/extensions/arbitrary_servers_spec.rb +2 -3
- data/spec/extensions/association_dependencies_spec.rb +14 -14
- data/spec/extensions/auto_validations_spec.rb +7 -0
- data/spec/extensions/blacklist_security_spec.rb +5 -5
- data/spec/extensions/blank_spec.rb +2 -0
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/extensions/columns_introspection_spec.rb +2 -29
- data/spec/extensions/composition_spec.rb +10 -17
- data/spec/extensions/core_refinements_spec.rb +5 -1
- data/spec/extensions/dataset_associations_spec.rb +18 -0
- data/spec/extensions/date_arithmetic_spec.rb +2 -2
- data/spec/extensions/defaults_setter_spec.rb +9 -9
- data/spec/extensions/dirty_spec.rb +0 -5
- data/spec/extensions/eval_inspect_spec.rb +2 -0
- data/spec/extensions/force_encoding_spec.rb +2 -18
- data/spec/extensions/hash_aliases_spec.rb +8 -0
- data/spec/extensions/hook_class_methods_spec.rb +39 -58
- data/spec/extensions/inflector_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +8 -8
- data/spec/extensions/json_serializer_spec.rb +1 -41
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +106 -109
- data/spec/extensions/migration_spec.rb +2 -0
- data/spec/extensions/named_timezones_spec.rb +1 -0
- data/spec/extensions/pg_array_associations_spec.rb +603 -0
- data/spec/extensions/pg_array_ops_spec.rb +25 -0
- data/spec/extensions/pg_array_spec.rb +9 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
- data/spec/extensions/pg_hstore_spec.rb +1 -0
- data/spec/extensions/pg_json_ops_spec.rb +131 -0
- data/spec/extensions/pg_json_spec.rb +10 -4
- data/spec/extensions/pg_range_ops_spec.rb +2 -5
- data/spec/extensions/pg_range_spec.rb +6 -2
- data/spec/extensions/pg_row_ops_spec.rb +2 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
- data/spec/extensions/rcte_tree_spec.rb +15 -15
- data/spec/extensions/schema_dumper_spec.rb +0 -1
- data/spec/extensions/schema_spec.rb +9 -9
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +18 -29
- data/spec/extensions/set_overrides_spec.rb +4 -0
- data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
- data/spec/extensions/single_table_inheritance_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +8 -9
- data/spec/extensions/sql_expr_spec.rb +2 -0
- data/spec/extensions/string_date_time_spec.rb +2 -0
- data/spec/extensions/string_stripper_spec.rb +2 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
- data/spec/extensions/thread_local_timezones_spec.rb +2 -0
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +24 -24
- data/spec/extensions/tree_spec.rb +7 -7
- data/spec/extensions/typecast_on_load_spec.rb +8 -1
- data/spec/extensions/update_primary_key_spec.rb +10 -10
- data/spec/extensions/validation_class_methods_spec.rb +10 -39
- data/spec/extensions/validation_helpers_spec.rb +29 -47
- data/spec/extensions/xml_serializer_spec.rb +1 -23
- data/spec/integration/associations_test.rb +231 -40
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +64 -64
- data/spec/integration/eager_loader_test.rb +28 -28
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +21 -21
- data/spec/integration/prepared_statement_test.rb +7 -7
- data/spec/integration/schema_test.rb +115 -110
- data/spec/integration/spec_helper.rb +17 -27
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +10 -10
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/association_reflection_spec.rb +2 -28
- data/spec/model/associations_spec.rb +239 -188
- data/spec/model/base_spec.rb +27 -68
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +160 -172
- data/spec/model/hooks_spec.rb +62 -79
- data/spec/model/model_spec.rb +36 -51
- data/spec/model/plugins_spec.rb +5 -19
- data/spec/model/record_spec.rb +125 -151
- data/spec/model/spec_helper.rb +8 -6
- data/spec/model/validations_spec.rb +4 -17
- data/spec/spec_config.rb +2 -10
- metadata +50 -56
- data/lib/sequel/deprecated_core_extensions.rb +0 -135
- data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
- data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
- data/lib/sequel/plugins/identity_map.rb +0 -260
- data/lib/sequel_core.rb +0 -2
- data/lib/sequel_model.rb +0 -2
- data/spec/extensions/association_autoreloading_spec.rb +0 -102
- data/spec/extensions/identity_map_spec.rb +0 -337
- data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
- data/spec/extensions/pg_statement_cache_spec.rb +0 -208
- data/spec/rcov.opts +0 -8
- data/spec/spec_config.rb.example +0 -10
|
@@ -7,7 +7,7 @@ module Sequel
|
|
|
7
7
|
# the additional support that the pg_* extensions add for advanced PostgreSQL
|
|
8
8
|
# types such as arrays.
|
|
9
9
|
#
|
|
10
|
-
# This plugin
|
|
10
|
+
# This plugin makes model loading to do the same conversion that the
|
|
11
11
|
# native postgres adapter would do for all columns given. You can either
|
|
12
12
|
# specify the columns to typecast on load in the plugin call itself, or
|
|
13
13
|
# afterwards using add_pg_typecast_on_load_columns:
|
|
@@ -41,19 +41,35 @@ module Sequel
|
|
|
41
41
|
@pg_typecast_on_load_columns.concat(columns)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
def call(values)
|
|
45
|
+
super(load_typecast_pg(values))
|
|
46
|
+
end
|
|
46
47
|
|
|
47
|
-
module InstanceMethods
|
|
48
48
|
# Lookup the conversion proc for the column's oid in the Database
|
|
49
49
|
# object, and use it to convert the value.
|
|
50
|
-
def
|
|
51
|
-
|
|
50
|
+
def load_typecast_pg(values)
|
|
51
|
+
pg_typecast_on_load_columns.each do |c|
|
|
52
52
|
if (v = values[c]).is_a?(String) && (oid = db_schema[c][:oid]) && (pr = db.conversion_procs[oid])
|
|
53
53
|
values[c] = pr.call(v)
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
|
-
|
|
56
|
+
values
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Plugins.inherited_instance_variables(self, :@pg_typecast_on_load_columns=>:dup)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
module InstanceMethods
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
# Typecast specific columns using the conversion procs when manually refreshing.
|
|
66
|
+
def _refresh_set_values(values)
|
|
67
|
+
super(model.load_typecast_pg(values))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Typecast specific columns using the conversion procs when refreshing after save.
|
|
71
|
+
def _save_set_values(values)
|
|
72
|
+
super(model.load_typecast_pg(values))
|
|
57
73
|
end
|
|
58
74
|
end
|
|
59
75
|
end
|
|
@@ -42,7 +42,7 @@ module Sequel
|
|
|
42
42
|
|
|
43
43
|
# Create a prepared statement based on the given dataset with a unique name for the given
|
|
44
44
|
# type of query and values.
|
|
45
|
-
def prepare_statement(ds, type, vals=
|
|
45
|
+
def prepare_statement(ds, type, vals=OPTS)
|
|
46
46
|
ps = ds.prepare(type, :"smpsp_#{NEXT.call}", vals)
|
|
47
47
|
ps.log_sql = true
|
|
48
48
|
ps
|
|
@@ -25,8 +25,8 @@ module Sequel
|
|
|
25
25
|
module ClassMethods
|
|
26
26
|
# Disable prepared statement use if a block is given, or the :dataset or :conditions
|
|
27
27
|
# options are used, or you are cloning an association.
|
|
28
|
-
def associate(type, name, opts =
|
|
29
|
-
if block || opts[:dataset] ||
|
|
28
|
+
def associate(type, name, opts = OPTS, &block)
|
|
29
|
+
if block || opts[:dataset] || (opts[:clone] && association_reflection(opts[:clone])[:prepared_statement] == false)
|
|
30
30
|
opts = opts.merge(:prepared_statement=>false)
|
|
31
31
|
end
|
|
32
32
|
super(type, name, opts, &block)
|
|
@@ -48,7 +48,7 @@ module Sequel
|
|
|
48
48
|
case opts[:type]
|
|
49
49
|
when :many_to_one
|
|
50
50
|
association_bound_variable_hash(opts.associated_class.table_name, opts.primary_keys, opts[:keys])
|
|
51
|
-
when :one_to_many
|
|
51
|
+
when :one_to_many, :one_to_one
|
|
52
52
|
association_bound_variable_hash(opts.associated_class.table_name, opts[:keys], opts[:primary_keys])
|
|
53
53
|
when :many_to_many
|
|
54
54
|
association_bound_variable_hash(opts.join_table_alias, opts[:left_keys], opts[:left_primary_keys])
|
|
@@ -59,10 +59,18 @@ module Sequel
|
|
|
59
59
|
|
|
60
60
|
# Given an association reflection, return and cache a prepared statement for this association such
|
|
61
61
|
# that, given appropriate bound variables, the prepared statement will work correctly for any
|
|
62
|
-
# instance.
|
|
63
|
-
def association_prepared_statement(opts)
|
|
62
|
+
# instance. Return false if such a prepared statement cannot be created.
|
|
63
|
+
def association_prepared_statement(opts, assoc_bv)
|
|
64
64
|
opts.send(:cached_fetch, :prepared_statement) do
|
|
65
|
-
|
|
65
|
+
ds, bv = _associated_dataset(opts, {}).unbind
|
|
66
|
+
if bv.length != assoc_bv.length
|
|
67
|
+
h = {}
|
|
68
|
+
bv.each do |k,v|
|
|
69
|
+
h[k] = v unless assoc_bv.has_key?(k)
|
|
70
|
+
end
|
|
71
|
+
ds = ds.bind(h)
|
|
72
|
+
end
|
|
73
|
+
ps = ds.prepare(opts.returns_array? ? :select : :first, :"smpsap_#{NEXT.call}")
|
|
66
74
|
ps.log_sql = true
|
|
67
75
|
ps
|
|
68
76
|
end
|
|
@@ -70,15 +78,13 @@ module Sequel
|
|
|
70
78
|
|
|
71
79
|
# If a prepared statement can be used to load the associated objects, execute it to retrieve them. Otherwise,
|
|
72
80
|
# fall back to the default implementation.
|
|
73
|
-
def _load_associated_objects(opts, dynamic_opts=
|
|
74
|
-
if !opts.can_have_associated_objects?(self) || dynamic_opts[:callback] || (
|
|
81
|
+
def _load_associated_objects(opts, dynamic_opts=OPTS)
|
|
82
|
+
if !opts.can_have_associated_objects?(self) || dynamic_opts[:callback] || (load_with_primary_key_lookup?(opts, dynamic_opts) && opts.associated_class.respond_to?(:cache_get_pk))
|
|
83
|
+
super
|
|
84
|
+
elsif (bv = association_bound_variables(opts)) && (ps ||= association_prepared_statement(opts, bv))
|
|
85
|
+
ps.call(bv)
|
|
86
|
+
else
|
|
75
87
|
super
|
|
76
|
-
else
|
|
77
|
-
if bv = association_bound_variables(opts)
|
|
78
|
-
(ps || association_prepared_statement(opts)).call(bv)
|
|
79
|
-
else
|
|
80
|
-
super
|
|
81
|
-
end
|
|
82
88
|
end
|
|
83
89
|
end
|
|
84
90
|
end
|
|
@@ -57,14 +57,14 @@ module Sequel
|
|
|
57
57
|
# of free columns.
|
|
58
58
|
def before_create
|
|
59
59
|
if v = model.prepared_statements_column_defaults
|
|
60
|
-
|
|
60
|
+
@values = v.merge(values)
|
|
61
61
|
end
|
|
62
62
|
super
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# Always do a full save of all columns to reduce the number of prepared
|
|
66
66
|
# statements that can be used.
|
|
67
|
-
def save_changes(opts=
|
|
67
|
+
def save_changes(opts=OPTS)
|
|
68
68
|
save(opts) || false if modified?
|
|
69
69
|
end
|
|
70
70
|
end
|
|
@@ -172,19 +172,20 @@ module Sequel
|
|
|
172
172
|
@deserialized_values ||= {}
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
+
# Freeze the deserialized values
|
|
175
176
|
def freeze
|
|
176
177
|
deserialized_values.freeze
|
|
177
178
|
super
|
|
178
179
|
end
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
private
|
|
182
|
+
|
|
183
|
+
# Clear any cached deserialized values when doing a manual refresh.
|
|
184
|
+
def _refresh_set_values(hash)
|
|
182
185
|
@deserialized_values.clear if @deserialized_values
|
|
183
186
|
super
|
|
184
187
|
end
|
|
185
188
|
|
|
186
|
-
private
|
|
187
|
-
|
|
188
189
|
# Deserialize the column value. Called when the model column accessor is called to
|
|
189
190
|
# return a deserialized value.
|
|
190
191
|
def deserialize_value(column, v)
|
|
@@ -27,7 +27,7 @@ module Sequel
|
|
|
27
27
|
# When eagerly loading, if the current dataset has a defined shard and the
|
|
28
28
|
# dataset that you will be using to get the associated records does not,
|
|
29
29
|
# use the current dataset's shard for the associated dataset.
|
|
30
|
-
def eager_loading_dataset(opts, ds, select, associations, eager_options=
|
|
30
|
+
def eager_loading_dataset(opts, ds, select, associations, eager_options=OPTS)
|
|
31
31
|
ds = super(opts, ds, select, associations, eager_options)
|
|
32
32
|
if !ds.opts[:server] and s = eager_options[:self] and server = s.opts[:server]
|
|
33
33
|
ds = ds.server(server)
|
|
@@ -82,6 +82,12 @@ module Sequel
|
|
|
82
82
|
o.set_server?(@server) if o.respond_to?(:set_server?)
|
|
83
83
|
super
|
|
84
84
|
end
|
|
85
|
+
|
|
86
|
+
# Don't use primary key lookup to load associated objects, since that will not
|
|
87
|
+
# respect the current object's server.
|
|
88
|
+
def load_with_primary_key_lookup?(opts, dynamic_opts)
|
|
89
|
+
false
|
|
90
|
+
end
|
|
85
91
|
end
|
|
86
92
|
|
|
87
93
|
module DatasetMethods
|
|
@@ -69,7 +69,7 @@ module Sequel
|
|
|
69
69
|
# as keys.
|
|
70
70
|
module SingleTableInheritance
|
|
71
71
|
# Setup the necessary STI variables, see the module RDoc for SingleTableInheritance
|
|
72
|
-
def self.configure(model, key, opts=
|
|
72
|
+
def self.configure(model, key, opts=OPTS)
|
|
73
73
|
model.instance_eval do
|
|
74
74
|
@sti_key_array = nil
|
|
75
75
|
@sti_key = key
|
|
@@ -26,7 +26,7 @@ module Sequel
|
|
|
26
26
|
# * :force - Whether to overwrite an existing create timestamp (default: false)
|
|
27
27
|
# * :update - The field to hold the update timestamp (default: :updated_at)
|
|
28
28
|
# * :update_on_create - Whether to set the update timestamp to the create timestamp when creating (default: false)
|
|
29
|
-
def self.configure(model, opts=
|
|
29
|
+
def self.configure(model, opts=OPTS)
|
|
30
30
|
model.instance_eval do
|
|
31
31
|
@create_timestamp_field = opts[:create]||:created_at
|
|
32
32
|
@update_timestamp_field = opts[:update]||:updated_at
|
data/lib/sequel/plugins/touch.rb
CHANGED
|
@@ -30,7 +30,7 @@ module Sequel
|
|
|
30
30
|
# The default column to update when touching
|
|
31
31
|
TOUCH_COLUMN_DEFAULT = :updated_at
|
|
32
32
|
|
|
33
|
-
def self.apply(model, opts=
|
|
33
|
+
def self.apply(model, opts=OPTS)
|
|
34
34
|
model.instance_variable_set(:@touched_associations, {})
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -43,7 +43,7 @@ module Sequel
|
|
|
43
43
|
# when updating the associated objects is the model's touch_column.
|
|
44
44
|
# If a hash is used, the value is used as the column to update.
|
|
45
45
|
# * :column - The column to modify when touching a model instance.
|
|
46
|
-
def self.configure(model, opts=
|
|
46
|
+
def self.configure(model, opts=OPTS)
|
|
47
47
|
model.touch_column = opts[:column] || TOUCH_COLUMN_DEFAULT if opts[:column] || !model.touch_column
|
|
48
48
|
model.touch_associations(opts[:associations]) if opts[:associations]
|
|
49
49
|
end
|
data/lib/sequel/plugins/tree.rb
CHANGED
|
@@ -27,7 +27,7 @@ module Sequel
|
|
|
27
27
|
# specify options to use for the parent association
|
|
28
28
|
# using a :parent option, and options to use for the
|
|
29
29
|
# children association using a :children option.
|
|
30
|
-
def self.apply(model, opts=
|
|
30
|
+
def self.apply(model, opts=OPTS)
|
|
31
31
|
opts = opts.dup
|
|
32
32
|
opts[:class] = model
|
|
33
33
|
|
|
@@ -5,7 +5,7 @@ module Sequel
|
|
|
5
5
|
# typecast correctly (with correct being defined as how the model object
|
|
6
6
|
# would typecast the same column values).
|
|
7
7
|
#
|
|
8
|
-
# This plugin
|
|
8
|
+
# This plugin makes model loading call the setter methods (which typecast
|
|
9
9
|
# by default) for all columns given. You can either specify the columns to
|
|
10
10
|
# typecast on load in the plugin call itself, or afterwards using
|
|
11
11
|
# add_typecast_on_load_columns:
|
|
@@ -36,6 +36,12 @@ module Sequel
|
|
|
36
36
|
@typecast_on_load_columns.concat(columns)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
# Typecast values using #load_typecast when the values are retrieved
|
|
40
|
+
# from the database.
|
|
41
|
+
def call(values)
|
|
42
|
+
super.load_typecast
|
|
43
|
+
end
|
|
44
|
+
|
|
39
45
|
Plugins.inherited_instance_variables(self, :@typecast_on_load_columns=>:dup)
|
|
40
46
|
end
|
|
41
47
|
|
|
@@ -52,9 +58,18 @@ module Sequel
|
|
|
52
58
|
self
|
|
53
59
|
end
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
# Typecast values using #load_typecast when the values are refreshed manually.
|
|
64
|
+
def _refresh_set_values(values)
|
|
65
|
+
ret = super
|
|
66
|
+
load_typecast
|
|
67
|
+
ret
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Typecast values using #load_typecast when the values are refreshed
|
|
71
|
+
# automatically after a save.
|
|
72
|
+
def _save_set_values(values)
|
|
58
73
|
ret = super
|
|
59
74
|
load_typecast
|
|
60
75
|
ret
|
|
@@ -264,36 +264,6 @@ module Sequel
|
|
|
264
264
|
end
|
|
265
265
|
end
|
|
266
266
|
|
|
267
|
-
# Validates whether an attribute is not a string. This is generally useful
|
|
268
|
-
# in conjunction with raise_on_typecast_failure = false, where you are
|
|
269
|
-
# passing in string values for non-string attributes (such as numbers and dates).
|
|
270
|
-
# If typecasting fails (invalid number or date), the value of the attribute will
|
|
271
|
-
# be a string in an invalid format, and if typecasting succeeds, the value will
|
|
272
|
-
# not be a string.
|
|
273
|
-
#
|
|
274
|
-
# Possible Options:
|
|
275
|
-
# * :message - The message to use (default: 'is a string' or 'is not a valid (integer|datetime|etc.)' if the type is known)
|
|
276
|
-
def validates_not_string(*atts)
|
|
277
|
-
Sequel::Deprecation.deprecate('validates_not_string', "Please switch to validates_schema_type")
|
|
278
|
-
opts = {
|
|
279
|
-
:tag => :not_string,
|
|
280
|
-
}.merge!(extract_options!(atts))
|
|
281
|
-
reflect_validation(:not_string, opts, atts)
|
|
282
|
-
atts << opts
|
|
283
|
-
validates_each(*atts) do |o, a, v|
|
|
284
|
-
if v.is_a?(String)
|
|
285
|
-
unless message = opts[:message]
|
|
286
|
-
message = if sch = o.db_schema[a] and typ = sch[:type]
|
|
287
|
-
"is not a valid #{typ}"
|
|
288
|
-
else
|
|
289
|
-
"is a string"
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
|
-
o.errors.add(a, message)
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
|
|
297
267
|
# Validates whether an attribute is a number.
|
|
298
268
|
#
|
|
299
269
|
# Possible Options:
|
|
@@ -32,9 +32,7 @@ module Sequel
|
|
|
32
32
|
# :allow_nil :: Whether to skip the validation if the value is nil.
|
|
33
33
|
# :message :: The message to use. Can be a string which is used directly, or a
|
|
34
34
|
# proc which is called. If the validation method takes a argument before the array of attributes,
|
|
35
|
-
# that argument is passed as an argument to the proc.
|
|
36
|
-
# validates_not_string method, which doesn't take an argument, but passes
|
|
37
|
-
# the schema type symbol as the argument to the proc.
|
|
35
|
+
# that argument is passed as an argument to the proc.
|
|
38
36
|
#
|
|
39
37
|
# The default validation options for all models can be modified by
|
|
40
38
|
# changing the values of the Sequel::Plugins::ValidationHelpers::DEFAULT_OPTIONS hash. You
|
|
@@ -84,7 +82,6 @@ module Sequel
|
|
|
84
82
|
:max_length=>{:message=>lambda{|max| "is longer than #{max} characters"}, :nil_message=>lambda{"is not present"}},
|
|
85
83
|
:min_length=>{:message=>lambda{|min| "is shorter than #{min} characters"}},
|
|
86
84
|
:not_null=>{:message=>lambda{"is not present"}},
|
|
87
|
-
:not_string=>{:message=>lambda{|type| type ? "is not a valid #{type}" : "is a string"}},
|
|
88
85
|
:numeric=>{:message=>lambda{"is not a number"}},
|
|
89
86
|
:type=>{:message=>lambda{|klass| klass.is_a?(Array) ? "is not a valid #{klass.join(" or ").downcase}" : "is not a valid #{klass.to_s.downcase}"}},
|
|
90
87
|
:presence=>{:message=>lambda{"is not present"}},
|
|
@@ -93,22 +90,22 @@ module Sequel
|
|
|
93
90
|
|
|
94
91
|
module InstanceMethods
|
|
95
92
|
# Check that the attribute values are the given exact length.
|
|
96
|
-
def validates_exact_length(exact, atts, opts=
|
|
93
|
+
def validates_exact_length(exact, atts, opts=OPTS)
|
|
97
94
|
validatable_attributes_for_type(:exact_length, atts, opts){|a,v,m| validation_error_message(m, exact) if v.nil? || v.length != exact}
|
|
98
95
|
end
|
|
99
96
|
|
|
100
97
|
# Check the string representation of the attribute value(s) against the regular expression with.
|
|
101
|
-
def validates_format(with, atts, opts=
|
|
98
|
+
def validates_format(with, atts, opts=OPTS)
|
|
102
99
|
validatable_attributes_for_type(:format, atts, opts){|a,v,m| validation_error_message(m, with) unless v.to_s =~ with}
|
|
103
100
|
end
|
|
104
101
|
|
|
105
102
|
# Check attribute value(s) is included in the given set.
|
|
106
|
-
def validates_includes(set, atts, opts=
|
|
103
|
+
def validates_includes(set, atts, opts=OPTS)
|
|
107
104
|
validatable_attributes_for_type(:includes, atts, opts){|a,v,m| validation_error_message(m, set) unless set.send(set.respond_to?(:cover?) ? :cover? : :include?, v)}
|
|
108
105
|
end
|
|
109
106
|
|
|
110
107
|
# Check attribute value(s) string representation is a valid integer.
|
|
111
|
-
def validates_integer(atts, opts=
|
|
108
|
+
def validates_integer(atts, opts=OPTS)
|
|
112
109
|
validatable_attributes_for_type(:integer, atts, opts) do |a,v,m|
|
|
113
110
|
begin
|
|
114
111
|
Kernel.Integer(v.to_s)
|
|
@@ -120,7 +117,7 @@ module Sequel
|
|
|
120
117
|
end
|
|
121
118
|
|
|
122
119
|
# Check that the attribute values length is in the specified range.
|
|
123
|
-
def validates_length_range(range, atts, opts=
|
|
120
|
+
def validates_length_range(range, atts, opts=OPTS)
|
|
124
121
|
validatable_attributes_for_type(:length_range, atts, opts){|a,v,m| validation_error_message(m, range) if v.nil? || !range.send(range.respond_to?(:cover?) ? :cover? : :include?, v.length)}
|
|
125
122
|
end
|
|
126
123
|
|
|
@@ -128,33 +125,22 @@ module Sequel
|
|
|
128
125
|
#
|
|
129
126
|
# Accepts a :nil_message option that is the error message to use when the
|
|
130
127
|
# value is nil instead of being too long.
|
|
131
|
-
def validates_max_length(max, atts, opts=
|
|
128
|
+
def validates_max_length(max, atts, opts=OPTS)
|
|
132
129
|
validatable_attributes_for_type(:max_length, atts, opts){|a,v,m| v ? validation_error_message(m, max) : validation_error_message(opts[:nil_message] || DEFAULT_OPTIONS[:max_length][:nil_message]) if v.nil? || v.length > max}
|
|
133
130
|
end
|
|
134
131
|
|
|
135
132
|
# Check that the attribute values are not shorter than the given min length.
|
|
136
|
-
def validates_min_length(min, atts, opts=
|
|
133
|
+
def validates_min_length(min, atts, opts=OPTS)
|
|
137
134
|
validatable_attributes_for_type(:min_length, atts, opts){|a,v,m| validation_error_message(m, min) if v.nil? || v.length < min}
|
|
138
135
|
end
|
|
139
136
|
|
|
140
137
|
# Check attribute value(s) are not NULL/nil.
|
|
141
|
-
def validates_not_null(atts, opts=
|
|
138
|
+
def validates_not_null(atts, opts=OPTS)
|
|
142
139
|
validatable_attributes_for_type(:not_null, atts, opts){|a,v,m| validation_error_message(m) if v.nil?}
|
|
143
140
|
end
|
|
144
141
|
|
|
145
|
-
# Check that the attribute value(s) is not a string. This is generally useful
|
|
146
|
-
# in conjunction with raise_on_typecast_failure = false, where you are
|
|
147
|
-
# passing in string values for non-string attributes (such as numbers and dates).
|
|
148
|
-
# If typecasting fails (invalid number or date), the value of the attribute will
|
|
149
|
-
# be a string in an invalid format, and if typecasting succeeds, the value will
|
|
150
|
-
# not be a string.
|
|
151
|
-
def validates_not_string(atts, opts={})
|
|
152
|
-
Sequel::Deprecation.deprecate('validates_not_string', "Please switch to validates_schema_types")
|
|
153
|
-
validatable_attributes_for_type(:not_string, atts, opts){|a,v,m| validation_error_message(m, (db_schema[a]||{})[:type]) if v.is_a?(String)}
|
|
154
|
-
end
|
|
155
|
-
|
|
156
142
|
# Check attribute value(s) string representation is a valid float.
|
|
157
|
-
def validates_numeric(atts, opts=
|
|
143
|
+
def validates_numeric(atts, opts=OPTS)
|
|
158
144
|
validatable_attributes_for_type(:numeric, atts, opts) do |a,v,m|
|
|
159
145
|
begin
|
|
160
146
|
Kernel.Float(v.to_s)
|
|
@@ -168,7 +154,7 @@ module Sequel
|
|
|
168
154
|
# Validates for all of the model columns (or just the given columns)
|
|
169
155
|
# that the column value is an instance of the expected class based on
|
|
170
156
|
# the column's schema type.
|
|
171
|
-
def validates_schema_types(atts=keys, opts=
|
|
157
|
+
def validates_schema_types(atts=keys, opts=OPTS)
|
|
172
158
|
Array(atts).each do |k|
|
|
173
159
|
if type = schema_type_class(k)
|
|
174
160
|
validates_type(type, k, {:allow_nil=>true}.merge(opts))
|
|
@@ -178,13 +164,9 @@ module Sequel
|
|
|
178
164
|
|
|
179
165
|
# Check if value is an instance of a class. If +klass+ is an array,
|
|
180
166
|
# the value must be an instance of one of the classes in the array.
|
|
181
|
-
def validates_type(klass, atts, opts=
|
|
167
|
+
def validates_type(klass, atts, opts=OPTS)
|
|
182
168
|
klass = klass.to_s.constantize if klass.is_a?(String) || klass.is_a?(Symbol)
|
|
183
169
|
validatable_attributes_for_type(:type, atts, opts) do |a,v,m|
|
|
184
|
-
if v.nil?
|
|
185
|
-
Sequel::Deprecation.deprecate('validates_type will no longer allow nil values by default in Sequel 4. Use the :allow_nil=>true option to allow nil values.')
|
|
186
|
-
next
|
|
187
|
-
end
|
|
188
170
|
if klass.is_a?(Array) ? !klass.any?{|kls| v.is_a?(kls)} : !v.is_a?(klass)
|
|
189
171
|
validation_error_message(m, klass)
|
|
190
172
|
end
|
|
@@ -192,7 +174,7 @@ module Sequel
|
|
|
192
174
|
end
|
|
193
175
|
|
|
194
176
|
# Check attribute value(s) is not considered blank by the database, but allow false values.
|
|
195
|
-
def validates_presence(atts, opts=
|
|
177
|
+
def validates_presence(atts, opts=OPTS)
|
|
196
178
|
validatable_attributes_for_type(:presence, atts, opts){|a,v,m| validation_error_message(m) if model.db.send(:blank_object?, v) && v != false}
|
|
197
179
|
end
|
|
198
180
|
|