sequel 3.48.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/sequel/model/errors.rb
CHANGED
@@ -5,19 +5,6 @@ module Sequel
|
|
5
5
|
class Errors < ::Hash
|
6
6
|
ATTRIBUTE_JOINER = ' and '.freeze
|
7
7
|
|
8
|
-
# Assign an array of messages for each attribute on access.
|
9
|
-
# Using this message is discouraged in new code, use +add+
|
10
|
-
# to add new error messages, and +on+ to check existing
|
11
|
-
# error messages.
|
12
|
-
def [](k)
|
13
|
-
if has_key?(k)
|
14
|
-
super
|
15
|
-
else
|
16
|
-
Sequel::Deprecation.deprecate('Model::Errors#[] autovivification', 'Please switch to Model::Errors#add to add errors, and Model::Errors#on to get errors')
|
17
|
-
self[k] = []
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
8
|
# Adds an error for the given attribute.
|
22
9
|
#
|
23
10
|
# errors.add(:name, 'is not valid') if name == 'invalid'
|
data/lib/sequel/model/plugins.rb
CHANGED
@@ -9,10 +9,10 @@ module Sequel
|
|
9
9
|
# already loaded by an ancestor class), before including/extending
|
10
10
|
# any modules, with the arguments
|
11
11
|
# and block provided to the call to Model.plugin.
|
12
|
-
# * A module inside the plugin module named InstanceMethods,
|
13
|
-
# which will be included in the model class.
|
14
12
|
# * A module inside the plugin module named ClassMethods,
|
15
13
|
# which will extend the model class.
|
14
|
+
# * A module inside the plugin module named InstanceMethods,
|
15
|
+
# which will be included in the model class.
|
16
16
|
# * A module inside the plugin module named DatasetMethods,
|
17
17
|
# which will extend the model's dataset.
|
18
18
|
# * A singleton method named configure, which takes a model,
|
data/lib/sequel/no_core_ext.rb
CHANGED
@@ -13,30 +13,24 @@ module Sequel
|
|
13
13
|
module AfterInitialize
|
14
14
|
module ClassMethods
|
15
15
|
# Call after_initialize for model objects loaded from the database.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
#end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
# REMOVE40
|
25
|
-
def check_deprecated_after_initialize(meths)
|
16
|
+
def call(h={})
|
17
|
+
v = super
|
18
|
+
v.after_initialize
|
19
|
+
v
|
26
20
|
end
|
27
21
|
end
|
28
22
|
|
29
23
|
module InstanceMethods
|
30
24
|
# Call after_initialize for new model objects.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
def initialize(h={})
|
26
|
+
super
|
27
|
+
after_initialize
|
28
|
+
end
|
29
|
+
|
36
30
|
# An empty after_initialize hook, so that plugins that use this
|
37
31
|
# can always call super to get the default behavior.
|
38
|
-
|
39
|
-
|
32
|
+
def after_initialize
|
33
|
+
end
|
40
34
|
end
|
41
35
|
end
|
42
36
|
end
|
@@ -1,53 +1,7 @@
|
|
1
1
|
module Sequel
|
2
2
|
module Plugins
|
3
|
-
#
|
4
|
-
# accessor methods automatically reload the cached object whenever
|
5
|
-
# the association's foreign key is modified:
|
6
|
-
#
|
7
|
-
# Album.many_to_one :artists
|
8
|
-
# album = Album.first
|
9
|
-
# album.artist_id #=> 1
|
10
|
-
# album.artist # caches associated artist
|
11
|
-
# album.artist_id = 2
|
12
|
-
# album.artist # reloads associated artist
|
13
|
-
#
|
3
|
+
# Empty plugin module for backwards compatibility
|
14
4
|
module AssociationAutoreloading
|
15
|
-
def self.apply(model)
|
16
|
-
model.instance_variable_set(:@autoreloading_associations, {})
|
17
|
-
end
|
18
|
-
|
19
|
-
module ClassMethods
|
20
|
-
# Hash with column symbol keys and arrays of many_to_one
|
21
|
-
# association symbols that should be cleared when the column
|
22
|
-
# value changes.
|
23
|
-
attr_reader :autoreloading_associations
|
24
|
-
|
25
|
-
Plugins.inherited_instance_variables(self, :@autoreloading_associations=>:hash_dup)
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
# Add the association to the array of associations to clear for
|
30
|
-
# each of the foreign key columns.
|
31
|
-
def def_many_to_one(opts)
|
32
|
-
super
|
33
|
-
opts[:keys].each do |key|
|
34
|
-
(@autoreloading_associations[key] ||= []) << opts[:name]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
module InstanceMethods
|
40
|
-
private
|
41
|
-
|
42
|
-
# If a foreign key column value changes, clear the related
|
43
|
-
# cached associations.
|
44
|
-
def change_column_value(column, value)
|
45
|
-
if assocs = model.autoreloading_associations[column]
|
46
|
-
assocs.each{|a| associations.delete(a)}
|
47
|
-
end
|
48
|
-
super
|
49
|
-
end
|
50
|
-
end
|
51
5
|
end
|
52
6
|
end
|
53
7
|
end
|
@@ -29,12 +29,12 @@ module Sequel
|
|
29
29
|
DEPENDENCE_ACTIONS = [:delete, :destroy, :nullify]
|
30
30
|
|
31
31
|
# Initialize the association_dependencies hash for this model.
|
32
|
-
def self.apply(model, hash=
|
32
|
+
def self.apply(model, hash=OPTS)
|
33
33
|
model.instance_eval{@association_dependencies = {:before_delete=>[], :before_destroy=>[], :before_nullify=>[], :after_delete=>[], :after_destroy=>[]}}
|
34
34
|
end
|
35
35
|
|
36
36
|
# Call add_association_dependencies with any dependencies given in the plugin call.
|
37
|
-
def self.configure(model, hash=
|
37
|
+
def self.configure(model, hash=OPTS)
|
38
38
|
model.add_association_dependencies(hash) unless hash.empty?
|
39
39
|
end
|
40
40
|
|
@@ -43,7 +43,7 @@ module Sequel
|
|
43
43
|
# # Make the Album class use auto validations
|
44
44
|
# Album.plugin :auto_validations
|
45
45
|
module AutoValidations
|
46
|
-
def self.apply(model, opts=
|
46
|
+
def self.apply(model, opts=OPTS)
|
47
47
|
model.instance_eval do
|
48
48
|
plugin :validation_helpers
|
49
49
|
@auto_validate_presence = false
|
@@ -55,7 +55,7 @@ module Sequel
|
|
55
55
|
end
|
56
56
|
|
57
57
|
# Setup auto validations for the model if it has a dataset.
|
58
|
-
def self.configure(model, opts=
|
58
|
+
def self.configure(model, opts=OPTS)
|
59
59
|
model.instance_eval do
|
60
60
|
setup_auto_validations if @dataset
|
61
61
|
if opts[:not_null] == :presence
|
@@ -77,12 +77,6 @@ module Sequel
|
|
77
77
|
Plugins.inherited_instance_variables(self, :@auto_validate_presence=>nil, :@auto_validate_types=>nil, :@auto_validate_not_null_columns=>:dup, :@auto_validate_explicit_not_null_columns=>:dup, :@auto_validate_unique_columns=>:dup)
|
78
78
|
Plugins.after_set_dataset(self, :setup_auto_validations)
|
79
79
|
|
80
|
-
# REMOVE40
|
81
|
-
def auto_validate_presence_columns
|
82
|
-
Sequel::Deprecation.deprecate('Model.auto_validate_presence_columns', 'Please switch to auto_validate_not_null_columns')
|
83
|
-
auto_validate_not_null_columns
|
84
|
-
end
|
85
|
-
|
86
80
|
# Whether to use a presence validation for not null columns
|
87
81
|
def auto_validate_presence?
|
88
82
|
@auto_validate_presence
|
@@ -36,9 +36,25 @@ module Sequel
|
|
36
36
|
clear_setter_methods_cache
|
37
37
|
@restricted_columns = cols
|
38
38
|
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# If allowed_columns is not set but restricted_columns is, remove the
|
43
|
+
# restricted_columns.
|
44
|
+
def get_setter_methods
|
45
|
+
meths = super
|
46
|
+
if !allowed_columns && restricted_columns
|
47
|
+
meths -= restricted_columns.map{|x| "#{x}="}
|
48
|
+
end
|
49
|
+
meths
|
50
|
+
end
|
39
51
|
end
|
40
52
|
|
41
53
|
module InstanceMethods
|
54
|
+
# Special array subclass used for marking methods to be removed.
|
55
|
+
class ExceptionList < Array
|
56
|
+
end
|
57
|
+
|
42
58
|
# Set all values using the entries in the hash, except for the keys
|
43
59
|
# given in except. You should probably use +set_fields+ or +set_only+
|
44
60
|
# instead of this method, as blacklist approaches to security are a bad idea.
|
@@ -46,7 +62,7 @@ module Sequel
|
|
46
62
|
# artist.set_except({:name=>'Jim'}, :hometown)
|
47
63
|
# artist.name # => 'Jim'
|
48
64
|
def set_except(hash, *except)
|
49
|
-
set_restricted(hash,
|
65
|
+
set_restricted(hash, ExceptionList.new(except.flatten))
|
50
66
|
end
|
51
67
|
|
52
68
|
# Update all values using the entries in the hash, except for the keys
|
@@ -55,7 +71,21 @@ module Sequel
|
|
55
71
|
#
|
56
72
|
# artist.update_except({:name=>'Jim'}, :hometown) # UPDATE artists SET name = 'Jim' WHERE (id = 1)
|
57
73
|
def update_except(hash, *except)
|
58
|
-
update_restricted(hash,
|
74
|
+
update_restricted(hash, ExceptionList.new(except.flatten))
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# If set_except or update_except was used, remove the related methods from the list.
|
80
|
+
def setter_methods(type)
|
81
|
+
if type.is_a?(ExceptionList)
|
82
|
+
meths = super(:all)
|
83
|
+
meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && model.restrict_primary_key?
|
84
|
+
meths -= type.map{|x| "#{x}="}
|
85
|
+
meths
|
86
|
+
else
|
87
|
+
super
|
88
|
+
end
|
59
89
|
end
|
60
90
|
end
|
61
91
|
end
|
@@ -34,7 +34,7 @@ module Sequel
|
|
34
34
|
module Caching
|
35
35
|
# Set the cache_store and cache_ttl attributes for the given model.
|
36
36
|
# If the :ttl option is not given, 3600 seconds is the default.
|
37
|
-
def self.configure(model, store, opts=
|
37
|
+
def self.configure(model, store, opts=OPTS)
|
38
38
|
model.instance_eval do
|
39
39
|
@cache_store = store
|
40
40
|
@cache_ttl = opts[:ttl] || 3600
|
@@ -68,7 +68,7 @@ module Sequel
|
|
68
68
|
# The class_table_inheritance plugin requires the lazy_attributes plugin
|
69
69
|
# to handle lazily-loaded attributes for subclass instances returned
|
70
70
|
# by superclass methods.
|
71
|
-
def self.apply(model, opts=
|
71
|
+
def self.apply(model, opts=OPTS)
|
72
72
|
model.plugin :lazy_attributes
|
73
73
|
end
|
74
74
|
|
@@ -81,7 +81,7 @@ module Sequel
|
|
81
81
|
# * :table_map - Hash with class name symbol keys and table name symbol
|
82
82
|
# values. Necessary if the implicit table name for the model class
|
83
83
|
# does not match the database table name
|
84
|
-
def self.configure(model, opts=
|
84
|
+
def self.configure(model, opts=OPTS)
|
85
85
|
model.instance_eval do
|
86
86
|
m = method(:constantize)
|
87
87
|
@cti_base_model = self
|
@@ -90,7 +90,7 @@ module Sequel
|
|
90
90
|
# # for example y in the composition object represents year
|
91
91
|
# # in the model object.
|
92
92
|
# :mapping=>[[:year, :y], [:month, :m], [:day, :d]]
|
93
|
-
def composition(name, opts=
|
93
|
+
def composition(name, opts=OPTS)
|
94
94
|
opts = opts.dup
|
95
95
|
compositions[name] = opts
|
96
96
|
if mapping = opts[:mapping]
|
@@ -127,7 +127,7 @@ module Sequel
|
|
127
127
|
Plugins.inherited_instance_variables(self, :@compositions=>:dup)
|
128
128
|
|
129
129
|
# Define getter and setter methods for the composition object.
|
130
|
-
def define_composition_accessor(name, opts=
|
130
|
+
def define_composition_accessor(name, opts=OPTS)
|
131
131
|
include(@composition_module ||= Module.new) unless composition_module
|
132
132
|
composer = opts[:composer]
|
133
133
|
composition_module.class_eval do
|
@@ -149,12 +149,6 @@ module Sequel
|
|
149
149
|
end
|
150
150
|
|
151
151
|
module InstanceMethods
|
152
|
-
# Clear the cached compositions when setting values.
|
153
|
-
def set_values(hash)
|
154
|
-
@compositions.clear if @compositions
|
155
|
-
super
|
156
|
-
end
|
157
|
-
|
158
152
|
# For each composition, set the columns in the model class based
|
159
153
|
# on the composition object.
|
160
154
|
def before_save
|
@@ -172,6 +166,14 @@ module Sequel
|
|
172
166
|
compositions.freeze
|
173
167
|
super
|
174
168
|
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# Clear the cached compositions when manually refreshing.
|
173
|
+
def _refresh_set_values(hash)
|
174
|
+
@compositions.clear if @compositions
|
175
|
+
super
|
176
|
+
end
|
175
177
|
end
|
176
178
|
end
|
177
179
|
end
|
@@ -32,7 +32,7 @@ module Sequel
|
|
32
32
|
DEFAULT_CONSTRAINT_VALIDATIONS_TABLE = :sequel_constraint_validations
|
33
33
|
|
34
34
|
# Automatically load the validation_helpers plugin to run the actual validations.
|
35
|
-
def self.apply(model, opts=
|
35
|
+
def self.apply(model, opts=OPTS)
|
36
36
|
model.instance_eval do
|
37
37
|
plugin :validation_helpers
|
38
38
|
@constraint_validations_table = DEFAULT_CONSTRAINT_VALIDATIONS_TABLE
|
@@ -49,7 +49,7 @@ module Sequel
|
|
49
49
|
# given options. Keys should be validation type symbols (e.g.
|
50
50
|
# :presence) and values should be hashes of options specific
|
51
51
|
# to that validation type.
|
52
|
-
def self.configure(model, opts=
|
52
|
+
def self.configure(model, opts=OPTS)
|
53
53
|
model.instance_eval do
|
54
54
|
if table = opts[:constraint_validations_table]
|
55
55
|
@constraint_validations_table = table
|
@@ -89,6 +89,10 @@ module Sequel
|
|
89
89
|
join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name)
|
90
90
|
edges.each{|e| sds = sds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
|
91
91
|
ds.filter(r.qualified_right_primary_key=>sds)
|
92
|
+
when :pg_array_to_many
|
93
|
+
ds.filter(Sequel.expr(r.primary_key=>sds.select{Sequel.pg_array_op(r.qualify(r[:model].table_name, r[:key])).unnest}))
|
94
|
+
when :many_to_pg_array
|
95
|
+
ds.filter(Sequel.function(:coalesce, Sequel.pg_array_op(r[:key]).overlaps(sds.select{array_agg(r.qualify(r[:model].table_name, r.primary_key))}), false))
|
92
96
|
else
|
93
97
|
raise Error, "unrecognized association type for association #{name.inspect}: #{r[:type].inspect}"
|
94
98
|
end
|
@@ -54,12 +54,14 @@ module Sequel
|
|
54
54
|
end
|
55
55
|
|
56
56
|
module InstanceMethods
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
# Use default value for a new record if values doesn't already contain an entry for it.
|
58
|
+
def [](k)
|
59
|
+
if new? && !values.has_key?(k)
|
60
|
+
v = model.default_values[k]
|
61
|
+
v.respond_to?(:call) ? v.call : v
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
data/lib/sequel/plugins/dirty.rb
CHANGED
@@ -123,12 +123,6 @@ module Sequel
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
# Reset the initial values when setting values.
|
127
|
-
def set_values(hash)
|
128
|
-
reset_initial_values
|
129
|
-
super
|
130
|
-
end
|
131
|
-
|
132
126
|
# Manually specify that a column will change. This should only be used
|
133
127
|
# if you plan to modify a column value in place, which is not recommended.
|
134
128
|
#
|
@@ -158,6 +152,12 @@ module Sequel
|
|
158
152
|
|
159
153
|
private
|
160
154
|
|
155
|
+
# Reset the initial values when setting values.
|
156
|
+
def _refresh_set_values(hash)
|
157
|
+
reset_initial_values
|
158
|
+
super
|
159
|
+
end
|
160
|
+
|
161
161
|
# Reset the initial values after saving.
|
162
162
|
def after_save
|
163
163
|
super
|
@@ -33,21 +33,26 @@ module Sequel
|
|
33
33
|
attr_accessor :forced_encoding
|
34
34
|
|
35
35
|
Plugins.inherited_instance_variables(self, :@forced_encoding=>nil)
|
36
|
+
|
37
|
+
def call(values)
|
38
|
+
o = super
|
39
|
+
o.send(:force_hash_encoding, o.values)
|
40
|
+
o
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
44
|
module InstanceMethods
|
39
|
-
|
40
|
-
# plugin by typecasting new values.
|
41
|
-
def merge_db_update(row)
|
42
|
-
super(force_hash_encoding(row))
|
43
|
-
end
|
45
|
+
private
|
44
46
|
|
45
47
|
# Force the encoding of all string values when setting the instance's values.
|
46
|
-
def
|
47
|
-
super(force_hash_encoding(
|
48
|
+
def _refresh_set_values(values)
|
49
|
+
super(force_hash_encoding(values))
|
48
50
|
end
|
49
51
|
|
50
|
-
|
52
|
+
# Force the encoding of all string values when setting the instance's values.
|
53
|
+
def _save_set_values(values)
|
54
|
+
super(force_hash_encoding(values))
|
55
|
+
end
|
51
56
|
|
52
57
|
# Force the encoding for all string values in the given row hash.
|
53
58
|
def force_hash_encoding(row)
|
@@ -39,13 +39,7 @@ module Sequel
|
|
39
39
|
end
|
40
40
|
|
41
41
|
module ClassMethods
|
42
|
-
|
43
|
-
|
44
|
-
# REMOVE40
|
45
|
-
def after_initialize(method = nil, &block)
|
46
|
-
Sequel::Deprecation.deprecate('The Model after_initialize hook', 'The hook_class_methods plugin will no longer support the hook. Please use the after_initialize plugin and define the after_initialize hook directly')
|
47
|
-
add_hook(:after_initialize, method, &block)
|
48
|
-
end
|
42
|
+
Model::HOOKS.each{|h| class_eval("def #{h}(method = nil, &block); add_hook(:#{h}, method, &block) end", __FILE__, __LINE__)}
|
49
43
|
|
50
44
|
# This adds a new hook type. It will define both a class
|
51
45
|
# method that you can use to add hooks, as well as an instance method
|
@@ -82,9 +82,6 @@ module Sequel
|
|
82
82
|
#
|
83
83
|
# album.from_json(json, :associations=>{:artist=>{:fields=>%w'id name', :associations=>:tags}})
|
84
84
|
#
|
85
|
-
# If the json is trusted and should be allowed to set all column and association
|
86
|
-
# values, you can use the :all_columns and :all_associations options.
|
87
|
-
#
|
88
85
|
# Note that active_support/json makes incompatible changes to the to_json API,
|
89
86
|
# and breaks some aspects of the json_serializer plugin. You can undo the damage
|
90
87
|
# done by active_support/json by doing:
|
@@ -142,10 +139,7 @@ module Sequel
|
|
142
139
|
|
143
140
|
# Attempt to parse a single instance from the given JSON string,
|
144
141
|
# with options passed to InstanceMethods#from_json_node.
|
145
|
-
def from_json(json, opts=
|
146
|
-
if opts[:all_associations] || opts[:all_columns]
|
147
|
-
Sequel::Deprecation.deprecate("The from_json :all_associations and :all_columns", 'You need to explicitly specify the associations and columns via the :associations and :fields options')
|
148
|
-
end
|
142
|
+
def from_json(json, opts=OPTS)
|
149
143
|
v = Sequel.parse_json(json)
|
150
144
|
case v
|
151
145
|
when self
|
@@ -159,10 +153,7 @@ module Sequel
|
|
159
153
|
|
160
154
|
# Attempt to parse an array of instances from the given JSON string,
|
161
155
|
# with options passed to InstanceMethods#from_json_node.
|
162
|
-
def array_from_json(json, opts=
|
163
|
-
if opts[:all_associations] || opts[:all_columns]
|
164
|
-
Sequel::Deprecation.deprecate("The from_json :all_associations and :all_columns", 'You need to explicitly specify the associations and columns via the :associations and :fields options')
|
165
|
-
end
|
156
|
+
def array_from_json(json, opts=OPTS)
|
166
157
|
v = Sequel.parse_json(json)
|
167
158
|
if v.is_a?(Array)
|
168
159
|
raise(Error, 'parsed json returned an array containing non-hashes') unless v.all?{|ve| ve.is_a?(Hash) || ve.is_a?(self)}
|
@@ -172,16 +163,6 @@ module Sequel
|
|
172
163
|
end
|
173
164
|
end
|
174
165
|
|
175
|
-
# Exists for compatibility with old json library which allows creation
|
176
|
-
# of arbitrary ruby objects by JSON.parse. Creates a new instance
|
177
|
-
# and populates it using InstanceMethods#from_json_node with the
|
178
|
-
# :all_columns and :all_associations options. Not recommended for usage
|
179
|
-
# in new code, consider calling the from_json method directly with the JSON string.
|
180
|
-
def json_create(hash, opts={})
|
181
|
-
Sequel::Deprecation.deprecate("Model.json_create", 'Switch to Model.from_json')
|
182
|
-
new.from_json_node(hash, {:all_columns=>true, :all_associations=>true}.merge(opts))
|
183
|
-
end
|
184
|
-
|
185
166
|
Plugins.inherited_instance_variables(self, :@json_serializer_opts=>lambda do |json_serializer_opts|
|
186
167
|
opts = {}
|
187
168
|
json_serializer_opts.each{|k, v| opts[k] = (v.is_a?(Array) || v.is_a?(Hash)) ? v.dup : v}
|
@@ -194,10 +175,7 @@ module Sequel
|
|
194
175
|
module InstanceMethods
|
195
176
|
# Parse the provided JSON, which should return a hash,
|
196
177
|
# and process the hash with from_json_node.
|
197
|
-
def from_json(json, opts=
|
198
|
-
if opts[:all_associations] || opts[:all_columns]
|
199
|
-
Sequel::Deprecation.deprecate("The from_json :all_associations and :all_columns", 'You need to explicitly specify the associations and columns via the :associations and :fields options')
|
200
|
-
end
|
178
|
+
def from_json(json, opts=OPTS)
|
201
179
|
from_json_node(Sequel.parse_json(json), opts)
|
202
180
|
end
|
203
181
|
|
@@ -205,38 +183,19 @@ module Sequel
|
|
205
183
|
# calls set with the hash values.
|
206
184
|
#
|
207
185
|
# Options:
|
208
|
-
# :all_associations :: Indicates that all associations supported by the model should be tried.
|
209
|
-
# This option also cascades to associations if used. It is better to use the
|
210
|
-
# :associations option instead of this option. This option only exists for
|
211
|
-
# backwards compatibility.
|
212
|
-
# :all_columns :: Overrides the setting logic allowing all setter methods be used,
|
213
|
-
# even if access to the setter method is restricted.
|
214
|
-
# This option cascades to associations if used, and can be reset in those associations
|
215
|
-
# using the :all_columns=>false or :fields options. This option is considered a
|
216
|
-
# security risk, and only exists for backwards compatibility. It is better to use
|
217
|
-
# the :fields option appropriately instead of this option, or no option at all.
|
218
186
|
# :associations :: Indicates that the associations cache should be updated by creating
|
219
187
|
# a new associated object using data from the hash. Should be a Symbol
|
220
188
|
# for a single association, an array of symbols for multiple associations,
|
221
189
|
# or a hash with symbol keys and dependent association option hash values.
|
222
190
|
# :fields :: Changes the behavior to call set_fields using the provided fields, instead of calling set.
|
223
|
-
def from_json_node(hash, opts=
|
191
|
+
def from_json_node(hash, opts=OPTS)
|
224
192
|
unless hash.is_a?(Hash)
|
225
193
|
raise Error, "parsed json doesn't return a hash"
|
226
194
|
end
|
227
|
-
if hash.has_key?(JSON.create_id)
|
228
|
-
Sequel::Deprecation.deprecate('Attempting to use Model#from_json with a hash value that includes JSON.create_id is deprecated. Starting in Sequel 4.0, the create_id will not be removed automatically.')
|
229
|
-
hash.delete(JSON.create_id)
|
230
|
-
end
|
231
195
|
|
232
|
-
|
233
|
-
if opts[:all_associations]
|
234
|
-
assocs = {}
|
235
|
-
model.associations.each{|v| assocs[v] = {:all_associations=>true}}
|
236
|
-
end
|
237
|
-
end
|
196
|
+
populate_associations = {}
|
238
197
|
|
239
|
-
if assocs
|
198
|
+
if assocs = opts[:associations]
|
240
199
|
assocs = case assocs
|
241
200
|
when Symbol
|
242
201
|
{assocs=>{}}
|
@@ -250,19 +209,13 @@ module Sequel
|
|
250
209
|
raise Error, ":associations should be Symbol, Array, or Hash if present"
|
251
210
|
end
|
252
211
|
|
253
|
-
if opts[:all_columns]
|
254
|
-
assocs.each_value do |assoc_opts|
|
255
|
-
assoc_opts[:all_columns] = true unless assoc_opts.has_key?(:fields) || assoc_opts.has_key?(:all_columns)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
212
|
assocs.each do |assoc, assoc_opts|
|
260
213
|
if assoc_values = hash.delete(assoc.to_s)
|
261
214
|
unless r = model.association_reflection(assoc)
|
262
215
|
raise Error, "Association #{assoc} is not defined for #{model}"
|
263
216
|
end
|
264
217
|
|
265
|
-
|
218
|
+
populate_associations[assoc] = if r.returns_array?
|
266
219
|
raise Error, "Attempt to populate array association with a non-array" unless assoc_values.is_a?(Array)
|
267
220
|
assoc_values.map{|v| v.is_a?(r.associated_class) ? v : r.associated_class.new.from_json_node(v, assoc_opts)}
|
268
221
|
else
|
@@ -275,19 +228,14 @@ module Sequel
|
|
275
228
|
|
276
229
|
if fields = opts[:fields]
|
277
230
|
set_fields(hash, fields, opts)
|
278
|
-
elsif opts[:all_columns]
|
279
|
-
meths = methods.collect{|x| x.to_s}.grep(Model::SETTER_METHOD_REGEXP) - Model::RESTRICTED_SETTER_METHODS
|
280
|
-
hash.each do |k, v|
|
281
|
-
if meths.include?(setter_meth = "#{k}=")
|
282
|
-
send(setter_meth, v)
|
283
|
-
else
|
284
|
-
raise Error, "Entry in JSON does not have a matching setter method: #{k}"
|
285
|
-
end
|
286
|
-
end
|
287
231
|
else
|
288
232
|
set(hash)
|
289
233
|
end
|
290
234
|
|
235
|
+
populate_associations.each do |assoc, values|
|
236
|
+
associations[assoc] = values
|
237
|
+
end
|
238
|
+
|
291
239
|
self
|
292
240
|
end
|
293
241
|
|
@@ -306,7 +254,6 @@ module Sequel
|
|
306
254
|
# include in the JSON output, ignoring all other
|
307
255
|
# columns.
|
308
256
|
# :root :: Qualify the JSON with the name of the object.
|
309
|
-
# Implies :naked since the object name is explicit.
|
310
257
|
def to_json(*a)
|
311
258
|
if opts = a.first.is_a?(Hash)
|
312
259
|
opts = model.json_serializer_opts.merge(a.first)
|
@@ -322,10 +269,6 @@ module Sequel
|
|
322
269
|
end
|
323
270
|
|
324
271
|
h = {}
|
325
|
-
if JSON.create_id && !opts[:naked] && !opts[:root]
|
326
|
-
Sequel::Deprecation.deprecate('The :naked and :root options have not been used, so adding JSON.create_id to the to_json output. This is deprecated, starting in Sequel 4, the JSON.create_id will never be added.')
|
327
|
-
h[JSON.create_id] = model.name
|
328
|
-
end
|
329
272
|
|
330
273
|
cols.each{|c| h[c.to_s] = send(c)}
|
331
274
|
if inc = opts[:include]
|
@@ -377,15 +320,11 @@ module Sequel
|
|
377
320
|
collection_root = case opts[:root]
|
378
321
|
when nil, false, :instance
|
379
322
|
false
|
380
|
-
when :collection
|
381
|
-
opts = opts.dup
|
382
|
-
opts.delete(:root)
|
383
|
-
opts[:naked] = true unless opts.has_key?(:naked)
|
384
|
-
true
|
385
323
|
when :both
|
386
324
|
true
|
387
325
|
else
|
388
|
-
|
326
|
+
opts = opts.dup
|
327
|
+
opts.delete(:root)
|
389
328
|
true
|
390
329
|
end
|
391
330
|
|