sequel 4.46.0 → 4.49.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 +210 -0
- data/Rakefile +1 -1
- data/doc/advanced_associations.rdoc +1 -1
- data/doc/opening_databases.rdoc +3 -2
- data/doc/release_notes/4.47.0.txt +56 -0
- data/doc/release_notes/4.48.0.txt +293 -0
- data/doc/release_notes/4.49.0.txt +222 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +30 -8
- data/lib/sequel/adapters/jdbc/as400.rb +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +46 -20
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +20 -6
- data/lib/sequel/adapters/jdbc.rb +39 -23
- data/lib/sequel/adapters/mock.rb +27 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +5 -6
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +91 -103
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +79 -25
- data/lib/sequel/adapters/shared/oracle.rb +26 -3
- data/lib/sequel/adapters/shared/postgres.rb +199 -95
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/ast_transformer.rb +1 -1
- data/lib/sequel/connection_pool/sharded_single.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/connection_pool.rb +9 -2
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +8 -8
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/dataset_defaults.rb +14 -1
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +72 -10
- data/lib/sequel/dataset/dataset_module.rb +58 -0
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +22 -11
- data/lib/sequel/dataset.rb +1 -1
- data/lib/sequel/exceptions.rb +8 -0
- data/lib/sequel/extensions/_model_pg_row.rb +5 -2
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -3
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +11 -8
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +1 -0
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +29 -25
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/server_block.rb +32 -15
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model/associations.rb +35 -7
- data/lib/sequel/model/base.rb +113 -87
- data/lib/sequel/model/dataset_module.rb +5 -43
- data/lib/sequel/model/errors.rb +2 -1
- data/lib/sequel/model/inflections.rb +17 -5
- data/lib/sequel/model.rb +26 -58
- data/lib/sequel/plugins/active_model.rb +2 -2
- data/lib/sequel/plugins/association_autoreloading.rb +2 -0
- data/lib/sequel/plugins/association_dependencies.rb +3 -3
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +2 -2
- data/lib/sequel/plugins/boolean_subsets.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +24 -13
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +3 -3
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/dataset_associations.rb +25 -13
- data/lib/sequel/plugins/defaults_setter.rb +13 -1
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +19 -12
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +2 -0
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +6 -2
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/pg_typecast_on_load.rb +2 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -24
- data/lib/sequel/plugins/serialization.rb +9 -15
- data/lib/sequel/plugins/single_table_inheritance.rb +8 -3
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +4 -2
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +14 -8
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +18 -9
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mssql_spec.rb +4 -4
- data/spec/adapters/mysql_spec.rb +83 -29
- data/spec/adapters/oracle_spec.rb +28 -24
- data/spec/adapters/postgres_spec.rb +40 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/bin_spec.rb +7 -1
- data/spec/core/connection_pool_spec.rb +45 -14
- data/spec/core/database_spec.rb +155 -0
- data/spec/core/dataset_spec.rb +219 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +106 -19
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/column_select_spec.rb +1 -0
- data/spec/extensions/composition_spec.rb +13 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +20 -8
- data/spec/extensions/defaults_setter_spec.rb +15 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/pg_typecast_on_load_spec.rb +11 -9
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +108 -94
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/serialization_spec.rb +1 -1
- data/spec/extensions/server_block_spec.rb +7 -0
- data/spec/extensions/single_table_inheritance_spec.rb +17 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +10 -5
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/associations_test.rb +8 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/model_test.rb +53 -4
- data/spec/integration/plugin_test.rb +28 -4
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/association_reflection_spec.rb +43 -1
- data/spec/model/associations_spec.rb +29 -9
- data/spec/model/class_dataset_methods_spec.rb +20 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/model_spec.rb +45 -1
- data/spec/model/plugins_spec.rb +34 -0
- data/spec/model/record_spec.rb +1 -1
- data/spec/spec_config.rb +2 -0
- metadata +11 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
# If you are using Ruby 2+, and you would like to use refinements, there
|
|
19
19
|
# is a refinement version of this in the symbol_aref_refinement extension.
|
|
20
20
|
#
|
|
21
|
-
# If you are using the ruby18_symbol_extensions, and would like symbol_aref
|
|
22
|
-
# to take affect, load the symbol_aref extension after the
|
|
23
|
-
# ruby18_symbol_extensions.
|
|
24
|
-
#
|
|
25
21
|
# Related module: Sequel::SymbolAref
|
|
26
22
|
|
|
27
23
|
if RUBY_VERSION >= '2.0'
|
|
@@ -15,6 +15,7 @@ module Sequel
|
|
|
15
15
|
@autoreloading_associations = {}
|
|
16
16
|
@cache_associations = true
|
|
17
17
|
@default_association_options = {}
|
|
18
|
+
@default_association_type_options = {}
|
|
18
19
|
@dataset_module_class = DatasetModule
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -326,6 +327,7 @@ module Sequel
|
|
|
326
327
|
|
|
327
328
|
# Alias of predicate_key, only for backwards compatibility.
|
|
328
329
|
def eager_loading_predicate_key
|
|
330
|
+
Sequel::Deprecation.deprecate("AssociationReflection#eager_loading_predicate_key", "Use #predicate_key instead")
|
|
329
331
|
predicate_key
|
|
330
332
|
end
|
|
331
333
|
|
|
@@ -1449,7 +1451,7 @@ module Sequel
|
|
|
1449
1451
|
|
|
1450
1452
|
# This module contains methods added to all association datasets
|
|
1451
1453
|
module AssociationDatasetMethods
|
|
1452
|
-
Dataset.def_deprecated_opts_setter(self, :
|
|
1454
|
+
Dataset.def_deprecated_opts_setter(self, :model_object, :association_reflection)
|
|
1453
1455
|
|
|
1454
1456
|
# The model object that created the association dataset
|
|
1455
1457
|
def model_object
|
|
@@ -1460,6 +1462,12 @@ module Sequel
|
|
|
1460
1462
|
def association_reflection
|
|
1461
1463
|
@opts[:association_reflection]
|
|
1462
1464
|
end
|
|
1465
|
+
|
|
1466
|
+
private
|
|
1467
|
+
|
|
1468
|
+
def non_sql_option?(key)
|
|
1469
|
+
super || key == :model_object || key == :association_reflection
|
|
1470
|
+
end
|
|
1463
1471
|
end
|
|
1464
1472
|
|
|
1465
1473
|
# Each kind of association adds a number of instance methods to the model class which
|
|
@@ -1526,9 +1534,15 @@ module Sequel
|
|
|
1526
1534
|
# the previous class.
|
|
1527
1535
|
attr_accessor :cache_associations
|
|
1528
1536
|
|
|
1529
|
-
# The default options to use for all associations.
|
|
1537
|
+
# The default options to use for all associations. This hash is merged into the association reflection hash for
|
|
1538
|
+
# all association reflections.
|
|
1530
1539
|
attr_accessor :default_association_options
|
|
1531
1540
|
|
|
1541
|
+
# The default options to use for all associations of a given type. This is a hash keyed by association type
|
|
1542
|
+
# symbol. If there is a value for the association type symbol key, the resulting hash will be merged into the
|
|
1543
|
+
# association reflection hash for all association reflections of that type.
|
|
1544
|
+
attr_accessor :default_association_type_options
|
|
1545
|
+
|
|
1532
1546
|
# The default :eager_limit_strategy option to use for limited or offset associations (default: true, causing Sequel
|
|
1533
1547
|
# to use what it considers the most appropriate strategy).
|
|
1534
1548
|
attr_accessor :default_eager_limit_strategy
|
|
@@ -1768,7 +1782,13 @@ module Sequel
|
|
|
1768
1782
|
orig_opts = cloned_assoc[:orig_opts].merge(orig_opts)
|
|
1769
1783
|
end
|
|
1770
1784
|
|
|
1771
|
-
opts = default_association_options
|
|
1785
|
+
opts = Hash[default_association_options]
|
|
1786
|
+
if type_options = default_association_type_options[type]
|
|
1787
|
+
opts.merge!(type_options)
|
|
1788
|
+
end
|
|
1789
|
+
opts.merge!(orig_opts)
|
|
1790
|
+
opts.merge!(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
|
|
1791
|
+
|
|
1772
1792
|
opts[:block] = block if block
|
|
1773
1793
|
if !opts.has_key?(:instance_specific) && (block || orig_opts[:block] || orig_opts[:dataset])
|
|
1774
1794
|
# It's possible the association is instance specific, in that it depends on
|
|
@@ -1784,6 +1804,7 @@ module Sequel
|
|
|
1784
1804
|
|
|
1785
1805
|
opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
|
|
1786
1806
|
if !opts.has_key?(:predicate_key) && opts.has_key?(:eager_loading_predicate_key)
|
|
1807
|
+
Sequel::Deprecation.deprecate("The :eager_loading_predicate_key association option", "Use the :predicate_key option instead")
|
|
1787
1808
|
opts[:predicate_key] = opts[:eager_loading_predicate_key]
|
|
1788
1809
|
end
|
|
1789
1810
|
opts[:graph_join_type] ||= :left_outer
|
|
@@ -1832,6 +1853,8 @@ module Sequel
|
|
|
1832
1853
|
@association_reflections.freeze.each_value(&:freeze)
|
|
1833
1854
|
@autoreloading_associations.freeze.each_value(&:freeze)
|
|
1834
1855
|
@default_association_options.freeze
|
|
1856
|
+
@default_association_type_options.freeze
|
|
1857
|
+
@default_association_type_options.each_value(&:freeze)
|
|
1835
1858
|
|
|
1836
1859
|
super
|
|
1837
1860
|
end
|
|
@@ -1869,7 +1892,7 @@ module Sequel
|
|
|
1869
1892
|
associate(:one_to_one, name, opts, &block)
|
|
1870
1893
|
end
|
|
1871
1894
|
|
|
1872
|
-
Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
|
|
1895
|
+
Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@default_association_type_options=>:hash_dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
|
|
1873
1896
|
Plugins.def_dataset_methods(self, [:eager, :eager_graph, :eager_graph_with_options, :association_join, :association_full_join, :association_inner_join, :association_left_join, :association_right_join])
|
|
1874
1897
|
|
|
1875
1898
|
private
|
|
@@ -1896,7 +1919,7 @@ module Sequel
|
|
|
1896
1919
|
# Adds the association method to the association methods module.
|
|
1897
1920
|
def def_association_method(opts)
|
|
1898
1921
|
association_module_def(opts.association_method, opts) do |*dynamic_opts, &block|
|
|
1899
|
-
Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored
|
|
1922
|
+
Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored") if dynamic_opts.length > 1
|
|
1900
1923
|
load_associated_objects(opts, dynamic_opts.length == 0 ? OPTS : dynamic_opts[0], &block)
|
|
1901
1924
|
end
|
|
1902
1925
|
end
|
|
@@ -2534,6 +2557,7 @@ module Sequel
|
|
|
2534
2557
|
end
|
|
2535
2558
|
|
|
2536
2559
|
if res == false and stop_on_false
|
|
2560
|
+
Sequel::Deprecation.deprecate("Having #{callback_type} association callback return false to cancel modification", "Instead, call Model#cancel_action inside the association callback")
|
|
2537
2561
|
raise(HookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false")
|
|
2538
2562
|
end
|
|
2539
2563
|
end
|
|
@@ -2799,7 +2823,7 @@ END
|
|
|
2799
2823
|
|
|
2800
2824
|
# If the dataset is being eagerly loaded, default to calling all
|
|
2801
2825
|
# instead of each.
|
|
2802
|
-
def
|
|
2826
|
+
def as_hash(key_column=nil, value_column=nil, opts=OPTS)
|
|
2803
2827
|
if (@opts[:eager_graph] || @opts[:eager]) && !opts.has_key?(:all)
|
|
2804
2828
|
opts = Hash[opts]
|
|
2805
2829
|
opts[:all] = true
|
|
@@ -3024,7 +3048,7 @@ END
|
|
|
3024
3048
|
# specific foreign/primary key
|
|
3025
3049
|
key_hash = {}
|
|
3026
3050
|
# Reflections for all associations to eager load
|
|
3027
|
-
reflections = eager_assoc.keys.
|
|
3051
|
+
reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
|
|
3028
3052
|
|
|
3029
3053
|
# Populate the key_hash entry for each association being eagerly loaded
|
|
3030
3054
|
reflections.each do |r|
|
|
@@ -3120,6 +3144,10 @@ END
|
|
|
3120
3144
|
end
|
|
3121
3145
|
alias one_to_one_association_filter_expression one_to_many_association_filter_expression
|
|
3122
3146
|
|
|
3147
|
+
def non_sql_option?(key)
|
|
3148
|
+
super || key == :eager || key == :eager_graph
|
|
3149
|
+
end
|
|
3150
|
+
|
|
3123
3151
|
# Build associations from the graph if #eager_graph was used,
|
|
3124
3152
|
# and/or load other associations if #eager was used.
|
|
3125
3153
|
def post_load(all_records)
|
data/lib/sequel/model/base.rb
CHANGED
|
@@ -7,16 +7,27 @@ module Sequel
|
|
|
7
7
|
|
|
8
8
|
# Class methods for Sequel::Model that implement basic model functionality.
|
|
9
9
|
#
|
|
10
|
-
# * All of the
|
|
11
|
-
# the
|
|
10
|
+
# * All of the following methods have class methods created that send the method
|
|
11
|
+
# to the model's dataset: all, as_hash, avg, count, cross_join, distinct, each,
|
|
12
|
+
# each_server, empty?, except, exclude, exclude_having, fetch_rows,
|
|
13
|
+
# filter, first, first!, for_update, from, from_self, full_join, full_outer_join,
|
|
14
|
+
# get, graph, grep, group, group_and_count, group_append, group_by, having, import,
|
|
15
|
+
# inner_join, insert, intersect, invert, join, join_table, last, left_join,
|
|
16
|
+
# left_outer_join, limit, lock_style, map, max, min, multi_insert, naked, natural_full_join,
|
|
17
|
+
# natural_join, natural_left_join, natural_right_join, offset, order, order_append, order_by,
|
|
18
|
+
# order_more, order_prepend, paged_each, qualify, reverse, reverse_order, right_join,
|
|
19
|
+
# right_outer_join, select, select_all, select_append, select_group, select_hash,
|
|
20
|
+
# select_hash_groups, select_map, select_more, select_order_map, server,
|
|
21
|
+
# single_record, single_record!, single_value, single_value!, sum, to_hash, to_hash_groups,
|
|
22
|
+
# truncate, unfiltered, ungraphed, ungrouped, union, unlimited, unordered, where, where_all,
|
|
23
|
+
# where_each, where_single_value, with, with_recursive, with_sql
|
|
12
24
|
module ClassMethods
|
|
13
25
|
# Which columns should be the only columns allowed in a call to a mass assignment method (e.g. set)
|
|
14
26
|
# (default: not set, so all columns not otherwise restricted are allowed).
|
|
15
27
|
attr_reader :allowed_columns # SEQUEL5: Deprecate after release
|
|
16
28
|
|
|
17
|
-
# Whether to cache the anonymous models created by Sequel::Model(). This is
|
|
18
|
-
# required for reloading them correctly (avoiding the superclass mismatch).
|
|
19
|
-
# by default for backwards compatibility.
|
|
29
|
+
# Whether to cache the anonymous models created by Sequel::Model(), true by default. This is
|
|
30
|
+
# required for reloading them correctly (avoiding the superclass mismatch).
|
|
20
31
|
attr_accessor :cache_anonymous_models
|
|
21
32
|
|
|
22
33
|
# Array of modules that extend this model's dataset. Stored
|
|
@@ -215,16 +226,20 @@ module Sequel
|
|
|
215
226
|
end
|
|
216
227
|
|
|
217
228
|
def initialize_copy(_)
|
|
218
|
-
Sequel::Deprecation.deprecate("Model.clone", "Create a subclass of the model instead of cloning it
|
|
229
|
+
Sequel::Deprecation.deprecate("Model.clone", "Create a subclass of the model instead of cloning it")
|
|
219
230
|
# raise(Error, "cannot dup/clone a Sequel::Model class") # SEQUEL5
|
|
220
231
|
super
|
|
221
232
|
end
|
|
222
233
|
def dup
|
|
223
|
-
Sequel::Deprecation.deprecate("Model.dup", "Create a subclass of the model instead of duping it
|
|
234
|
+
Sequel::Deprecation.deprecate("Model.dup", "Create a subclass of the model instead of duping it")
|
|
224
235
|
# raise(Error, "cannot dup/clone a Sequel::Model class") # SEQUEL5
|
|
225
236
|
super
|
|
226
237
|
end
|
|
227
238
|
|
|
239
|
+
def <<(arg)
|
|
240
|
+
Sequel::Deprecation.deprecate("Sequel::Model.<<", "Switch to using #insert")
|
|
241
|
+
dataset << (arg)
|
|
242
|
+
end
|
|
228
243
|
|
|
229
244
|
# Returns the first record from the database matching the conditions.
|
|
230
245
|
# If a hash is given, it is used as the conditions. If another
|
|
@@ -661,7 +676,7 @@ module Sequel
|
|
|
661
676
|
# end
|
|
662
677
|
def inherited(subclass)
|
|
663
678
|
super
|
|
664
|
-
ivs = subclass.instance_variables.
|
|
679
|
+
ivs = subclass.instance_variables.map(&:to_s)
|
|
665
680
|
inherited_instance_variables.each do |iv, dup|
|
|
666
681
|
next if ivs.include?(iv.to_s)
|
|
667
682
|
if (sup_class_value = instance_variable_get(iv)) && dup
|
|
@@ -700,14 +715,14 @@ module Sequel
|
|
|
700
715
|
pluralize(underscore(demodulize(name))).to_sym
|
|
701
716
|
end
|
|
702
717
|
|
|
703
|
-
# Calls #call with the values hash.
|
|
718
|
+
# Calls #call with the values hash.
|
|
704
719
|
def load(values)
|
|
705
720
|
call(values)
|
|
706
721
|
end
|
|
707
722
|
|
|
708
723
|
# Clear the setter_methods cache when a setter method is added
|
|
709
724
|
def method_added(meth)
|
|
710
|
-
clear_setter_methods_cache if meth.to_s
|
|
725
|
+
clear_setter_methods_cache if meth.to_s.end_with?('=')
|
|
711
726
|
super
|
|
712
727
|
end
|
|
713
728
|
|
|
@@ -976,18 +991,26 @@ module Sequel
|
|
|
976
991
|
end
|
|
977
992
|
|
|
978
993
|
# Add model methods that call dataset methods
|
|
979
|
-
Plugins.def_dataset_methods(self,
|
|
994
|
+
Plugins.def_dataset_methods(self, (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server]) - [:<<, :and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases])
|
|
995
|
+
# SEQUEL5: add :set_graph_aliases to remove list and remove :and
|
|
980
996
|
|
|
981
997
|
private
|
|
982
998
|
|
|
983
999
|
# Yield to the passed block and swallow all errors other than DatabaseConnectionErrors.
|
|
984
|
-
def check_non_connection_error
|
|
1000
|
+
def check_non_connection_error(do_raise=require_valid_table)
|
|
985
1001
|
begin
|
|
986
1002
|
db.transaction(:savepoint=>:only){yield}
|
|
987
1003
|
rescue Sequel::DatabaseConnectionError
|
|
988
1004
|
raise
|
|
989
1005
|
rescue Sequel::Error
|
|
990
|
-
|
|
1006
|
+
case do_raise
|
|
1007
|
+
when nil
|
|
1008
|
+
Sequel::Deprecation.deprecate("Setting a model class dataset to an invalid dataset", "Either use a valid dataset or set require_valid_table = false for the model class")
|
|
1009
|
+
when false
|
|
1010
|
+
# nothing
|
|
1011
|
+
else
|
|
1012
|
+
raise
|
|
1013
|
+
end
|
|
991
1014
|
end
|
|
992
1015
|
end
|
|
993
1016
|
|
|
@@ -1000,6 +1023,7 @@ module Sequel
|
|
|
1000
1023
|
ds = db.from(ds)
|
|
1001
1024
|
when Dataset
|
|
1002
1025
|
if ds.joined_dataset?
|
|
1026
|
+
# raise Error, "Using a joined dataset as a model dataset is not support, use from_self on the dataset to wrap it in a subquery" # SEQUEL5
|
|
1003
1027
|
Sequel::Deprecation.deprecate("Using a joined dataset as a Sequel::Model dataset", respond_to?(:cti_base_model) ? "Use the class_table_inheritance plugin :alias option in #{cti_base_model.inspect}" : "Call from_self on the dataset to wrap it in a subquery")
|
|
1004
1028
|
end
|
|
1005
1029
|
|
|
@@ -1038,9 +1062,9 @@ module Sequel
|
|
|
1038
1062
|
# use a string to define the method for speed. For other columns names, use a block.
|
|
1039
1063
|
def def_column_accessor(*columns)
|
|
1040
1064
|
clear_setter_methods_cache
|
|
1041
|
-
columns, bad_columns = columns.partition{|x|
|
|
1065
|
+
columns, bad_columns = columns.partition{|x| /\A[A-Za-z_][A-Za-z0-9_]*\z/.match(x.to_s)}
|
|
1042
1066
|
bad_columns.each{|x| def_bad_column_accessor(x)}
|
|
1043
|
-
im = instance_methods.
|
|
1067
|
+
im = instance_methods.map(&:to_s)
|
|
1044
1068
|
columns.each do |column|
|
|
1045
1069
|
meth = "#{column}="
|
|
1046
1070
|
overridable_methods_module.module_eval("def #{column}; self[:#{column}] end", __FILE__, __LINE__) unless im.include?(column.to_s)
|
|
@@ -1054,7 +1078,7 @@ module Sequel
|
|
|
1054
1078
|
def def_model_dataset_method(meth)
|
|
1055
1079
|
return if respond_to?(meth, true)
|
|
1056
1080
|
|
|
1057
|
-
if meth.to_s =~
|
|
1081
|
+
if meth.to_s =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/
|
|
1058
1082
|
instance_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__)
|
|
1059
1083
|
else
|
|
1060
1084
|
(class << self; self; end).send(:define_method, meth){|*args, &block| dataset.send(meth, *args, &block)}
|
|
@@ -1097,14 +1121,14 @@ module Sequel
|
|
|
1097
1121
|
schema_hash = {}
|
|
1098
1122
|
ds_opts = dataset.opts
|
|
1099
1123
|
get_columns = proc{check_non_connection_error{columns} || []}
|
|
1100
|
-
schema_array = check_non_connection_error{db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
|
|
1124
|
+
schema_array = check_non_connection_error(false){db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
|
|
1101
1125
|
if schema_array
|
|
1102
1126
|
schema_array.each{|k,v| schema_hash[k] = v}
|
|
1103
1127
|
|
|
1104
1128
|
# Set the primary key(s) based on the schema information,
|
|
1105
1129
|
# if the schema information includes primary key information
|
|
1106
1130
|
if schema_array.all?{|k,v| v.has_key?(:primary_key)}
|
|
1107
|
-
pks = schema_array.
|
|
1131
|
+
pks = schema_array.map{|k,v| k if v[:primary_key]}.compact
|
|
1108
1132
|
pks.length > 0 ? set_primary_key(pks) : no_primary_key
|
|
1109
1133
|
end
|
|
1110
1134
|
|
|
@@ -1119,7 +1143,7 @@ module Sequel
|
|
|
1119
1143
|
# Dataset is for a single table with all columns,
|
|
1120
1144
|
# so set the columns based on the order they were
|
|
1121
1145
|
# returned by the schema.
|
|
1122
|
-
cols = schema_array.
|
|
1146
|
+
cols = schema_array.map{|k,v| k}
|
|
1123
1147
|
set_columns(cols)
|
|
1124
1148
|
# Also set the columns for the dataset, so the dataset
|
|
1125
1149
|
# doesn't have to do a query to get them.
|
|
@@ -1141,18 +1165,46 @@ module Sequel
|
|
|
1141
1165
|
# SEQUEL5: Remove allowed_columns handling
|
|
1142
1166
|
allowed_columns.map{|x| "#{x}="}
|
|
1143
1167
|
else
|
|
1144
|
-
meths = instance_methods.
|
|
1168
|
+
meths = instance_methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
|
|
1145
1169
|
meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && restrict_primary_key?
|
|
1146
1170
|
meths
|
|
1147
1171
|
end
|
|
1148
1172
|
end
|
|
1149
1173
|
|
|
1150
1174
|
# A hash of instance variables to automatically set up in subclasses.
|
|
1151
|
-
#
|
|
1152
|
-
#
|
|
1153
|
-
#
|
|
1175
|
+
# Keys are instance variable symbols, values should be:
|
|
1176
|
+
# nil :: Assign directly from superclass to subclass (frozen objects)
|
|
1177
|
+
# :dup :: Dup object when assigning from superclass to subclass (mutable objects)
|
|
1178
|
+
# :hash_dup :: Assign hash with same keys, but dup all the values
|
|
1179
|
+
# Proc :: Call with subclass to do the assignment
|
|
1154
1180
|
def inherited_instance_variables
|
|
1155
|
-
|
|
1181
|
+
{
|
|
1182
|
+
:@allowed_columns=>:dup, # SEQUEL5: Remove
|
|
1183
|
+
:@cache_anonymous_models=>nil,
|
|
1184
|
+
:@dataset_method_modules=>:dup,
|
|
1185
|
+
:@dataset_module_class=>nil,
|
|
1186
|
+
:@db=>nil,
|
|
1187
|
+
:@default_set_fields_options=>:dup,
|
|
1188
|
+
:@fast_instance_delete_sql=>nil,
|
|
1189
|
+
:@fast_pk_lookup_sql=>nil,
|
|
1190
|
+
:@finder_loaders=>:dup, # SEQUEL5: Remove
|
|
1191
|
+
:@finders=>:dup, # SEQUEL5: Remove
|
|
1192
|
+
:@plugins=>:dup,
|
|
1193
|
+
:@primary_key=>nil,
|
|
1194
|
+
:@raise_on_save_failure=>nil,
|
|
1195
|
+
:@raise_on_typecast_failure=>nil,
|
|
1196
|
+
:@require_modification=>nil,
|
|
1197
|
+
:@require_valid_table=>nil,
|
|
1198
|
+
:@restrict_primary_key=>nil,
|
|
1199
|
+
:@setter_methods=>nil,
|
|
1200
|
+
:@simple_pk=>nil,
|
|
1201
|
+
:@simple_table=>nil,
|
|
1202
|
+
:@strict_param_setting=>nil,
|
|
1203
|
+
:@typecast_empty_string_to_nil=>nil,
|
|
1204
|
+
:@typecast_on_assignment=>nil,
|
|
1205
|
+
:@use_after_commit_rollback=>nil,
|
|
1206
|
+
:@use_transactions=>nil
|
|
1207
|
+
}
|
|
1156
1208
|
end
|
|
1157
1209
|
|
|
1158
1210
|
# For the given opts hash and default name or :class option, add a
|
|
@@ -1196,6 +1248,7 @@ module Sequel
|
|
|
1196
1248
|
rescue LoadError => e
|
|
1197
1249
|
begin
|
|
1198
1250
|
require "sequel_#{plugin}"
|
|
1251
|
+
Sequel::Deprecation.deprecate("requiring 'sequel_#{plugin}' to load a plugin", "Update the #{plugin} plugin to be required via 'sequel/plugins/#{plugin}'")
|
|
1199
1252
|
rescue LoadError => e2
|
|
1200
1253
|
e.message << "; #{e2.message}"
|
|
1201
1254
|
raise e
|
|
@@ -1249,6 +1302,7 @@ module Sequel
|
|
|
1249
1302
|
ds.fetch_rows(sql){|r| return ds.row_proc.call(r)}
|
|
1250
1303
|
nil
|
|
1251
1304
|
elsif dataset.joined_dataset?
|
|
1305
|
+
# SEQUEL5: Remove as joined model datasets are not allowed
|
|
1252
1306
|
dataset.first(qualified_primary_key_hash(pk))
|
|
1253
1307
|
else
|
|
1254
1308
|
dataset.first(primary_key_hash(pk))
|
|
@@ -1311,19 +1365,21 @@ module Sequel
|
|
|
1311
1365
|
|
|
1312
1366
|
# Sequel::Model instance methods that implement basic model functionality.
|
|
1313
1367
|
#
|
|
1314
|
-
# * All of the
|
|
1368
|
+
# * All of the model before/after/around hooks are implemented as instance methods that are called
|
|
1315
1369
|
# by Sequel when the appropriate action occurs. For example, when destroying
|
|
1316
1370
|
# a model object, Sequel will call +around_destroy+, which will call +before_destroy+, do
|
|
1317
1371
|
# the destroy, and then call +after_destroy+.
|
|
1318
1372
|
# * The following instance_methods all call the class method of the same
|
|
1319
1373
|
# name: columns, db, primary_key, db_schema.
|
|
1320
|
-
# *
|
|
1321
|
-
#
|
|
1322
|
-
#
|
|
1323
|
-
#
|
|
1374
|
+
# * The following accessor methods are defined via metaprogramming:
|
|
1375
|
+
# raise_on_save_failure, raise_on_typecast_failure, require_modification,
|
|
1376
|
+
# strict_param_setting, typecast_empty_string_to_nil, typecast_on_assignment,
|
|
1377
|
+
# and use_transactions. The setter methods will change the setting for the
|
|
1378
|
+
# instance, and the getter methods will check for an instance setting, then
|
|
1379
|
+
# try the class setting if no instance setting has been set.
|
|
1324
1380
|
module InstanceMethods
|
|
1325
1381
|
HOOKS.each{|h| class_eval("def #{h}; end", __FILE__, __LINE__)}
|
|
1326
|
-
|
|
1382
|
+
[:around_create, :around_update, :around_save, :around_destroy, :around_validation].each{|h| class_eval("def #{h}; yield end", __FILE__, __LINE__)}
|
|
1327
1383
|
|
|
1328
1384
|
# Define instance method(s) that calls class method(s) of the
|
|
1329
1385
|
# same name. Replaces the construct:
|
|
@@ -1334,8 +1390,13 @@ module Sequel
|
|
|
1334
1390
|
# Define instance method(s) that calls class method(s) of the
|
|
1335
1391
|
# same name, caching the result in an instance variable. Define
|
|
1336
1392
|
# standard attr_writer method for modifying that instance variable.
|
|
1337
|
-
|
|
1338
|
-
|
|
1393
|
+
[:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, \
|
|
1394
|
+
:raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions,
|
|
1395
|
+
:use_after_commit_rollback # SEQUEL5: Remove
|
|
1396
|
+
].each do |meth|
|
|
1397
|
+
class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)
|
|
1398
|
+
attr_writer(meth)
|
|
1399
|
+
end
|
|
1339
1400
|
|
|
1340
1401
|
# The hash of attribute values. Keys are symbols with the names of the
|
|
1341
1402
|
# underlying database columns. The returned hash is a reference to the
|
|
@@ -1882,7 +1943,7 @@ module Sequel
|
|
|
1882
1943
|
|
|
1883
1944
|
# Clear the setter_methods cache when a method is added
|
|
1884
1945
|
def singleton_method_added(meth)
|
|
1885
|
-
@singleton_setter_added = true if meth.to_s
|
|
1946
|
+
@singleton_setter_added = true if meth.to_s.end_with?('=')
|
|
1886
1947
|
super
|
|
1887
1948
|
end
|
|
1888
1949
|
|
|
@@ -1895,6 +1956,7 @@ module Sequel
|
|
|
1895
1956
|
raise Error, "No dataset for model #{model}" unless ds = model.instance_dataset
|
|
1896
1957
|
|
|
1897
1958
|
cond = if ds.joined_dataset?
|
|
1959
|
+
# SEQUEL5: Remove as joined model datasets are now allowed
|
|
1898
1960
|
qualified_pk_hash
|
|
1899
1961
|
else
|
|
1900
1962
|
pk_hash
|
|
@@ -2136,7 +2198,7 @@ module Sequel
|
|
|
2136
2198
|
sh = {:server=>this_server}
|
|
2137
2199
|
uacr = use_after_commit_rollback
|
|
2138
2200
|
if uacr.nil? ? (method(:after_rollback).owner != InstanceMethods) : uacr
|
|
2139
|
-
Sequel::Deprecation.deprecate("Model#after_rollback", "Instead, call db.after_rollback in Model#before_save
|
|
2201
|
+
Sequel::Deprecation.deprecate("Model#after_rollback", "Instead, call db.after_rollback in Model#before_save")
|
|
2140
2202
|
db.after_rollback(sh){after_rollback}
|
|
2141
2203
|
end
|
|
2142
2204
|
pk = nil
|
|
@@ -2203,7 +2265,7 @@ module Sequel
|
|
|
2203
2265
|
raise_hook_failure(:around_save) unless called_save
|
|
2204
2266
|
_after_save(pk) # SEQUEL5: Remove
|
|
2205
2267
|
if uacr.nil? ? (method(:after_commit).owner != InstanceMethods) : uacr
|
|
2206
|
-
Sequel::Deprecation.deprecate("Model#after_commit", "Instead, call db.after_commit in Model#after_save
|
|
2268
|
+
Sequel::Deprecation.deprecate("Model#after_commit", "Instead, call db.after_commit in Model#after_save")
|
|
2207
2269
|
db.after_commit(sh){after_commit}
|
|
2208
2270
|
end
|
|
2209
2271
|
self
|
|
@@ -2436,7 +2498,7 @@ module Sequel
|
|
|
2436
2498
|
if type.is_a?(Array)
|
|
2437
2499
|
type.map{|x| "#{x}="}
|
|
2438
2500
|
else
|
|
2439
|
-
meths = methods.
|
|
2501
|
+
meths = methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
|
|
2440
2502
|
meths -= Array(primary_key).map{|x| "#{x}="} if type != :all && primary_key && model.restrict_primary_key?
|
|
2441
2503
|
meths
|
|
2442
2504
|
end
|
|
@@ -2600,15 +2662,15 @@ module Sequel
|
|
|
2600
2662
|
end
|
|
2601
2663
|
end
|
|
2602
2664
|
|
|
2603
|
-
# This allows you to call +
|
|
2665
|
+
# This allows you to call +as_hash+ without any arguments, which will
|
|
2604
2666
|
# result in a hash with the primary key value being the key and the
|
|
2605
2667
|
# model object being the value.
|
|
2606
2668
|
#
|
|
2607
|
-
# Artist.dataset.
|
|
2669
|
+
# Artist.dataset.as_hash # SELECT * FROM artists
|
|
2608
2670
|
# # => {1=>#<Artist {:id=>1, ...}>,
|
|
2609
2671
|
# # 2=>#<Artist {:id=>2, ...}>,
|
|
2610
2672
|
# # ...}
|
|
2611
|
-
def
|
|
2673
|
+
def as_hash(key_column=nil, value_column=nil, opts=OPTS)
|
|
2612
2674
|
if key_column
|
|
2613
2675
|
super
|
|
2614
2676
|
else
|
|
@@ -2617,50 +2679,9 @@ module Sequel
|
|
|
2617
2679
|
end
|
|
2618
2680
|
end
|
|
2619
2681
|
|
|
2620
|
-
#
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
#
|
|
2624
|
-
# Artist.where_all(:id=>[1,2,3])
|
|
2625
|
-
# # SELECT * FROM artists WHERE (id IN (1, 2, 3))
|
|
2626
|
-
def where_all(cond, &block)
|
|
2627
|
-
if loader = _model_where_loader
|
|
2628
|
-
loader.all(filter_expr(cond), &block)
|
|
2629
|
-
else
|
|
2630
|
-
where(cond).all(&block)
|
|
2631
|
-
end
|
|
2632
|
-
end
|
|
2633
|
-
|
|
2634
|
-
# Iterate over all rows matching the given filter condition,
|
|
2635
|
-
# yielding each row to the given block. Basically the same as where(cond).each(&block),
|
|
2636
|
-
# except it can be optimized to not create an intermediate dataset.
|
|
2637
|
-
#
|
|
2638
|
-
# Artist.where_each(:id=>[1,2,3]){|row| p row}
|
|
2639
|
-
# # SELECT * FROM artists WHERE (id IN (1, 2, 3))
|
|
2640
|
-
def where_each(cond, &block)
|
|
2641
|
-
if loader = _model_where_loader
|
|
2642
|
-
loader.each(filter_expr(cond), &block)
|
|
2643
|
-
else
|
|
2644
|
-
where(cond).each(&block)
|
|
2645
|
-
end
|
|
2646
|
-
end
|
|
2647
|
-
|
|
2648
|
-
# Filter the datasets using the given filter condition, then return a single value.
|
|
2649
|
-
# This assumes that the dataset has already been setup to limit the selection to
|
|
2650
|
-
# a single column. Basically the same as where(cond).single_value,
|
|
2651
|
-
# except it can be optimized to not create an intermediate dataset.
|
|
2652
|
-
#
|
|
2653
|
-
# Artist.select(:name).where_single_value(:id=>1)
|
|
2654
|
-
# # SELECT name FROM artists WHERE (id = 1) LIMIT 1
|
|
2655
|
-
def where_single_value(cond)
|
|
2656
|
-
if loader = cached_placeholder_literalizer(:_model_where_single_value_loader) do |pl|
|
|
2657
|
-
single_value_ds.where(pl.arg)
|
|
2658
|
-
end
|
|
2659
|
-
|
|
2660
|
-
loader.get(filter_expr(cond))
|
|
2661
|
-
else
|
|
2662
|
-
where(cond).single_value
|
|
2663
|
-
end
|
|
2682
|
+
# Alias of as_hash for backwards compatibility.
|
|
2683
|
+
def to_hash(*a)
|
|
2684
|
+
as_hash(*a)
|
|
2664
2685
|
end
|
|
2665
2686
|
|
|
2666
2687
|
# Given a primary key value, return the first record in the dataset with that primary key
|
|
@@ -2689,11 +2710,12 @@ module Sequel
|
|
|
2689
2710
|
|
|
2690
2711
|
private
|
|
2691
2712
|
|
|
2692
|
-
#
|
|
2713
|
+
# SEQUEL5: Remove
|
|
2693
2714
|
def _model_where_loader
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2715
|
+
# :nocov:
|
|
2716
|
+
Sequel::Deprecation.deprecate("Dataset#_model_where_loader", "Use _where_loader instead")
|
|
2717
|
+
_where_loader
|
|
2718
|
+
# :nocov:
|
|
2697
2719
|
end
|
|
2698
2720
|
|
|
2699
2721
|
# If the dataset is not already ordered, and the model has a primary key,
|
|
@@ -2720,6 +2742,10 @@ module Sequel
|
|
|
2720
2742
|
where(cond).limit(1)
|
|
2721
2743
|
end
|
|
2722
2744
|
end
|
|
2745
|
+
|
|
2746
|
+
def non_sql_option?(key)
|
|
2747
|
+
super || key == :model
|
|
2748
|
+
end
|
|
2723
2749
|
end
|
|
2724
2750
|
|
|
2725
2751
|
extend ClassMethods
|
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
module Sequel
|
|
4
4
|
class Model
|
|
5
5
|
# This Module subclass is used by Model.dataset_module
|
|
6
|
-
# to add dataset methods to classes.
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
class DatasetModule < ::Module
|
|
6
|
+
# to add dataset methods to classes. In addition to the
|
|
7
|
+
# methods offered by Dataset::DatasetModule, it also
|
|
8
|
+
# automatically creates class methods for public dataset
|
|
9
|
+
# methods.
|
|
10
|
+
class DatasetModule < Dataset::DatasetModule
|
|
12
11
|
# Store the model related to this dataset module.
|
|
13
12
|
def initialize(model)
|
|
14
13
|
@model = model
|
|
@@ -19,43 +18,6 @@ module Sequel
|
|
|
19
18
|
where(name, *args, &block)
|
|
20
19
|
end
|
|
21
20
|
|
|
22
|
-
%w'where exclude exclude_having having'.map(&:to_sym).each do |meth|
|
|
23
|
-
define_method(meth) do |name, *args, &block|
|
|
24
|
-
if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
|
|
25
|
-
define_method(name){send(meth, *args, &block)}
|
|
26
|
-
else
|
|
27
|
-
key = :"_#{meth}_#{name}_ds"
|
|
28
|
-
define_method(name) do
|
|
29
|
-
cached_dataset(key){send(meth, *args)}
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
meths = (<<-METHS).split.map(&:to_sym)
|
|
36
|
-
distinct grep group group_and_count group_append
|
|
37
|
-
limit offset order order_append order_prepend
|
|
38
|
-
select select_all select_append select_group server
|
|
39
|
-
METHS
|
|
40
|
-
|
|
41
|
-
# Define a method in the module
|
|
42
|
-
def self.def_dataset_caching_method(mod, meth)
|
|
43
|
-
mod.send(:define_method, meth) do |name, *args, &block|
|
|
44
|
-
if block
|
|
45
|
-
define_method(name){send(meth, *args, &block)}
|
|
46
|
-
else
|
|
47
|
-
key = :"_#{meth}_#{name}_ds"
|
|
48
|
-
define_method(name) do
|
|
49
|
-
cached_dataset(key){send(meth, *args)}
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
meths.each do |meth|
|
|
56
|
-
def_dataset_caching_method(self, meth)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
21
|
private
|
|
60
22
|
|
|
61
23
|
# Add a class method to the related model that
|
data/lib/sequel/model/errors.rb
CHANGED
|
@@ -6,6 +6,7 @@ module Sequel
|
|
|
6
6
|
# with a few convenience methods.
|
|
7
7
|
class Errors < ::Hash
|
|
8
8
|
ATTRIBUTE_JOINER = ' and '.freeze
|
|
9
|
+
Sequel::Deprecation.deprecate_constant(self, :ATTRIBUTE_JOINER)
|
|
9
10
|
|
|
10
11
|
# Adds an error for the given attribute.
|
|
11
12
|
#
|
|
@@ -40,7 +41,7 @@ module Sequel
|
|
|
40
41
|
def full_messages
|
|
41
42
|
inject([]) do |m, kv|
|
|
42
43
|
att, errors = *kv
|
|
43
|
-
errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(
|
|
44
|
+
errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(' and ')} #{e}")}
|
|
44
45
|
m
|
|
45
46
|
end
|
|
46
47
|
end
|