sequel 3.47.0 → 3.48.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,43 @@
|
|
1
|
+
# The set_overrides extension adds the Dataset#set_overrides and
|
2
|
+
# Dataset#set_defaults methods which provide a crude way to
|
3
|
+
# control the values used in INSERT/UPDATE statements if a hash
|
4
|
+
# of values is passed to Dataset#insert or Dataset#update.
|
5
|
+
# It is only recommended to use this for backwards compatibility.
|
6
|
+
#
|
7
|
+
# You can load this extension into specific datasets:
|
8
|
+
#
|
9
|
+
# ds = DB[:table]
|
10
|
+
# ds.extension(:set_overrides)
|
11
|
+
#
|
12
|
+
# Or you can load it into all of a database's datasets, which
|
13
|
+
# is probably the desired behavior if you are using this extension:
|
14
|
+
#
|
15
|
+
# DB.extension(:set_overrides)
|
16
|
+
|
17
|
+
module Sequel
|
18
|
+
module SetOverrides
|
19
|
+
Dataset.def_mutation_method(:set_defaults, :set_overrides, :module=>self)
|
20
|
+
|
21
|
+
# Set the default values for insert and update statements. The values hash passed
|
22
|
+
# to insert or update are merged into this hash, so any values in the hash passed
|
23
|
+
# to insert or update will override values passed to this method.
|
24
|
+
#
|
25
|
+
# DB[:items].set_defaults(:a=>'a', :c=>'c').insert(:a=>'d', :b=>'b')
|
26
|
+
# # INSERT INTO items (a, c, b) VALUES ('d', 'c', 'b')
|
27
|
+
def set_defaults(hash)
|
28
|
+
clone(:defaults=>(@opts[:defaults]||{}).merge(hash))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set values that override hash arguments given to insert and update statements.
|
32
|
+
# This hash is merged into the hash provided to insert or update, so values
|
33
|
+
# will override any values given in the insert/update hashes.
|
34
|
+
#
|
35
|
+
# DB[:items].set_overrides(:a=>'a', :c=>'c').insert(:a=>'d', :b=>'b')
|
36
|
+
# # INSERT INTO items (a, c, b) VALUES ('a', 'c', 'b')
|
37
|
+
def set_overrides(hash)
|
38
|
+
clone(:overrides=>hash.merge(@opts[:overrides]||{}))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Dataset.register_extension(:set_overrides, SetOverrides)
|
43
|
+
end
|
@@ -9,6 +9,9 @@
|
|
9
9
|
|
10
10
|
module Sequel
|
11
11
|
class ToDot
|
12
|
+
module DatasetMethods
|
13
|
+
end
|
14
|
+
|
12
15
|
# The option keys that should be included in the dot output.
|
13
16
|
TO_DOT_OPTIONS = [:with, :distinct, :select, :from, :join, :where, :group, :having, :compounds, :order, :limit, :offset, :lock].freeze
|
14
17
|
|
@@ -147,7 +150,10 @@ module Sequel
|
|
147
150
|
# with graphviz) in order to see a visualization of the dataset's
|
148
151
|
# abstract syntax tree.
|
149
152
|
def to_dot
|
153
|
+
Sequel::Deprecation.deprecate('Loading the to_dot extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(ToDot::DatasetMethods)
|
150
154
|
ToDot.output(self)
|
151
155
|
end
|
152
156
|
end
|
157
|
+
|
158
|
+
Dataset.register_extension(:to_dot, ToDot::DatasetMethods)
|
153
159
|
end
|
data/lib/sequel/model.rb
CHANGED
@@ -35,7 +35,7 @@ module Sequel
|
|
35
35
|
# dataset # => DB1[:comments]
|
36
36
|
# end
|
37
37
|
def self.Model(source)
|
38
|
-
if
|
38
|
+
if cache_anonymous_models && (klass = Sequel.synchronize{Model::ANONYMOUS_MODEL_CLASSES[source]})
|
39
39
|
return klass
|
40
40
|
end
|
41
41
|
klass = if source.is_a?(Database)
|
@@ -45,10 +45,19 @@ module Sequel
|
|
45
45
|
else
|
46
46
|
Class.new(Model).set_dataset(source)
|
47
47
|
end
|
48
|
-
Sequel.synchronize{Model::ANONYMOUS_MODEL_CLASSES[source] = klass} if
|
48
|
+
Sequel.synchronize{Model::ANONYMOUS_MODEL_CLASSES[source] = klass} if cache_anonymous_models
|
49
49
|
klass
|
50
50
|
end
|
51
51
|
|
52
|
+
@cache_anonymous_models = true
|
53
|
+
|
54
|
+
class << self
|
55
|
+
# Whether to cache the anonymous models created by Sequel::Model(). This is
|
56
|
+
# required for reloading them correctly (avoiding the superclass mismatch). True
|
57
|
+
# by default for backwards compatibility.
|
58
|
+
attr_accessor :cache_anonymous_models
|
59
|
+
end
|
60
|
+
|
52
61
|
# <tt>Sequel::Model</tt> is an object relational mapper built on top of Sequel core. Each
|
53
62
|
# model class is backed by a dataset instance, and many dataset methods can be
|
54
63
|
# called directly on the class. Model datasets return rows as model instances,
|
@@ -63,16 +72,13 @@ module Sequel
|
|
63
72
|
# You can set the +SEQUEL_NO_ASSOCIATIONS+ constant or environment variable to
|
64
73
|
# make Sequel not load the associations plugin by default.
|
65
74
|
class Model
|
66
|
-
# Cache anonymous models created by Sequel::Model()
|
67
|
-
@cache_anonymous_models = true
|
68
|
-
|
69
75
|
# Map that stores model classes created with <tt>Sequel::Model()</tt>, to allow the reopening
|
70
76
|
# of classes when dealing with code reloading.
|
71
77
|
ANONYMOUS_MODEL_CLASSES = {}
|
72
78
|
|
73
79
|
# Class methods added to model that call the method of the same name on the dataset
|
74
80
|
DATASET_METHODS = (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS +
|
75
|
-
[:
|
81
|
+
[:each_server]) - [:and, :or, :[], :[]=, :columns, :columns!, :delete, :update, :add_graph_aliases]
|
76
82
|
|
77
83
|
# Class instance variables to set to nil when a subclass is created, for -w compliance
|
78
84
|
EMPTY_INSTANCE_VARIABLES = [:@overridable_methods_module, :@db]
|
@@ -188,20 +188,32 @@ module Sequel
|
|
188
188
|
# it sets album.artist to this_artist.
|
189
189
|
def reciprocal
|
190
190
|
cached_fetch(:reciprocal) do
|
191
|
-
|
192
|
-
|
193
|
-
|
191
|
+
possible_recips = []
|
192
|
+
fallback_recips = []
|
193
|
+
|
194
194
|
associated_class.all_association_reflections.each do |assoc_reflect|
|
195
|
-
if
|
196
|
-
|
197
|
-
|
198
|
-
|
195
|
+
if reciprocal_association?(assoc_reflect)
|
196
|
+
if deprecated_reciprocal_association?(assoc_reflect)
|
197
|
+
fallback_recips << assoc_reflect
|
198
|
+
else
|
199
|
+
possible_recips << assoc_reflect
|
200
|
+
end
|
199
201
|
end
|
200
202
|
end
|
201
|
-
|
203
|
+
|
204
|
+
Sequel::Deprecation.deprecate("Multiple reciprocal association candidates found for #{self[:name]} association (#{possible_recips.map{|r| r[:name]}.join(', ')}). Choosing the first candidate is", "Please explicitly specify the reciprocal option for the #{self[:name]} association") if possible_recips.size >= 2
|
205
|
+
if possible_recips.empty? && !fallback_recips.empty?
|
206
|
+
possible_recips = fallback_recips
|
207
|
+
Sequel::Deprecation.deprecate("All reciprocal association candidates found for #{self[:name]} association have conditions, blocks, or differing primary keys (#{possible_recips.map{|r| r[:name]}.join(', ')}). Automatic choosing of an reciprocal association with conditions or blocks is", "Please explicitly specify the reciprocal option for the #{self[:name]} association")
|
208
|
+
end
|
209
|
+
|
210
|
+
unless possible_recips.empty?
|
211
|
+
cached_set(:reciprocal_type, possible_recips.first[:type]) if reciprocal_type.is_a?(Array)
|
212
|
+
possible_recips.first[:name]
|
213
|
+
end
|
202
214
|
end
|
203
215
|
end
|
204
|
-
|
216
|
+
|
205
217
|
# Whether the reciprocal of this association returns an array of objects instead of a single object,
|
206
218
|
# true by default.
|
207
219
|
def reciprocal_array?
|
@@ -288,6 +300,16 @@ module Sequel
|
|
288
300
|
end
|
289
301
|
end
|
290
302
|
|
303
|
+
# REMOVE40: merge into reciprocal_association?
|
304
|
+
def deprecated_reciprocal_association?(assoc_reflect)
|
305
|
+
assoc_reflect[:conditions] || assoc_reflect[:block]
|
306
|
+
end
|
307
|
+
|
308
|
+
def reciprocal_association?(assoc_reflect)
|
309
|
+
Array(reciprocal_type).include?(assoc_reflect[:type]) &&
|
310
|
+
assoc_reflect.associated_class == self[:model]
|
311
|
+
end
|
312
|
+
|
291
313
|
# If +s+ is an array, map +s+ over the block. Otherwise, just call the
|
292
314
|
# block with +s+.
|
293
315
|
def transform(s)
|
@@ -378,6 +400,15 @@ module Sequel
|
|
378
400
|
|
379
401
|
private
|
380
402
|
|
403
|
+
# REMOVE40: merge into reciprocal_association?
|
404
|
+
def deprecated_reciprocal_association?(assoc_reflect)
|
405
|
+
super || primary_key != assoc_reflect.primary_key
|
406
|
+
end
|
407
|
+
|
408
|
+
def reciprocal_association?(assoc_reflect)
|
409
|
+
super && self[:keys] == assoc_reflect[:keys]
|
410
|
+
end
|
411
|
+
|
381
412
|
# The reciprocal type of a many_to_one association is either
|
382
413
|
# a one_to_many or a one_to_one association.
|
383
414
|
def reciprocal_type
|
@@ -444,6 +475,15 @@ module Sequel
|
|
444
475
|
|
445
476
|
private
|
446
477
|
|
478
|
+
# REMOVE40: merge into reciprocal_association?
|
479
|
+
def deprecated_reciprocal_association?(assoc_reflect)
|
480
|
+
super || primary_key != assoc_reflect.primary_key
|
481
|
+
end
|
482
|
+
|
483
|
+
def reciprocal_association?(assoc_reflect)
|
484
|
+
super && self[:keys] == assoc_reflect[:keys]
|
485
|
+
end
|
486
|
+
|
447
487
|
# The reciprocal type of a one_to_many association is a many_to_one association.
|
448
488
|
def reciprocal_type
|
449
489
|
:many_to_one
|
@@ -570,25 +610,6 @@ module Sequel
|
|
570
610
|
true
|
571
611
|
end
|
572
612
|
|
573
|
-
# Returns the reciprocal association symbol, if one exists.
|
574
|
-
def reciprocal
|
575
|
-
cached_fetch(:reciprocal) do
|
576
|
-
left_keys = self[:left_keys]
|
577
|
-
right_keys = self[:right_keys]
|
578
|
-
join_table = self[:join_table]
|
579
|
-
recip = nil
|
580
|
-
associated_class.all_association_reflections.each do |assoc_reflect|
|
581
|
-
if assoc_reflect[:type] == :many_to_many && assoc_reflect[:left_keys] == right_keys &&
|
582
|
-
assoc_reflect[:right_keys] == left_keys && assoc_reflect[:join_table] == join_table &&
|
583
|
-
assoc_reflect.associated_class == self[:model]
|
584
|
-
recip = assoc_reflect[:name]
|
585
|
-
break
|
586
|
-
end
|
587
|
-
end
|
588
|
-
recip
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
613
|
# #right_primary_key qualified by the associated table
|
593
614
|
def qualified_right_primary_key
|
594
615
|
cached_fetch(:qualified_right_primary_key){qualify_assoc(right_primary_key)}
|
@@ -623,6 +644,21 @@ module Sequel
|
|
623
644
|
|
624
645
|
private
|
625
646
|
|
647
|
+
# REMOVE40: merge into reciprocal_association?
|
648
|
+
def deprecated_reciprocal_association?(assoc_reflect)
|
649
|
+
super || right_primary_keys != assoc_reflect[:left_primary_key_columns] || self[:left_primary_key_columns] != assoc_reflect.right_primary_keys
|
650
|
+
end
|
651
|
+
|
652
|
+
def reciprocal_association?(assoc_reflect)
|
653
|
+
super && assoc_reflect[:left_keys] == self[:right_keys] &&
|
654
|
+
assoc_reflect[:right_keys] == self[:left_keys] &&
|
655
|
+
assoc_reflect[:join_table] == self[:join_table]
|
656
|
+
end
|
657
|
+
|
658
|
+
def reciprocal_type
|
659
|
+
:many_to_many
|
660
|
+
end
|
661
|
+
|
626
662
|
# Split the join table into source and alias parts.
|
627
663
|
def split_join_table_alias
|
628
664
|
associated_class.dataset.split_alias(self[:join_table])
|
@@ -782,12 +818,10 @@ module Sequel
|
|
782
818
|
# :eager_graph :: The associations to eagerly load via +eager_graph+ when loading the associated object(s).
|
783
819
|
# many_to_many associations with this option cannot be eagerly loaded via +eager+.
|
784
820
|
# :eager_grapher :: A proc to use to implement eager loading via +eager_graph+, overriding the default.
|
785
|
-
# Takes
|
786
|
-
# the
|
787
|
-
# (
|
788
|
-
#
|
789
|
-
# additional key :eager_block, a callback accepting one argument, the associated dataset. This
|
790
|
-
# is used to customize the association at query time.
|
821
|
+
# Takes an options hash with the entries :self (the receiver of the eager_graph call),
|
822
|
+
# :table_alias (the alias to use for table to graph into the association), :implicit_qualifier
|
823
|
+
# (the alias that was used for the current table), and possibly :eager_block (a callback
|
824
|
+
# proc accepting the associated dataset, for per-call customization).
|
791
825
|
# Should return a copy of the dataset with the association graphed into it.
|
792
826
|
# :eager_limit_strategy :: Determines the strategy used for enforcing limits when eager loading associations via
|
793
827
|
# the +eager+ method. For one_to_one associations, no strategy is used by default, and
|
@@ -795,8 +829,8 @@ module Sequel
|
|
795
829
|
# all records but slices the resulting array after the association is retrieved. You
|
796
830
|
# can pass a +true+ value for this option to have Sequel pick what it thinks is the best
|
797
831
|
# choice for the database, or specify a specific symbol to manually select a strategy.
|
798
|
-
# one_to_one associations support :distinct_on
|
799
|
-
# *_many associations support :ruby,
|
832
|
+
# one_to_one associations support :distinct_on and :window_function.
|
833
|
+
# *_many associations support :ruby, and :window_function.
|
800
834
|
# :eager_loader :: A proc to use to implement eager loading, overriding the default. Takes a single hash argument,
|
801
835
|
# with at least the keys: :rows, which is an array of current model instances, :associations,
|
802
836
|
# which is a hash of dependent associations, :self, which is the dataset doing the eager loading,
|
@@ -922,12 +956,18 @@ module Sequel
|
|
922
956
|
# Defaults to :right_primary_key option.
|
923
957
|
# :uniq :: Adds a after_load callback that makes the array of objects unique.
|
924
958
|
def associate(type, name, opts = {}, &block)
|
925
|
-
|
959
|
+
if opts[:one_to_one] && type == :one_to_many
|
960
|
+
Sequel::Deprecation.deprecate('Raising an Error when the one_to_many type uses the :one_to_one option', "Use the one_to_one associationtype")
|
961
|
+
raise(Error, 'one_to_many association type with :one_to_one option removed, used one_to_one association type')
|
962
|
+
end
|
926
963
|
raise(Error, 'invalid association type') unless assoc_class = ASSOCIATION_TYPES[type]
|
927
|
-
raise(Error, 'Model.associate name argument must be a symbol') unless Symbol
|
964
|
+
raise(Error, 'Model.associate name argument must be a symbol') unless name.is_a?(Symbol)
|
928
965
|
raise(Error, ':eager_loader option must have an arity of 1 or 3') if opts[:eager_loader] && ![1, 3].include?(opts[:eager_loader].arity)
|
929
966
|
raise(Error, ':eager_grapher option must have an arity of 1 or 3') if opts[:eager_grapher] && ![1, 3].include?(opts[:eager_grapher].arity)
|
930
967
|
|
968
|
+
Sequel::Deprecation.deprecate('The :eager_loader association option accepting 3 arguments', "Please switch to accepting a single options hash") if opts[:eager_loader] && opts[:eager_loader].arity == 3
|
969
|
+
Sequel::Deprecation.deprecate('The :eager_grapher association option accepting 3 arguments', "Please switch to accepting a single options hash") if opts[:eager_grapher] && opts[:eager_grapher].arity == 3
|
970
|
+
|
931
971
|
# dup early so we don't modify opts
|
932
972
|
orig_opts = opts.dup
|
933
973
|
if opts[:clone]
|
@@ -1023,6 +1063,7 @@ module Sequel
|
|
1023
1063
|
|
1024
1064
|
# Use a correlated subquery to limit the results of the eager loading dataset.
|
1025
1065
|
def apply_correlated_subquery_eager_limit_strategy(ds, opts)
|
1066
|
+
Sequel::Deprecation.deprecate('The correlated_subquery eager limit strategy', 'Switch to another eager limit strategy.')
|
1026
1067
|
klass = opts.associated_class
|
1027
1068
|
kds = klass.dataset
|
1028
1069
|
dsa = ds.send(:dataset_alias, 1)
|
@@ -1460,6 +1501,7 @@ module Sequel
|
|
1460
1501
|
# Formally used internally by the associations code, like pk but doesn't raise
|
1461
1502
|
# an Error if the model has no primary key. Not used any longer, deprecated.
|
1462
1503
|
def pk_or_nil
|
1504
|
+
Sequel::Deprecation.deprecate('Model#pk_or_nil', 'There is no replacement')
|
1463
1505
|
key = primary_key
|
1464
1506
|
key.is_a?(Array) ? key.map{|k| @values[k]} : @values[key]
|
1465
1507
|
end
|
data/lib/sequel/model/base.rb
CHANGED
@@ -12,10 +12,15 @@ module Sequel
|
|
12
12
|
# (default: not set, so all columns not otherwise restricted are allowed).
|
13
13
|
attr_reader :allowed_columns
|
14
14
|
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
# REMOVE40
|
16
|
+
def cache_anonymous_models
|
17
|
+
Sequel::Deprecation.deprecate('Model.cache_anonymous_models', 'Please switch to Sequel.cache_anonymous_models')
|
18
|
+
Sequel.cache_anonymous_models
|
19
|
+
end
|
20
|
+
def cache_anonymous_models=(v)
|
21
|
+
Sequel::Deprecation.deprecate('Model.cache_anonymous_models=', 'Please switch to Sequel.cache_anonymous_models=')
|
22
|
+
Sequel.cache_anonymous_models = v
|
23
|
+
end
|
19
24
|
|
20
25
|
# Array of modules that extend this model's dataset. Stored
|
21
26
|
# so that if the model's dataset is changed, it will be extended
|
@@ -63,10 +68,14 @@ module Sequel
|
|
63
68
|
# Sequel will not check the number of rows modified (default: true).
|
64
69
|
attr_accessor :require_modification
|
65
70
|
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
# REMOVE40
|
72
|
+
def restricted_columns
|
73
|
+
Sequel::Deprecation.deprecate('Model.restricted_columns', 'Please load the blacklist_security plugin to continue using it')
|
74
|
+
@restricted_columns
|
75
|
+
end
|
76
|
+
def _restricted_columns
|
77
|
+
@restricted_columns
|
78
|
+
end
|
70
79
|
|
71
80
|
# Should be the literal primary key column name if this Model's table has a simple primary key, or
|
72
81
|
# nil if the model has a compound primary key or no primary key.
|
@@ -254,7 +263,7 @@ module Sequel
|
|
254
263
|
# sharding support.
|
255
264
|
def db=(db)
|
256
265
|
@db = db
|
257
|
-
set_dataset(db.dataset(@dataset.opts)) if @dataset
|
266
|
+
set_dataset(db.dataset.clone(@dataset.opts)) if @dataset
|
258
267
|
end
|
259
268
|
|
260
269
|
# Returns the cached schema information if available or gets it
|
@@ -342,9 +351,11 @@ module Sequel
|
|
342
351
|
# may contain setter methods.
|
343
352
|
def include(mod)
|
344
353
|
clear_setter_methods_cache
|
354
|
+
check_deprecated_after_initialize(mod.instance_methods) unless allowed_after_initialize_implementation?(mod)
|
355
|
+
Sequel::Deprecation.deprecate('Model#set_values', 'Please override Model.call, Model#_refresh_set_values, and/or Model#_create_set_values depending on the type of behavior you want to change') if mod.public_instance_methods.map{|x| x.to_s}.include?('set_values') && mod.name.to_s !~ /\ASequel::(Model|Model::Associations|Plugins::(ForceEncoding|Serialization|TypecastOnLoad|Composition|PreparedStatementsSafe|Dirty|PgTypecastOnLoad))::InstanceMethods\z/
|
345
356
|
super
|
346
357
|
end
|
347
|
-
|
358
|
+
|
348
359
|
# If possible, set the dataset for the model subclass as soon as it
|
349
360
|
# is created. Also, make sure the inherited class instance variables
|
350
361
|
# are copied into the subclass.
|
@@ -405,6 +416,8 @@ module Sequel
|
|
405
416
|
# Clear the setter_methods cache when a setter method is added
|
406
417
|
def method_added(meth)
|
407
418
|
clear_setter_methods_cache if meth.to_s =~ SETTER_METHOD_REGEXP
|
419
|
+
check_deprecated_after_initialize(meth)
|
420
|
+
Sequel::Deprecation.deprecate('Model#set_values', 'Please override Model.call, Model#_refresh_set_values, and/or Model#_create_set_values depending on the type of behavior you want to change') if meth.to_s == 'set_values'
|
408
421
|
super
|
409
422
|
end
|
410
423
|
|
@@ -431,7 +444,18 @@ module Sequel
|
|
431
444
|
m.apply(self, *args, &block) if m.respond_to?(:apply)
|
432
445
|
include(m::InstanceMethods) if plugin_module_defined?(m, :InstanceMethods)
|
433
446
|
extend(m::ClassMethods)if plugin_module_defined?(m, :ClassMethods)
|
434
|
-
|
447
|
+
if plugin_module_defined?(m, :DatasetMethods)
|
448
|
+
dataset_extend(m::DatasetMethods, :create_class_methods=>false)
|
449
|
+
# REMOVE40
|
450
|
+
m::DatasetMethods.public_instance_methods.each do |meth|
|
451
|
+
unless respond_to?(meth, true)
|
452
|
+
(class << self; self; end).send(:define_method, meth) do |*args, &block|
|
453
|
+
Sequel::Deprecation.deprecate('Automatically defining Model class methods for plugin public dataset methods', "Please modify the plugin to use Plugins.def_dataset_method for #{meth}")
|
454
|
+
dataset.send(meth, *args, &block)
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
435
459
|
end
|
436
460
|
m.configure(self, *args, &block) if m.respond_to?(:configure)
|
437
461
|
end
|
@@ -521,10 +545,10 @@ module Sequel
|
|
521
545
|
# sharding support.
|
522
546
|
def set_dataset(ds, opts={})
|
523
547
|
inherited = opts[:inherited]
|
524
|
-
|
548
|
+
case ds
|
525
549
|
when Symbol, SQL::Identifier, SQL::QualifiedIdentifier, SQL::AliasedExpression, LiteralString
|
526
550
|
self.simple_table = db.literal(ds)
|
527
|
-
db.from(ds)
|
551
|
+
ds = db.from(ds)
|
528
552
|
when Dataset
|
529
553
|
self.simple_table = if ds.send(:simple_select_all?)
|
530
554
|
ds.literal(ds.first_source_table)
|
@@ -532,11 +556,11 @@ module Sequel
|
|
532
556
|
nil
|
533
557
|
end
|
534
558
|
@db = ds.db
|
535
|
-
ds
|
536
559
|
else
|
537
560
|
raise(Error, "Model.set_dataset takes one of the following classes as an argument: Symbol, LiteralString, SQL::Identifier, SQL::QualifiedIdentifier, SQL::AliasedExpression, Dataset")
|
538
561
|
end
|
539
|
-
|
562
|
+
set_dataset_row_proc(ds)
|
563
|
+
@dataset = ds
|
540
564
|
@require_modification = Sequel::Model.require_modification.nil? ? @dataset.provides_accurate_rows_matched? : Sequel::Model.require_modification
|
541
565
|
if inherited
|
542
566
|
self.simple_table = superclass.simple_table
|
@@ -565,6 +589,9 @@ module Sequel
|
|
565
589
|
# set_primary_key [:taggable_id, :tag_id]
|
566
590
|
# end
|
567
591
|
def set_primary_key(*key)
|
592
|
+
Sequel::Deprecation.deprecate('Calling set_primary_key without arguments is deprecated and will raise an exception in Sequel 4. Please use no_primary_key to mark the model as not having a primary key.') if key.length == 0
|
593
|
+
Sequel::Deprecation.deprecate('Calling set_primary_key with multiple arguments is deprecated and will raise an exception in Sequel 4. Please pass an array of keys to setup a composite primary key.') if key.length > 1
|
594
|
+
|
568
595
|
clear_setter_methods_cache
|
569
596
|
key = key.flatten
|
570
597
|
self.simple_pk = if key.length == 1
|
@@ -590,6 +617,7 @@ module Sequel
|
|
590
617
|
# Artist.set(:name=>'Bob', :records_sold=>30000) # Error
|
591
618
|
def set_restricted_columns(*cols)
|
592
619
|
clear_setter_methods_cache
|
620
|
+
Sequel::Deprecation.deprecate('Model.set_restricted_columns', 'Please switch to Model.set_allowed_columns or use the blacklist_security plugin')
|
593
621
|
@restricted_columns = cols
|
594
622
|
end
|
595
623
|
|
@@ -600,7 +628,7 @@ module Sequel
|
|
600
628
|
else
|
601
629
|
meths = instance_methods.collect{|x| x.to_s}.grep(SETTER_METHOD_REGEXP) - RESTRICTED_SETTER_METHODS
|
602
630
|
meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && restrict_primary_key?
|
603
|
-
meths -=
|
631
|
+
meths -= _restricted_columns.map{|x| "#{x}="} if _restricted_columns
|
604
632
|
meths
|
605
633
|
end
|
606
634
|
end
|
@@ -651,6 +679,37 @@ module Sequel
|
|
651
679
|
clear_setter_methods_cache
|
652
680
|
@restrict_primary_key = false
|
653
681
|
end
|
682
|
+
|
683
|
+
# Return the model instance with the primary key, or nil if there is no matching record.
|
684
|
+
def with_pk(pk)
|
685
|
+
primary_key_lookup(pk)
|
686
|
+
end
|
687
|
+
|
688
|
+
# Return the model instance with the primary key, or raise NoMatchingRow if there is no matching record.
|
689
|
+
def with_pk!(pk)
|
690
|
+
with_pk(pk) || raise(NoMatchingRow)
|
691
|
+
end
|
692
|
+
|
693
|
+
# Add model methods that call dataset methods
|
694
|
+
Plugins.def_dataset_methods(self, DATASET_METHODS)
|
695
|
+
|
696
|
+
# REMOVE40
|
697
|
+
%w'print each_page set add_graph_aliases insert_multiple query set_overrides set_defaults to_csv paginate'.each do |meth|
|
698
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
699
|
+
def #{meth}(*args, &block)
|
700
|
+
Sequel::Deprecation.deprecate('Model.#{meth}', 'Please use Model.dataset.#{meth} instead')
|
701
|
+
dataset.#{meth}(*args, &block)
|
702
|
+
end
|
703
|
+
END
|
704
|
+
end
|
705
|
+
%w'destroy delete update'.each do |meth|
|
706
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
707
|
+
def #{meth}(*args, &block)
|
708
|
+
Sequel::Deprecation.deprecate('Model.#{meth}', 'Please use the scissors plugin or Model.dataset.#{meth} instead')
|
709
|
+
dataset.#{meth}(*args, &block)
|
710
|
+
end
|
711
|
+
END
|
712
|
+
end
|
654
713
|
|
655
714
|
private
|
656
715
|
|
@@ -665,14 +724,28 @@ module Sequel
|
|
665
724
|
end
|
666
725
|
end
|
667
726
|
|
727
|
+
# REMOVE40
|
728
|
+
def allowed_after_initialize_implementation?(mod)
|
729
|
+
mod == InstanceMethods || mod.to_s == 'Sequel::Plugins::HookClassMethods::InstanceMethods'
|
730
|
+
end
|
731
|
+
|
732
|
+
# REMOVE40
|
733
|
+
def check_deprecated_after_initialize(meths)
|
734
|
+
Array(meths).each do |meth|
|
735
|
+
Sequel::Deprecation.deprecate('The Model after_initialize hook', 'Please use the after_initialize plugin to continue using the hook') if meth.to_s == 'after_initialize'
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
668
739
|
# Add the module to the class's dataset_method_modules. Extend the dataset with the
|
669
740
|
# module if the model has a dataset. Add dataset methods to the class for all
|
670
741
|
# public dataset methods.
|
671
|
-
def dataset_extend(mod)
|
672
|
-
@dataset.extend(mod) if
|
742
|
+
def dataset_extend(mod, opts={})
|
743
|
+
@dataset.extend(mod) if @dataset
|
673
744
|
reset_instance_dataset
|
674
745
|
dataset_method_modules << mod
|
675
|
-
|
746
|
+
unless opts[:create_class_methods] == false
|
747
|
+
mod.public_instance_methods.each{|meth| def_model_dataset_method(meth)}
|
748
|
+
end
|
676
749
|
end
|
677
750
|
|
678
751
|
# Create a column accessor for a column with a method name that is hard to use in ruby code.
|
@@ -719,7 +792,7 @@ module Sequel
|
|
719
792
|
schema_hash = {}
|
720
793
|
ds_opts = dataset.opts
|
721
794
|
get_columns = proc{check_non_connection_error{columns} || []}
|
722
|
-
schema_array = check_non_connection_error{db.schema(dataset, :reload=>reload)}
|
795
|
+
schema_array = check_non_connection_error{db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
|
723
796
|
if schema_array
|
724
797
|
schema_array.each{|k,v| schema_hash[k] = v}
|
725
798
|
if ds_opts.include?(:select)
|
@@ -739,7 +812,7 @@ module Sequel
|
|
739
812
|
# if the schema information includes primary key information
|
740
813
|
if schema_array.all?{|k,v| v.has_key?(:primary_key)}
|
741
814
|
pks = schema_array.collect{|k,v| k if v[:primary_key]}.compact
|
742
|
-
pks.length > 0 ? set_primary_key(
|
815
|
+
pks.length > 0 ? set_primary_key(pks) : no_primary_key
|
743
816
|
end
|
744
817
|
# Also set the columns for the dataset, so the dataset
|
745
818
|
# doesn't have to do a query to get them.
|
@@ -780,7 +853,7 @@ module Sequel
|
|
780
853
|
# Module that the class includes that holds methods the class adds for column accessors and
|
781
854
|
# associations so that the methods can be overridden with +super+.
|
782
855
|
def overridable_methods_module
|
783
|
-
include(@overridable_methods_module = Module.new) unless
|
856
|
+
include(@overridable_methods_module = Module.new) unless @overridable_methods_module
|
784
857
|
@overridable_methods_module
|
785
858
|
end
|
786
859
|
|
@@ -792,10 +865,10 @@ module Sequel
|
|
792
865
|
(Sequel.const_defined?(module_name) &&
|
793
866
|
Sequel::Plugins.const_get(module_name) == Sequel.const_get(module_name))
|
794
867
|
begin
|
795
|
-
|
868
|
+
require "sequel/plugins/#{plugin}"
|
796
869
|
rescue LoadError => e
|
797
870
|
begin
|
798
|
-
|
871
|
+
require "sequel_#{plugin}"
|
799
872
|
rescue LoadError => e2
|
800
873
|
e.message << "; #{e2.message}"
|
801
874
|
raise e
|
@@ -848,7 +921,7 @@ module Sequel
|
|
848
921
|
# Reset the instance dataset to a modified copy of the current dataset,
|
849
922
|
# should be used whenever the model's dataset is modified.
|
850
923
|
def reset_instance_dataset
|
851
|
-
@instance_dataset = @dataset.limit(1).naked if
|
924
|
+
@instance_dataset = @dataset.limit(1).naked if @dataset
|
852
925
|
end
|
853
926
|
|
854
927
|
# Set the columns for this model and create accessor methods for each column.
|
@@ -858,6 +931,11 @@ module Sequel
|
|
858
931
|
@columns
|
859
932
|
end
|
860
933
|
|
934
|
+
# Set the dataset's row_proc to the current model.
|
935
|
+
def set_dataset_row_proc(ds)
|
936
|
+
ds.row_proc = self
|
937
|
+
end
|
938
|
+
|
861
939
|
# Reset the fast primary key lookup SQL when the simple_pk value changes.
|
862
940
|
def simple_pk=(pk)
|
863
941
|
@simple_pk = pk
|
@@ -870,9 +948,6 @@ module Sequel
|
|
870
948
|
reset_fast_pk_lookup_sql
|
871
949
|
end
|
872
950
|
|
873
|
-
# Add model methods that call dataset methods
|
874
|
-
Plugins.def_dataset_methods(self, DATASET_METHODS)
|
875
|
-
|
876
951
|
# Returns a copy of the model's dataset with custom SQL
|
877
952
|
#
|
878
953
|
# Artist.fetch("SELECT * FROM artists WHERE name LIKE 'A%'")
|
@@ -896,32 +971,29 @@ module Sequel
|
|
896
971
|
HOOKS.each{|h| class_eval("def #{h}; end", __FILE__, __LINE__)}
|
897
972
|
AROUND_HOOKS.each{|h| class_eval("def #{h}; yield end", __FILE__, __LINE__)}
|
898
973
|
|
899
|
-
#
|
900
|
-
# same name, caching the result in an instance variable. Define
|
901
|
-
# standard attr_writer method for modifying that instance variable.
|
902
|
-
#
|
903
|
-
# Do not call this method with untrusted input, as that can result in
|
904
|
-
# arbitrary code execution.
|
974
|
+
# REMOVE40
|
905
975
|
def self.class_attr_overridable(*meths) # :nodoc:
|
976
|
+
Sequel::Deprecation.deprecate('Model::InstanceMethods.class_attr_overridable', "There is no replacement planned")
|
906
977
|
meths.each{|meth| class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)}
|
907
978
|
attr_writer(*meths)
|
908
979
|
end
|
909
|
-
|
910
|
-
# Define instance method(s) that calls class method(s) of the
|
911
|
-
# same name. Replaces the construct:
|
912
|
-
#
|
913
|
-
# define_method(meth){self.class.send(meth)}
|
914
|
-
#
|
915
|
-
# Do not call this method with untrusted input, as that can result in
|
916
|
-
# arbitrary code execution.
|
917
980
|
def self.class_attr_reader(*meths) # :nodoc:
|
981
|
+
Sequel::Deprecation.deprecate('Model::InstanceMethods.class_attr_reader', "There is no replacement planned")
|
918
982
|
meths.each{|meth| class_eval("def #{meth}; self.class.#{meth} end", __FILE__, __LINE__)}
|
919
983
|
end
|
920
|
-
|
921
984
|
private_class_method :class_attr_overridable, :class_attr_reader
|
922
985
|
|
923
|
-
|
924
|
-
|
986
|
+
# Define instance method(s) that calls class method(s) of the
|
987
|
+
# same name. Replaces the construct:
|
988
|
+
#
|
989
|
+
# define_method(meth){self.class.send(meth)}
|
990
|
+
[:columns, :db, :primary_key, :db_schema].each{|meth| class_eval("def #{meth}; self.class.#{meth} end", __FILE__, __LINE__)}
|
991
|
+
|
992
|
+
# Define instance method(s) that calls class method(s) of the
|
993
|
+
# same name, caching the result in an instance variable. Define
|
994
|
+
# standard attr_writer method for modifying that instance variable.
|
995
|
+
BOOLEAN_SETTINGS.each{|meth| class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)}
|
996
|
+
attr_writer(*BOOLEAN_SETTINGS)
|
925
997
|
|
926
998
|
# The hash of attribute values. Keys are symbols with the names of the
|
927
999
|
# underlying database columns.
|
@@ -948,6 +1020,7 @@ module Sequel
|
|
948
1020
|
# end
|
949
1021
|
def initialize(values = {}, from_db = false)
|
950
1022
|
if from_db
|
1023
|
+
Sequel::Deprecation.deprecate('Passing two arguments to Model.new', 'Please use Model.call instead')
|
951
1024
|
set_values(values)
|
952
1025
|
else
|
953
1026
|
@values = {}
|
@@ -1074,7 +1147,7 @@ module Sequel
|
|
1074
1147
|
# Returns the validation errors associated with this object.
|
1075
1148
|
# See +Errors+.
|
1076
1149
|
def errors
|
1077
|
-
@errors ||=
|
1150
|
+
@errors ||= errors_class.new
|
1078
1151
|
end
|
1079
1152
|
|
1080
1153
|
# Returns true when current instance exists, false otherwise.
|
@@ -1088,7 +1161,7 @@ module Sequel
|
|
1088
1161
|
# Artist.new.exists?
|
1089
1162
|
# # => false
|
1090
1163
|
def exists?
|
1091
|
-
new? ? false : !this.get(1).nil?
|
1164
|
+
new? ? false : !this.get(SQL::AliasedExpression.new(1, :one)).nil?
|
1092
1165
|
end
|
1093
1166
|
|
1094
1167
|
# Ignore the model's setter method cache when this instances extends a module, as the
|
@@ -1292,6 +1365,7 @@ module Sequel
|
|
1292
1365
|
# Takes the following options:
|
1293
1366
|
#
|
1294
1367
|
# :changed :: save all changed columns, instead of all columns or the columns given
|
1368
|
+
# :columns :: array of specific columns that should be saved.
|
1295
1369
|
# :raise_on_failure :: set to true or false to override the current
|
1296
1370
|
# +raise_on_save_failure+ setting
|
1297
1371
|
# :server :: set the server/shard on the object before saving, and use that
|
@@ -1302,6 +1376,10 @@ module Sequel
|
|
1302
1376
|
def save(*columns)
|
1303
1377
|
raise Sequel::Error, "can't save frozen object" if frozen?
|
1304
1378
|
opts = columns.last.is_a?(Hash) ? columns.pop : {}
|
1379
|
+
|
1380
|
+
Sequel::Deprecation.deprecate('Passing columns as separate arguments to Model#save', 'Instead, provide a :columns option with the array of columns to save.') unless columns.empty?
|
1381
|
+
columns.concat(Array(opts[:columns])) if opts[:columns]
|
1382
|
+
|
1305
1383
|
set_server(opts[:server]) if opts[:server]
|
1306
1384
|
if opts[:validate] != false
|
1307
1385
|
unless checked_save_failure(opts){_valid?(true, opts)}
|
@@ -1337,9 +1415,9 @@ module Sequel
|
|
1337
1415
|
end
|
1338
1416
|
|
1339
1417
|
# Set all values using the entries in the hash, ignoring any setting of
|
1340
|
-
# allowed_columns
|
1418
|
+
# allowed_columns in the model.
|
1341
1419
|
#
|
1342
|
-
# Artist.
|
1420
|
+
# Artist.set_allowed_columns(:num_albums)
|
1343
1421
|
# artist.set_all(:name=>'Jim')
|
1344
1422
|
# artist.name # => 'Jim'
|
1345
1423
|
def set_all(hash)
|
@@ -1353,6 +1431,7 @@ module Sequel
|
|
1353
1431
|
# artist.set_except({:name=>'Jim'}, :hometown)
|
1354
1432
|
# artist.name # => 'Jim'
|
1355
1433
|
def set_except(hash, *except)
|
1434
|
+
Sequel::Deprecation.deprecate('Model#set_except', 'Please switch to Model#set_only or use the blacklist_security plugin')
|
1356
1435
|
set_restricted(hash, false, except.flatten)
|
1357
1436
|
end
|
1358
1437
|
|
@@ -1462,9 +1541,9 @@ module Sequel
|
|
1462
1541
|
end
|
1463
1542
|
|
1464
1543
|
# Update all values using the entries in the hash, ignoring any setting of
|
1465
|
-
# +allowed_columns+
|
1544
|
+
# +allowed_columns+ in the model.
|
1466
1545
|
#
|
1467
|
-
# Artist.
|
1546
|
+
# Artist.set_allowed_columns(:num_albums)
|
1468
1547
|
# artist.update_all(:name=>'Jim') # UPDATE artists SET name = 'Jim' WHERE (id = 1)
|
1469
1548
|
def update_all(hash)
|
1470
1549
|
update_restricted(hash, false, false)
|
@@ -1476,6 +1555,7 @@ module Sequel
|
|
1476
1555
|
#
|
1477
1556
|
# artist.update_except({:name=>'Jim'}, :hometown) # UPDATE artists SET name = 'Jim' WHERE (id = 1)
|
1478
1557
|
def update_except(hash, *except)
|
1558
|
+
Sequel::Deprecation.deprecate('Model#update_except', 'Please switch to Model#update_only or use the blacklist_security plugin')
|
1479
1559
|
update_restricted(hash, false, except.flatten)
|
1480
1560
|
end
|
1481
1561
|
|
@@ -1789,6 +1869,11 @@ module Sequel
|
|
1789
1869
|
@values[column] = value
|
1790
1870
|
end
|
1791
1871
|
|
1872
|
+
# Default error class used for errors.
|
1873
|
+
def errors_class
|
1874
|
+
Errors
|
1875
|
+
end
|
1876
|
+
|
1792
1877
|
# Set the columns with the given hash. By default, the same as +set+, but
|
1793
1878
|
# exists so it can be overridden. This is called only for new records, before
|
1794
1879
|
# changed_columns is cleared.
|
@@ -1869,7 +1954,7 @@ module Sequel
|
|
1869
1954
|
# well, see Model.unrestrict_primary_key to change this.
|
1870
1955
|
def setter_methods(only, except)
|
1871
1956
|
only = only.nil? ? model.allowed_columns : only
|
1872
|
-
except = except.nil? ? model.
|
1957
|
+
except = except.nil? ? model._restricted_columns : except
|
1873
1958
|
if only
|
1874
1959
|
only.map{|x| "#{x}="}
|
1875
1960
|
else
|