sequel 4.49.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +70 -0
- data/README.rdoc +195 -136
- data/Rakefile +26 -42
- data/bin/sequel +3 -5
- data/doc/advanced_associations.rdoc +86 -163
- data/doc/association_basics.rdoc +197 -274
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +66 -43
- data/doc/code_order.rdoc +1 -8
- data/doc/core_extensions.rdoc +81 -56
- data/doc/dataset_basics.rdoc +8 -17
- data/doc/dataset_filtering.rdoc +81 -86
- data/doc/extensions.rdoc +3 -10
- data/doc/mass_assignment.rdoc +73 -30
- data/doc/migration.rdoc +19 -36
- data/doc/model_dataset_method_design.rdoc +14 -17
- data/doc/model_hooks.rdoc +15 -25
- data/doc/model_plugins.rdoc +10 -10
- data/doc/mssql_stored_procedures.rdoc +3 -3
- data/doc/object_model.rdoc +52 -70
- data/doc/opening_databases.rdoc +39 -32
- data/doc/postgresql.rdoc +48 -38
- data/doc/prepared_statements.rdoc +27 -22
- data/doc/querying.rdoc +173 -150
- data/doc/reflection.rdoc +5 -6
- data/doc/release_notes/5.0.0.txt +159 -0
- data/doc/schema_modification.rdoc +63 -60
- data/doc/security.rdoc +97 -88
- data/doc/sharding.rdoc +43 -30
- data/doc/sql.rdoc +53 -65
- data/doc/testing.rdoc +3 -5
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +18 -17
- data/doc/validations.rdoc +48 -45
- data/doc/virtual_rows.rdoc +87 -115
- data/lib/sequel.rb +1 -1
- data/lib/sequel/adapters/ado.rb +9 -25
- data/lib/sequel/adapters/ado/access.rb +7 -13
- data/lib/sequel/adapters/ado/mssql.rb +2 -9
- data/lib/sequel/adapters/amalgalite.rb +3 -18
- data/lib/sequel/adapters/ibmdb.rb +9 -45
- data/lib/sequel/adapters/jdbc.rb +13 -73
- data/lib/sequel/adapters/jdbc/db2.rb +8 -37
- data/lib/sequel/adapters/jdbc/derby.rb +4 -50
- data/lib/sequel/adapters/jdbc/h2.rb +4 -25
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -26
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -9
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -11
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +4 -26
- data/lib/sequel/adapters/jdbc/postgresql.rb +2 -31
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +4 -17
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -13
- data/lib/sequel/adapters/jdbc/transactions.rb +1 -14
- data/lib/sequel/adapters/mock.rb +4 -30
- data/lib/sequel/adapters/mysql.rb +7 -44
- data/lib/sequel/adapters/mysql2.rb +5 -23
- data/lib/sequel/adapters/odbc.rb +0 -19
- data/lib/sequel/adapters/odbc/db2.rb +1 -1
- data/lib/sequel/adapters/odbc/mssql.rb +4 -12
- data/lib/sequel/adapters/odbc/oracle.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +7 -13
- data/lib/sequel/adapters/postgres.rb +13 -57
- data/lib/sequel/adapters/postgresql.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +11 -51
- data/lib/sequel/adapters/shared/db2.rb +3 -61
- data/lib/sequel/adapters/shared/mssql.rb +21 -157
- data/lib/sequel/adapters/shared/mysql.rb +23 -224
- data/lib/sequel/adapters/shared/oracle.rb +13 -41
- data/lib/sequel/adapters/shared/postgres.rb +44 -259
- data/lib/sequel/adapters/shared/sqlanywhere.rb +4 -96
- data/lib/sequel/adapters/shared/sqlite.rb +12 -101
- data/lib/sequel/adapters/sqlanywhere.rb +4 -23
- data/lib/sequel/adapters/sqlite.rb +2 -19
- data/lib/sequel/adapters/tinytds.rb +5 -15
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -4
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +3 -6
- data/lib/sequel/adapters/utils/replace.rb +0 -5
- data/lib/sequel/adapters/utils/stored_procedures.rb +0 -2
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +2 -0
- data/lib/sequel/ast_transformer.rb +3 -94
- data/lib/sequel/connection_pool.rb +26 -28
- data/lib/sequel/connection_pool/sharded_single.rb +1 -4
- data/lib/sequel/connection_pool/sharded_threaded.rb +97 -95
- data/lib/sequel/connection_pool/single.rb +0 -2
- data/lib/sequel/connection_pool/threaded.rb +94 -110
- data/lib/sequel/core.rb +42 -101
- data/lib/sequel/database.rb +12 -2
- data/lib/sequel/database/connecting.rb +23 -60
- data/lib/sequel/database/dataset.rb +6 -9
- data/lib/sequel/database/dataset_defaults.rb +4 -48
- data/lib/sequel/database/features.rb +5 -4
- data/lib/sequel/database/logging.rb +2 -9
- data/lib/sequel/database/misc.rb +23 -55
- data/lib/sequel/database/query.rb +8 -13
- data/lib/sequel/database/schema_generator.rb +89 -64
- data/lib/sequel/database/schema_methods.rb +61 -79
- data/lib/sequel/database/transactions.rb +4 -24
- data/lib/sequel/dataset.rb +18 -10
- data/lib/sequel/dataset/actions.rb +53 -107
- data/lib/sequel/dataset/dataset_module.rb +3 -15
- data/lib/sequel/dataset/features.rb +30 -30
- data/lib/sequel/dataset/graph.rb +40 -49
- data/lib/sequel/dataset/misc.rb +12 -37
- data/lib/sequel/dataset/placeholder_literalizer.rb +4 -4
- data/lib/sequel/dataset/prepared_statements.rb +23 -51
- data/lib/sequel/dataset/query.rb +71 -155
- data/lib/sequel/dataset/sql.rb +30 -225
- data/lib/sequel/deprecated.rb +18 -27
- data/lib/sequel/exceptions.rb +1 -17
- data/lib/sequel/extensions/_model_pg_row.rb +0 -7
- data/lib/sequel/extensions/_pretty_table.rb +1 -3
- data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
- data/lib/sequel/extensions/connection_expiration.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +11 -11
- data/lib/sequel/extensions/core_extensions.rb +39 -49
- data/lib/sequel/extensions/core_refinements.rb +39 -45
- data/lib/sequel/extensions/current_datetime_timestamp.rb +0 -4
- data/lib/sequel/extensions/date_arithmetic.rb +7 -7
- data/lib/sequel/extensions/duplicate_columns_handler.rb +12 -9
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
- data/lib/sequel/extensions/eval_inspect.rb +4 -11
- data/lib/sequel/extensions/freeze_datasets.rb +1 -69
- data/lib/sequel/extensions/from_block.rb +1 -35
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/identifier_mangling.rb +9 -19
- data/lib/sequel/extensions/implicit_subquery.rb +2 -2
- data/lib/sequel/extensions/inflector.rb +4 -4
- data/lib/sequel/extensions/migration.rb +23 -40
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -84
- data/lib/sequel/extensions/null_dataset.rb +2 -8
- data/lib/sequel/extensions/pagination.rb +1 -17
- data/lib/sequel/extensions/pg_array.rb +20 -189
- data/lib/sequel/extensions/pg_hstore.rb +11 -50
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
- data/lib/sequel/extensions/pg_inet.rb +2 -15
- data/lib/sequel/extensions/pg_interval.rb +1 -20
- data/lib/sequel/extensions/pg_json.rb +7 -27
- data/lib/sequel/extensions/pg_loose_count.rb +1 -1
- data/lib/sequel/extensions/pg_range.rb +6 -121
- data/lib/sequel/extensions/pg_range_ops.rb +1 -3
- data/lib/sequel/extensions/pg_row.rb +5 -77
- data/lib/sequel/extensions/pg_row_ops.rb +2 -13
- data/lib/sequel/extensions/query.rb +3 -4
- data/lib/sequel/extensions/round_timestamps.rb +0 -6
- data/lib/sequel/extensions/schema_dumper.rb +13 -13
- data/lib/sequel/extensions/select_remove.rb +3 -3
- data/lib/sequel/extensions/split_array_nil.rb +2 -2
- data/lib/sequel/extensions/sql_comments.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +11 -8
- data/lib/sequel/extensions/symbol_aref.rb +6 -20
- data/lib/sequel/model.rb +27 -62
- data/lib/sequel/model/associations.rb +128 -131
- data/lib/sequel/model/base.rb +171 -711
- data/lib/sequel/model/default_inflections.rb +1 -1
- data/lib/sequel/model/errors.rb +0 -3
- data/lib/sequel/model/exceptions.rb +2 -6
- data/lib/sequel/model/inflections.rb +1 -26
- data/lib/sequel/model/plugins.rb +1 -0
- data/lib/sequel/plugins/active_model.rb +2 -5
- data/lib/sequel/plugins/association_dependencies.rb +15 -15
- data/lib/sequel/plugins/association_pks.rb +14 -28
- data/lib/sequel/plugins/association_proxies.rb +6 -7
- data/lib/sequel/plugins/auto_validations.rb +4 -4
- data/lib/sequel/plugins/before_after_save.rb +0 -43
- data/lib/sequel/plugins/blacklist_security.rb +9 -8
- data/lib/sequel/plugins/boolean_readers.rb +3 -3
- data/lib/sequel/plugins/boolean_subsets.rb +2 -2
- data/lib/sequel/plugins/caching.rb +5 -5
- data/lib/sequel/plugins/class_table_inheritance.rb +71 -102
- data/lib/sequel/plugins/column_conflicts.rb +2 -2
- data/lib/sequel/plugins/column_select.rb +2 -2
- data/lib/sequel/plugins/composition.rb +15 -24
- data/lib/sequel/plugins/constraint_validations.rb +4 -3
- data/lib/sequel/plugins/csv_serializer.rb +13 -20
- data/lib/sequel/plugins/dataset_associations.rb +2 -2
- data/lib/sequel/plugins/def_dataset_method.rb +5 -5
- data/lib/sequel/plugins/defaults_setter.rb +1 -1
- data/lib/sequel/plugins/delay_add_association.rb +1 -1
- data/lib/sequel/plugins/finder.rb +16 -10
- data/lib/sequel/plugins/force_encoding.rb +1 -7
- data/lib/sequel/plugins/hook_class_methods.rb +4 -106
- data/lib/sequel/plugins/input_transformer.rb +10 -11
- data/lib/sequel/plugins/insert_returning_select.rb +1 -9
- data/lib/sequel/plugins/instance_filters.rb +5 -5
- data/lib/sequel/plugins/instance_hooks.rb +7 -52
- data/lib/sequel/plugins/inverted_subsets.rb +3 -1
- data/lib/sequel/plugins/json_serializer.rb +19 -19
- data/lib/sequel/plugins/lazy_attributes.rb +1 -10
- data/lib/sequel/plugins/list.rb +6 -6
- data/lib/sequel/plugins/many_through_many.rb +11 -8
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/nested_attributes.rb +18 -31
- data/lib/sequel/plugins/optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/pg_array_associations.rb +8 -2
- data/lib/sequel/plugins/pg_row.rb +2 -11
- data/lib/sequel/plugins/prepared_statements.rb +13 -66
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +7 -7
- data/lib/sequel/plugins/serialization.rb +15 -33
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +2 -8
- data/lib/sequel/plugins/single_table_inheritance.rb +10 -13
- data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
- data/lib/sequel/plugins/static_cache.rb +8 -9
- data/lib/sequel/plugins/string_stripper.rb +3 -3
- data/lib/sequel/plugins/subclasses.rb +1 -1
- data/lib/sequel/plugins/subset_conditions.rb +2 -2
- data/lib/sequel/plugins/table_select.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
- data/lib/sequel/plugins/timestamps.rb +6 -7
- data/lib/sequel/plugins/touch.rb +4 -8
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +2 -2
- data/lib/sequel/plugins/unlimited_update.rb +1 -7
- data/lib/sequel/plugins/update_or_create.rb +3 -3
- data/lib/sequel/plugins/update_refresh.rb +3 -3
- data/lib/sequel/plugins/uuid.rb +7 -11
- data/lib/sequel/plugins/validation_class_methods.rb +10 -9
- data/lib/sequel/plugins/validation_contexts.rb +4 -4
- data/lib/sequel/plugins/validation_helpers.rb +26 -25
- data/lib/sequel/plugins/whitelist_security.rb +13 -9
- data/lib/sequel/plugins/xml_serializer.rb +24 -25
- data/lib/sequel/sql.rb +145 -276
- data/lib/sequel/timezones.rb +8 -22
- data/lib/sequel/version.rb +2 -2
- data/spec/adapter_spec.rb +1 -1
- data/spec/adapters/db2_spec.rb +2 -103
- data/spec/adapters/mssql_spec.rb +89 -68
- data/spec/adapters/mysql_spec.rb +101 -480
- data/spec/adapters/oracle_spec.rb +1 -9
- data/spec/adapters/postgres_spec.rb +312 -565
- data/spec/adapters/spec_helper.rb +12 -31
- data/spec/adapters/sqlanywhere_spec.rb +2 -77
- data/spec/adapters/sqlite_spec.rb +8 -146
- data/spec/bin_spec.rb +11 -16
- data/spec/core/connection_pool_spec.rb +173 -74
- data/spec/core/database_spec.rb +64 -244
- data/spec/core/dataset_spec.rb +81 -415
- data/spec/core/deprecated_spec.rb +3 -3
- data/spec/core/expression_filters_spec.rb +37 -144
- data/spec/core/mock_adapter_spec.rb +176 -4
- data/spec/core/object_graph_spec.rb +11 -60
- data/spec/core/placeholder_literalizer_spec.rb +1 -14
- data/spec/core/schema_generator_spec.rb +51 -40
- data/spec/core/schema_spec.rb +74 -77
- data/spec/core/spec_helper.rb +6 -24
- data/spec/core/version_spec.rb +1 -1
- data/spec/core_extensions_spec.rb +7 -83
- data/spec/core_model_spec.rb +2 -2
- data/spec/deprecation_helper.rb +2 -14
- data/spec/extensions/accessed_columns_spec.rb +1 -1
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +2 -2
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +4 -59
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/auto_literal_strings_spec.rb +1 -12
- data/spec/extensions/auto_validations_spec.rb +1 -1
- data/spec/extensions/blacklist_security_spec.rb +1 -1
- data/spec/extensions/blank_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/caching_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +35 -1086
- data/spec/extensions/column_conflicts_spec.rb +1 -1
- data/spec/extensions/column_select_spec.rb +4 -4
- data/spec/extensions/columns_introspection_spec.rb +1 -1
- data/spec/extensions/columns_updated_spec.rb +1 -1
- data/spec/extensions/composition_spec.rb +1 -7
- data/spec/extensions/connection_expiration_spec.rb +3 -3
- data/spec/extensions/connection_validator_spec.rb +3 -3
- data/spec/extensions/constraint_validations_plugin_spec.rb +1 -1
- data/spec/extensions/constraint_validations_spec.rb +1 -1
- data/spec/extensions/core_refinements_spec.rb +1 -3
- data/spec/extensions/csv_serializer_spec.rb +4 -9
- data/spec/extensions/current_datetime_timestamp_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +2 -1
- data/spec/extensions/dataset_source_alias_spec.rb +1 -1
- data/spec/extensions/date_arithmetic_spec.rb +3 -3
- data/spec/extensions/def_dataset_method_spec.rb +1 -1
- data/spec/extensions/defaults_setter_spec.rb +2 -2
- data/spec/extensions/delay_add_association_spec.rb +8 -9
- data/spec/extensions/dirty_spec.rb +1 -1
- data/spec/extensions/duplicate_columns_handler_spec.rb +1 -1
- data/spec/extensions/eager_each_spec.rb +2 -2
- data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
- data/spec/extensions/error_splitter_spec.rb +1 -1
- data/spec/extensions/error_sql_spec.rb +1 -1
- data/spec/extensions/eval_inspect_spec.rb +1 -1
- data/spec/extensions/finder_spec.rb +1 -1
- data/spec/extensions/force_encoding_spec.rb +2 -5
- data/spec/extensions/freeze_datasets_spec.rb +1 -1
- data/spec/extensions/graph_each_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +1 -194
- data/spec/extensions/identifier_mangling_spec.rb +17 -170
- data/spec/extensions/implicit_subquery_spec.rb +1 -5
- data/spec/extensions/inflector_spec.rb +1 -1
- data/spec/extensions/input_transformer_spec.rb +7 -2
- data/spec/extensions/insert_returning_select_spec.rb +1 -1
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/instance_hooks_spec.rb +1 -95
- data/spec/extensions/inverted_subsets_spec.rb +1 -1
- data/spec/extensions/json_serializer_spec.rb +1 -1
- data/spec/extensions/lazy_attributes_spec.rb +1 -7
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +1 -1
- data/spec/extensions/migration_spec.rb +2 -2
- data/spec/extensions/modification_detection_spec.rb +1 -1
- data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
- data/spec/extensions/named_timezones_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +1 -29
- data/spec/extensions/null_dataset_spec.rb +1 -11
- data/spec/extensions/optimistic_locking_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +1 -1
- data/spec/extensions/pg_array_associations_spec.rb +4 -1
- data/spec/extensions/pg_array_ops_spec.rb +1 -1
- data/spec/extensions/pg_array_spec.rb +3 -48
- data/spec/extensions/pg_enum_spec.rb +1 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +1 -1
- data/spec/extensions/pg_hstore_spec.rb +23 -32
- data/spec/extensions/pg_inet_ops_spec.rb +1 -1
- data/spec/extensions/pg_inet_spec.rb +1 -14
- data/spec/extensions/pg_interval_spec.rb +3 -13
- data/spec/extensions/pg_json_ops_spec.rb +1 -1
- data/spec/extensions/pg_json_spec.rb +1 -13
- data/spec/extensions/pg_loose_count_spec.rb +1 -1
- data/spec/extensions/pg_range_ops_spec.rb +1 -1
- data/spec/extensions/pg_range_spec.rb +3 -88
- data/spec/extensions/pg_row_ops_spec.rb +1 -1
- data/spec/extensions/pg_row_plugin_spec.rb +1 -1
- data/spec/extensions/pg_row_spec.rb +1 -44
- data/spec/extensions/pg_static_cache_updater_spec.rb +1 -1
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/prepared_statements_spec.rb +13 -48
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +1 -12
- data/spec/extensions/rcte_tree_spec.rb +1 -1
- data/spec/extensions/round_timestamps_spec.rb +1 -5
- data/spec/extensions/s_spec.rb +1 -1
- data/spec/extensions/schema_caching_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +1 -1
- data/spec/extensions/select_remove_spec.rb +1 -1
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +2 -14
- data/spec/extensions/server_block_spec.rb +1 -1
- data/spec/extensions/server_logging_spec.rb +2 -2
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/shared_caching_spec.rb +1 -28
- data/spec/extensions/single_table_inheritance_spec.rb +2 -5
- data/spec/extensions/singular_table_names_spec.rb +1 -1
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +5 -27
- data/spec/extensions/split_array_nil_spec.rb +1 -1
- data/spec/extensions/split_values_spec.rb +1 -1
- data/spec/extensions/sql_comments_spec.rb +1 -1
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/static_cache_spec.rb +1 -1
- data/spec/extensions/string_agg_spec.rb +2 -2
- data/spec/extensions/string_date_time_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +1 -1
- data/spec/extensions/subclasses_spec.rb +1 -1
- data/spec/extensions/subset_conditions_spec.rb +1 -1
- data/spec/extensions/symbol_aref_refinement_spec.rb +1 -1
- data/spec/extensions/symbol_as_refinement_spec.rb +1 -1
- data/spec/extensions/table_select_spec.rb +4 -4
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -6
- data/spec/extensions/thread_local_timezones_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +3 -3
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/tree_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +1 -1
- data/spec/extensions/unlimited_update_spec.rb +1 -1
- data/spec/extensions/update_or_create_spec.rb +1 -1
- data/spec/extensions/update_primary_key_spec.rb +4 -3
- data/spec/extensions/update_refresh_spec.rb +1 -1
- data/spec/extensions/uuid_spec.rb +10 -12
- data/spec/extensions/validate_associated_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +3 -3
- data/spec/extensions/validation_contexts_spec.rb +1 -1
- data/spec/extensions/validation_helpers_spec.rb +10 -44
- data/spec/extensions/whitelist_security_spec.rb +5 -5
- data/spec/extensions/xml_serializer_spec.rb +3 -3
- data/spec/guards_helper.rb +2 -1
- data/spec/integration/associations_test.rb +1 -23
- data/spec/integration/database_test.rb +7 -7
- data/spec/integration/dataset_test.rb +5 -47
- data/spec/integration/eager_loader_test.rb +1 -1
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +4 -82
- data/spec/integration/plugin_test.rb +6 -22
- data/spec/integration/prepared_statement_test.rb +8 -88
- data/spec/integration/schema_test.rb +6 -6
- data/spec/integration/spec_helper.rb +13 -21
- data/spec/integration/timezone_test.rb +5 -5
- data/spec/integration/transaction_test.rb +3 -55
- data/spec/integration/type_test.rb +9 -9
- data/spec/model/association_reflection_spec.rb +24 -9
- data/spec/model/associations_spec.rb +124 -303
- data/spec/model/base_spec.rb +18 -137
- data/spec/model/class_dataset_methods_spec.rb +2 -20
- data/spec/model/dataset_methods_spec.rb +1 -20
- data/spec/model/eager_loading_spec.rb +17 -11
- data/spec/model/hooks_spec.rb +5 -300
- data/spec/model/inflector_spec.rb +1 -1
- data/spec/model/model_spec.rb +15 -320
- data/spec/model/plugins_spec.rb +2 -16
- data/spec/model/record_spec.rb +29 -121
- data/spec/model/spec_helper.rb +5 -15
- data/spec/model/validations_spec.rb +1 -1
- data/spec/sequel_warning.rb +1 -12
- metadata +8 -64
- data/doc/active_record.rdoc +0 -927
- data/lib/sequel/adapters/cubrid.rb +0 -160
- data/lib/sequel/adapters/do.rb +0 -166
- data/lib/sequel/adapters/do/mysql.rb +0 -69
- data/lib/sequel/adapters/do/postgres.rb +0 -46
- data/lib/sequel/adapters/do/sqlite3.rb +0 -41
- data/lib/sequel/adapters/jdbc/as400.rb +0 -92
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -65
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -37
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -34
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -34
- data/lib/sequel/adapters/odbc/progress.rb +0 -12
- data/lib/sequel/adapters/shared/cubrid.rb +0 -245
- data/lib/sequel/adapters/shared/firebird.rb +0 -261
- data/lib/sequel/adapters/shared/informix.rb +0 -63
- data/lib/sequel/adapters/shared/progress.rb +0 -40
- data/lib/sequel/adapters/swift.rb +0 -169
- data/lib/sequel/adapters/swift/mysql.rb +0 -50
- data/lib/sequel/adapters/swift/postgres.rb +0 -49
- data/lib/sequel/adapters/swift/sqlite.rb +0 -48
- data/lib/sequel/adapters/utils/pg_types.rb +0 -4
- data/lib/sequel/dataset/mutation.rb +0 -98
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +0 -117
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -8
- data/lib/sequel/extensions/filter_having.rb +0 -65
- data/lib/sequel/extensions/hash_aliases.rb +0 -51
- data/lib/sequel/extensions/meta_def.rb +0 -37
- data/lib/sequel/extensions/query_literals.rb +0 -86
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -26
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -133
- data/lib/sequel/extensions/set_overrides.rb +0 -82
- data/lib/sequel/no_core_ext.rb +0 -4
- data/lib/sequel/plugins/association_autoreloading.rb +0 -11
- data/lib/sequel/plugins/identifier_columns.rb +0 -49
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -11
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -90
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -137
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -71
- data/lib/sequel/plugins/schema.rb +0 -84
- data/lib/sequel/plugins/scissors.rb +0 -37
- data/spec/core/dataset_mutation_spec.rb +0 -253
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +0 -314
- data/spec/extensions/before_after_save_spec.rb +0 -40
- data/spec/extensions/filter_having_spec.rb +0 -42
- data/spec/extensions/from_block_spec.rb +0 -21
- data/spec/extensions/hash_aliases_spec.rb +0 -26
- data/spec/extensions/identifier_columns_spec.rb +0 -19
- data/spec/extensions/meta_def_spec.rb +0 -35
- data/spec/extensions/no_auto_literal_strings_spec.rb +0 -69
- data/spec/extensions/pg_typecast_on_load_spec.rb +0 -70
- data/spec/extensions/prepared_statements_associations_spec.rb +0 -212
- data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -40
- data/spec/extensions/query_literals_spec.rb +0 -185
- data/spec/extensions/schema_spec.rb +0 -123
- data/spec/extensions/scissors_spec.rb +0 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -118
- data/spec/extensions/set_overrides_spec.rb +0 -75
@@ -41,26 +41,12 @@ else
|
|
41
41
|
alias_method :aref_before_sequel, :[]
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
else
|
51
|
-
aref_before_sequel(v)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
else
|
55
|
-
def [](*v)
|
56
|
-
arg = v.first if v.length == 1
|
57
|
-
|
58
|
-
case arg
|
59
|
-
when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
|
60
|
-
Sequel::SQL::QualifiedIdentifier.new(self, arg)
|
61
|
-
else
|
62
|
-
respond_to?(:aref_before_sequel) ? aref_before_sequel(*v) : super(*v)
|
63
|
-
end
|
44
|
+
def [](v)
|
45
|
+
case v
|
46
|
+
when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
|
47
|
+
Sequel::SQL::QualifiedIdentifier.new(self, v)
|
48
|
+
else
|
49
|
+
aref_before_sequel(v)
|
64
50
|
end
|
65
51
|
end
|
66
52
|
end
|
data/lib/sequel/model.rb
CHANGED
@@ -1,24 +1,13 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'core'
|
4
4
|
|
5
5
|
module Sequel
|
6
|
-
# Delegate to Sequel::Model, only for backwards compatibility.
|
7
|
-
def self.cache_anonymous_models
|
8
|
-
Sequel::Deprecation.deprecate("Sequel.cache_anonymous_models", "Use Sequel::Model.cache_anonymous_models")
|
9
|
-
Model.cache_anonymous_models
|
10
|
-
end
|
11
|
-
|
12
|
-
# Delegate to Sequel::Model, only for backwards compatibility.
|
13
|
-
def self.cache_anonymous_models=(v)
|
14
|
-
Sequel::Deprecation.deprecate("Sequel.cache_anonymous_models=", "Use Sequel::Model.cache_anonymous_models=")
|
15
|
-
Model.cache_anonymous_models = v
|
16
|
-
end
|
17
|
-
|
18
6
|
# <tt>Sequel::Model</tt> is an object relational mapper built on top of Sequel core. Each
|
19
7
|
# model class is backed by a dataset instance, and many dataset methods can be
|
20
8
|
# called directly on the class. Model datasets return rows as model instances,
|
21
|
-
# which
|
9
|
+
# which are wrappers around the underlying hash that allow easily updating or
|
10
|
+
# deleting the individual row.
|
22
11
|
#
|
23
12
|
# <tt>Sequel::Model</tt> is built completely out of plugins. Plugins can override any class,
|
24
13
|
# instance, or dataset method defined by a previous plugin and call super to get the default
|
@@ -31,47 +20,30 @@ module Sequel
|
|
31
20
|
class Model
|
32
21
|
OPTS = Sequel::OPTS
|
33
22
|
|
34
|
-
|
35
|
-
Sequel::Deprecation.deprecate_constant(self, :DATASET_METHODS)
|
36
|
-
BOOLEAN_SETTINGS = [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions, :use_after_commit_rollback]
|
37
|
-
Sequel::Deprecation.deprecate_constant(self, :BOOLEAN_SETTINGS)
|
38
|
-
BEFORE_HOOKS = [:before_create, :before_update, :before_save, :before_destroy, :before_validation]
|
39
|
-
Sequel::Deprecation.deprecate_constant(self, :BEFORE_HOOKS)
|
40
|
-
AFTER_HOOKS = [:after_create, :after_update, :after_save, :after_destroy, :after_validation, :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback]
|
41
|
-
Sequel::Deprecation.deprecate_constant(self, :AFTER_HOOKS)
|
42
|
-
AROUND_HOOKS = [:around_create, :around_update, :around_save, :around_destroy, :around_validation]
|
43
|
-
Sequel::Deprecation.deprecate_constant(self, :AROUND_HOOKS)
|
44
|
-
NORMAL_METHOD_NAME_REGEXP = /\A[A-Za-z_][A-Za-z0-9_]*\z/
|
45
|
-
Sequel::Deprecation.deprecate_constant(self, :NORMAL_METHOD_NAME_REGEXP)
|
46
|
-
SETTER_METHOD_REGEXP = /=\z/
|
47
|
-
Sequel::Deprecation.deprecate_constant(self, :SETTER_METHOD_REGEXP)
|
48
|
-
ANONYMOUS_MODEL_CLASSES = @Model_cache = {}
|
49
|
-
Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES)
|
50
|
-
ANONYMOUS_MODEL_CLASSES_MUTEX = Mutex.new
|
51
|
-
Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES_MUTEX)
|
52
|
-
INHERITED_INSTANCE_VARIABLES = { :@allowed_columns=>:dup, :@dataset_method_modules=>:dup, :@primary_key=>nil, :@use_transactions=>nil, :@raise_on_save_failure=>nil, :@require_modification=>nil, :@restrict_primary_key=>nil, :@simple_pk=>nil, :@simple_table=>nil, :@strict_param_setting=>nil, :@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil, :@raise_on_typecast_failure=>nil, :@plugins=>:dup, :@setter_methods=>nil, :@use_after_commit_rollback=>nil, :@fast_pk_lookup_sql=>nil, :@fast_instance_delete_sql=>nil, :@finders=>:dup, :@finder_loaders=>:dup, :@db=>nil, :@default_set_fields_options=>:dup, :@require_valid_table=>nil, :@cache_anonymous_models=>nil, :@dataset_module_class=>nil}
|
53
|
-
Sequel::Deprecation.deprecate_constant(self, :INHERITED_INSTANCE_VARIABLES)
|
54
|
-
|
55
|
-
# Empty instance methods to create that the user can override to get hook/callback behavior.
|
23
|
+
# Empty instance methods to create that the user can override.
|
56
24
|
# Just like any other method defined by Sequel, if you override one of these, you should
|
57
|
-
# call +super+ to get the default behavior (while empty by default, they
|
25
|
+
# call +super+ to get the default behavior (while empty by default, they are often overridden
|
58
26
|
# by plugins). See the {"Model Hooks" guide}[rdoc-ref:doc/model_hooks.rdoc] for
|
59
27
|
# more detail on hooks.
|
60
|
-
HOOKS = [
|
61
|
-
:after_create,
|
62
|
-
:
|
63
|
-
|
28
|
+
HOOKS = [
|
29
|
+
:after_create,
|
30
|
+
:after_destroy,
|
31
|
+
:after_save,
|
32
|
+
:after_update,
|
33
|
+
:after_validation,
|
34
|
+
:before_create,
|
35
|
+
:before_destroy,
|
36
|
+
:before_save,
|
37
|
+
:before_update,
|
38
|
+
:before_validation
|
39
|
+
].freeze
|
64
40
|
|
65
|
-
@allowed_columns = nil # SEQUEL5: Remove
|
66
41
|
@cache_anonymous_models = true
|
67
42
|
@db = nil
|
68
43
|
@db_schema = nil
|
69
44
|
@dataset = nil
|
70
45
|
@dataset_method_modules = []
|
71
|
-
@default_eager_limit_strategy = true
|
72
46
|
@default_set_fields_options = {}
|
73
|
-
@finders = {} # SEQUEL5: Remove
|
74
|
-
@finder_loaders = {} # SEQUEL5: Remove
|
75
47
|
@overridable_methods_module = nil
|
76
48
|
@fast_pk_lookup_sql = nil
|
77
49
|
@fast_instance_delete_sql = nil
|
@@ -80,7 +52,7 @@ module Sequel
|
|
80
52
|
@raise_on_save_failure = true
|
81
53
|
@raise_on_typecast_failure = false
|
82
54
|
@require_modification = nil
|
83
|
-
@require_valid_table =
|
55
|
+
@require_valid_table = true
|
84
56
|
@restrict_primary_key = true
|
85
57
|
@setter_methods = nil
|
86
58
|
@simple_pk = nil
|
@@ -88,12 +60,17 @@ module Sequel
|
|
88
60
|
@strict_param_setting = true
|
89
61
|
@typecast_empty_string_to_nil = true
|
90
62
|
@typecast_on_assignment = true
|
91
|
-
@use_after_commit_rollback = nil
|
92
63
|
@use_transactions = true
|
93
64
|
|
94
|
-
|
65
|
+
require_relative "model/default_inflections"
|
66
|
+
require_relative "model/inflections"
|
67
|
+
require_relative "model/plugins"
|
68
|
+
require_relative "model/dataset_module"
|
69
|
+
require_relative "model/base"
|
70
|
+
require_relative "model/exceptions"
|
71
|
+
require_relative "model/errors"
|
95
72
|
if !defined?(::SEQUEL_NO_ASSOCIATIONS) && !ENV.has_key?('SEQUEL_NO_ASSOCIATIONS')
|
96
|
-
|
73
|
+
require_relative 'model/associations'
|
97
74
|
plugin Model::Associations
|
98
75
|
end
|
99
76
|
|
@@ -101,18 +78,6 @@ module Sequel
|
|
101
78
|
|
102
79
|
# The setter methods (methods ending with =) that are never allowed
|
103
80
|
# to be called automatically via +set+/+update+/+new+/etc..
|
104
|
-
RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).select{|l| l.end_with?('=')}
|
105
|
-
|
106
|
-
# SEQUEL5: Remove
|
107
|
-
class DeprecatedColumnsUpdated # :nodoc:
|
108
|
-
def initialize(columns_updated)
|
109
|
-
@columns_updated = columns_updated
|
110
|
-
end
|
111
|
-
|
112
|
-
def method_missing(*args, &block)
|
113
|
-
Sequel::Deprecation.deprecate("Accessing @columns_updated directly", "Use the columns_updated plugin and switch to the columns_updated method")
|
114
|
-
@columns_updated.send(*args, &block)
|
115
|
-
end
|
116
|
-
end
|
81
|
+
RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).select{|l| l.end_with?('=')}.freeze
|
117
82
|
end
|
118
83
|
end
|
@@ -10,10 +10,11 @@ module Sequel
|
|
10
10
|
|
11
11
|
# Set an empty association reflection hash in the model
|
12
12
|
def self.apply(model)
|
13
|
-
model.
|
13
|
+
model.instance_exec do
|
14
14
|
@association_reflections = {}
|
15
15
|
@autoreloading_associations = {}
|
16
16
|
@cache_associations = true
|
17
|
+
@default_eager_limit_strategy = true
|
17
18
|
@default_association_options = {}
|
18
19
|
@default_association_type_options = {}
|
19
20
|
@dataset_module_class = DatasetModule
|
@@ -33,27 +34,27 @@ module Sequel
|
|
33
34
|
|
34
35
|
# Name symbol for the _add internal association method
|
35
36
|
def _add_method
|
36
|
-
|
37
|
+
self[:_add_method]
|
37
38
|
end
|
38
39
|
|
39
40
|
# Name symbol for the _remove_all internal association method
|
40
41
|
def _remove_all_method
|
41
|
-
|
42
|
+
self[:_remove_all_method]
|
42
43
|
end
|
43
44
|
|
44
45
|
# Name symbol for the _remove internal association method
|
45
46
|
def _remove_method
|
46
|
-
|
47
|
+
self[:_remove_method]
|
47
48
|
end
|
48
49
|
|
49
50
|
# Name symbol for the _setter association method
|
50
51
|
def _setter_method
|
51
|
-
|
52
|
+
self[:_setter_method]
|
52
53
|
end
|
53
54
|
|
54
55
|
# Name symbol for the add association method
|
55
56
|
def add_method
|
56
|
-
|
57
|
+
self[:add_method]
|
57
58
|
end
|
58
59
|
|
59
60
|
# Name symbol for association method, the same as the name of the association.
|
@@ -81,9 +82,10 @@ module Sequel
|
|
81
82
|
|
82
83
|
# Apply all non-instance specific changes to the given dataset and return it.
|
83
84
|
def apply_dataset_changes(ds)
|
84
|
-
ds = ds.with_extend(AssociationDatasetMethods).
|
85
|
-
|
86
|
-
|
85
|
+
ds = ds.with_extend(AssociationDatasetMethods).clone(:association_reflection => self)
|
86
|
+
if exts = self[:reverse_extend]
|
87
|
+
ds = ds.with_extend(*exts)
|
88
|
+
end
|
87
89
|
ds = ds.select(*select) if select
|
88
90
|
if c = self[:conditions]
|
89
91
|
ds = (c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
|
@@ -191,7 +193,7 @@ module Sequel
|
|
191
193
|
|
192
194
|
# Name symbol for the dataset association method
|
193
195
|
def dataset_method
|
194
|
-
|
196
|
+
self[:dataset_method]
|
195
197
|
end
|
196
198
|
|
197
199
|
# Whether the dataset needs a primary key to function, true by default.
|
@@ -325,12 +327,6 @@ module Sequel
|
|
325
327
|
false
|
326
328
|
end
|
327
329
|
|
328
|
-
# Alias of predicate_key, only for backwards compatibility.
|
329
|
-
def eager_loading_predicate_key
|
330
|
-
Sequel::Deprecation.deprecate("AssociationReflection#eager_loading_predicate_key", "Use #predicate_key instead")
|
331
|
-
predicate_key
|
332
|
-
end
|
333
|
-
|
334
330
|
# Whether to eagerly graph a lazy dataset, true by default. If this
|
335
331
|
# is false, the association won't respect the :eager_graph option
|
336
332
|
# when loading the association for a single record.
|
@@ -362,6 +358,7 @@ module Sequel
|
|
362
358
|
finalize_settings.each do |meth, key|
|
363
359
|
next if has_key?(key)
|
364
360
|
|
361
|
+
# Allow calling private methods to make sure caching is done appropriately
|
365
362
|
send(meth)
|
366
363
|
self[key] = cache.delete(key) if cache.has_key?(key)
|
367
364
|
end
|
@@ -401,7 +398,7 @@ module Sequel
|
|
401
398
|
end
|
402
399
|
end
|
403
400
|
|
404
|
-
# Show which type of reflection this is, and a guess at what
|
401
|
+
# Show which type of reflection this is, and a guess at what code was used to create the
|
405
402
|
# association.
|
406
403
|
def inspect
|
407
404
|
o = self[:orig_opts].dup
|
@@ -450,9 +447,7 @@ module Sequel
|
|
450
447
|
predicate_key_methods.map{|k| object.get_column_value(k)}
|
451
448
|
end
|
452
449
|
|
453
|
-
# Qualify +col+ with the given table name.
|
454
|
-
# return an array of qualified columns. Only qualifies Symbols and SQL::Identifier
|
455
|
-
# values, other values are not modified.
|
450
|
+
# Qualify +col+ with the given table name.
|
456
451
|
def qualify(table, col)
|
457
452
|
transform(col) do |k|
|
458
453
|
case k
|
@@ -505,7 +500,7 @@ module Sequel
|
|
505
500
|
|
506
501
|
# Name symbol for the remove_all_ association method
|
507
502
|
def remove_all_method
|
508
|
-
|
503
|
+
self[:remove_all_method]
|
509
504
|
end
|
510
505
|
|
511
506
|
# Whether associated objects need to be removed from the association before
|
@@ -516,7 +511,7 @@ module Sequel
|
|
516
511
|
|
517
512
|
# Name symbol for the remove_ association method
|
518
513
|
def remove_method
|
519
|
-
|
514
|
+
self[:remove_method]
|
520
515
|
end
|
521
516
|
|
522
517
|
# Whether to check that an object to be disassociated is already associated to this object, false by default.
|
@@ -543,7 +538,7 @@ module Sequel
|
|
543
538
|
|
544
539
|
# Name symbol for the setter association method
|
545
540
|
def setter_method
|
546
|
-
|
541
|
+
self[:setter_method]
|
547
542
|
end
|
548
543
|
|
549
544
|
# The range used for slicing when using the :ruby eager limit strategy.
|
@@ -556,8 +551,10 @@ module Sequel
|
|
556
551
|
|
557
552
|
private
|
558
553
|
|
559
|
-
#
|
560
|
-
#
|
554
|
+
# If the key exists in the reflection hash, return it.
|
555
|
+
# If the key doesn't exist and association reflections are uncached, then yield to get the value.
|
556
|
+
# If the key doesn't exist and association reflection are cached, check the cache and return
|
557
|
+
# the value if present, or yield to get the value, cache the value, and return it.
|
561
558
|
def cached_fetch(key)
|
562
559
|
fetch(key) do
|
563
560
|
return yield unless h = self[:cache]
|
@@ -567,7 +564,7 @@ module Sequel
|
|
567
564
|
end
|
568
565
|
end
|
569
566
|
|
570
|
-
# Cache the value at the given key
|
567
|
+
# Cache the value at the given key if caching.
|
571
568
|
def cached_set(key, value)
|
572
569
|
return unless h = self[:cache]
|
573
570
|
Sequel.synchronize{h[key] = value}
|
@@ -576,10 +573,10 @@ module Sequel
|
|
576
573
|
# The base dataset used for the association, before any order/conditions
|
577
574
|
# options have been applied.
|
578
575
|
def _associated_dataset
|
579
|
-
associated_class.dataset
|
576
|
+
associated_class.dataset
|
580
577
|
end
|
581
578
|
|
582
|
-
# Whether for the reciprocal type for the given association
|
579
|
+
# Whether for the reciprocal type for the given association cannot be
|
583
580
|
# known in advantage, false by default.
|
584
581
|
def ambiguous_reciprocal_type?
|
585
582
|
false
|
@@ -1106,7 +1103,7 @@ module Sequel
|
|
1106
1103
|
end
|
1107
1104
|
|
1108
1105
|
# Support automatic use of correlated subqueries if :ruby option is best available option,
|
1109
|
-
#
|
1106
|
+
# the database supports them, and either the associated class has a non-composite primary key
|
1110
1107
|
# or the database supports multiple columns in IN.
|
1111
1108
|
def true_eager_graph_limit_strategy
|
1112
1109
|
r = super
|
@@ -1451,8 +1448,6 @@ module Sequel
|
|
1451
1448
|
|
1452
1449
|
# This module contains methods added to all association datasets
|
1453
1450
|
module AssociationDatasetMethods
|
1454
|
-
Dataset.def_deprecated_opts_setter(self, :model_object, :association_reflection)
|
1455
|
-
|
1456
1451
|
# The model object that created the association dataset
|
1457
1452
|
def model_object
|
1458
1453
|
@opts[:model_object]
|
@@ -1508,7 +1503,7 @@ module Sequel
|
|
1508
1503
|
# Project.associations
|
1509
1504
|
# => [:portfolio, :milestones]
|
1510
1505
|
# Project.association_reflection(:portfolio)
|
1511
|
-
# =>
|
1506
|
+
# => #<Sequel::Model::Associations::ManyToOneAssociationReflection Project.many_to_one :portfolio>
|
1512
1507
|
#
|
1513
1508
|
# Associations should not have the same names as any of the columns in the
|
1514
1509
|
# model's current table they reference. If you are dealing with an existing schema that
|
@@ -1530,7 +1525,7 @@ module Sequel
|
|
1530
1525
|
|
1531
1526
|
# Whether association metadata should be cached in the association reflection. If not cached, it will be computed
|
1532
1527
|
# on demand. In general you only want to set this to false when using code reloading. When using code reloading,
|
1533
|
-
# setting this will make sure that if an associated class is removed or modified, this class will not
|
1528
|
+
# setting this will make sure that if an associated class is removed or modified, this class will not have a reference to
|
1534
1529
|
# the previous class.
|
1535
1530
|
attr_accessor :cache_associations
|
1536
1531
|
|
@@ -1605,7 +1600,7 @@ module Sequel
|
|
1605
1600
|
# singularized unless the type is :many_to_one, :one_to_one, or one_through_one). If this is specified
|
1606
1601
|
# as a string or symbol, you must specify the full class name (e.g. "::SomeModule::MyModel").
|
1607
1602
|
# :class_namespace :: If :class is given as a string or symbol, sets the default namespace in which to look for
|
1608
|
-
# the class. <tt
|
1603
|
+
# the class. <tt>class: 'Foo', class_namespace: 'Bar'</tt> looks for <tt>::Bar::Foo</tt>.)
|
1609
1604
|
# :clearer :: Proc used to define the private _remove_all_* method for doing the database work
|
1610
1605
|
# to remove all objects associated to the current object (*_to_many assocations).
|
1611
1606
|
# :clone :: Merge the current options and block into the options and block used in defining
|
@@ -1678,8 +1673,7 @@ module Sequel
|
|
1678
1673
|
# :order_eager_graph :: Whether to add the association's order to the graphed dataset's order when graphing
|
1679
1674
|
# via +eager_graph+. Defaults to true, so set to false to disable.
|
1680
1675
|
# :read_only :: Do not add a setter method (for many_to_one or one_to_one associations),
|
1681
|
-
# or add_/remove_/remove_all_ methods (for one_to_many and many_to_many associations).
|
1682
|
-
# true for one_through_one associations.
|
1676
|
+
# or add_/remove_/remove_all_ methods (for one_to_many and many_to_many associations).
|
1683
1677
|
# :reciprocal :: the symbol name of the reciprocal association,
|
1684
1678
|
# if it exists. By default, Sequel will try to determine it by looking at the
|
1685
1679
|
# associated model's assocations for a association that matches
|
@@ -1710,7 +1704,7 @@ module Sequel
|
|
1710
1704
|
# array of symbols for a composite key association.
|
1711
1705
|
# :primary_key_method :: the method symbol or array of method symbols to call on the associated
|
1712
1706
|
# object to get the foreign key values. Defaults to :primary_key option.
|
1713
|
-
# :qualify :: Whether to use
|
1707
|
+
# :qualify :: Whether to use qualified primary keys when loading the association. The default
|
1714
1708
|
# is true, so you must set to false to not qualify. Qualification rarely causes
|
1715
1709
|
# problems, but it's necessary to disable in some cases, such as when you are doing
|
1716
1710
|
# a JOIN USING operation on the column on Oracle.
|
@@ -1803,10 +1797,6 @@ module Sequel
|
|
1803
1797
|
end
|
1804
1798
|
|
1805
1799
|
opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
|
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")
|
1808
|
-
opts[:predicate_key] = opts[:eager_loading_predicate_key]
|
1809
|
-
end
|
1810
1800
|
opts[:graph_join_type] ||= :left_outer
|
1811
1801
|
opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
|
1812
1802
|
conds = opts[:conditions]
|
@@ -1814,9 +1804,15 @@ module Sequel
|
|
1814
1804
|
opts[:graph_conditions] = conds if !opts.include?(:graph_conditions) and Sequel.condition_specifier?(conds)
|
1815
1805
|
opts[:graph_conditions] = opts.fetch(:graph_conditions, []).to_a
|
1816
1806
|
opts[:graph_select] = Array(opts[:graph_select]) if opts[:graph_select]
|
1817
|
-
[:before_add, :before_remove, :after_add, :after_remove, :after_load, :before_set, :after_set
|
1818
|
-
opts[cb_type] = Array(opts[cb_type])
|
1807
|
+
[:before_add, :before_remove, :after_add, :after_remove, :after_load, :before_set, :after_set].each do |cb_type|
|
1808
|
+
opts[cb_type] = Array(opts[cb_type]) if opts[cb_type]
|
1809
|
+
end
|
1810
|
+
|
1811
|
+
if opts[:extend]
|
1812
|
+
opts[:extend] = Array(opts[:extend])
|
1813
|
+
opts[:reverse_extend] = opts[:extend].reverse
|
1819
1814
|
end
|
1815
|
+
|
1820
1816
|
late_binding_class_option(opts, opts.returns_array? ? singularize(name) : name)
|
1821
1817
|
|
1822
1818
|
# Remove :class entry if it exists and is nil, to work with cached_fetch
|
@@ -1877,7 +1873,7 @@ module Sequel
|
|
1877
1873
|
associate(:many_to_one, name, opts, &block)
|
1878
1874
|
end
|
1879
1875
|
|
1880
|
-
# Shortcut for adding a one_through_one association, see #associate
|
1876
|
+
# Shortcut for adding a one_through_one association, see #associate
|
1881
1877
|
def one_through_one(name, opts=OPTS, &block)
|
1882
1878
|
associate(:one_through_one, name, opts, &block)
|
1883
1879
|
end
|
@@ -1887,7 +1883,7 @@ module Sequel
|
|
1887
1883
|
associate(:one_to_many, name, opts, &block)
|
1888
1884
|
end
|
1889
1885
|
|
1890
|
-
# Shortcut for adding a one_to_one association, see #associate
|
1886
|
+
# Shortcut for adding a one_to_one association, see #associate
|
1891
1887
|
def one_to_one(name, opts=OPTS, &block)
|
1892
1888
|
associate(:one_to_one, name, opts, &block)
|
1893
1889
|
end
|
@@ -1918,14 +1914,29 @@ module Sequel
|
|
1918
1914
|
|
1919
1915
|
# Adds the association method to the association methods module.
|
1920
1916
|
def def_association_method(opts)
|
1921
|
-
association_module_def(opts.association_method, opts) do
|
1922
|
-
|
1923
|
-
load_associated_objects(opts, dynamic_opts.length == 0 ? OPTS : dynamic_opts[0], &block)
|
1917
|
+
association_module_def(opts.association_method, opts) do |dynamic_opts=OPTS, &block|
|
1918
|
+
load_associated_objects(opts, dynamic_opts, &block)
|
1924
1919
|
end
|
1925
1920
|
end
|
1926
1921
|
|
1927
1922
|
# Define all of the association instance methods for this association.
|
1928
1923
|
def def_association_instance_methods(opts)
|
1924
|
+
# Always set the method names in the association reflection, even if they
|
1925
|
+
# are not used, for backwards compatibility.
|
1926
|
+
opts[:dataset_method] = :"#{opts[:name]}_dataset"
|
1927
|
+
if opts.returns_array?
|
1928
|
+
sname = singularize(opts[:name])
|
1929
|
+
opts[:_add_method] = :"_add_#{sname}"
|
1930
|
+
opts[:add_method] = :"add_#{sname}"
|
1931
|
+
opts[:_remove_method] = :"_remove_#{sname}"
|
1932
|
+
opts[:remove_method] = :"remove_#{sname}"
|
1933
|
+
opts[:_remove_all_method] = :"_remove_all_#{opts[:name]}"
|
1934
|
+
opts[:remove_all_method] = :"remove_all_#{opts[:name]}"
|
1935
|
+
else
|
1936
|
+
opts[:_setter_method] = :"_#{opts[:name]}="
|
1937
|
+
opts[:setter_method] = :"#{opts[:name]}="
|
1938
|
+
end
|
1939
|
+
|
1929
1940
|
association_module_def(opts.dataset_method, opts){_dataset(opts)}
|
1930
1941
|
def_association_method(opts)
|
1931
1942
|
|
@@ -1933,23 +1944,23 @@ module Sequel
|
|
1933
1944
|
|
1934
1945
|
if opts[:setter] && opts[:_setter]
|
1935
1946
|
# This is backwards due to backwards compatibility
|
1936
|
-
association_module_private_def(opts
|
1937
|
-
association_module_def(opts
|
1947
|
+
association_module_private_def(opts[:_setter_method], opts, &opts[:setter])
|
1948
|
+
association_module_def(opts[:setter_method], opts, &opts[:_setter])
|
1938
1949
|
end
|
1939
1950
|
|
1940
1951
|
if adder = opts[:adder]
|
1941
|
-
association_module_private_def(opts
|
1942
|
-
association_module_def(opts
|
1952
|
+
association_module_private_def(opts[:_add_method], opts, &adder)
|
1953
|
+
association_module_def(opts[:add_method], opts){|o,*args| add_associated_object(opts, o, *args)}
|
1943
1954
|
end
|
1944
1955
|
|
1945
1956
|
if remover = opts[:remover]
|
1946
|
-
association_module_private_def(opts
|
1947
|
-
association_module_def(opts
|
1957
|
+
association_module_private_def(opts[:_remove_method], opts, &remover)
|
1958
|
+
association_module_def(opts[:remove_method], opts){|o,*args| remove_associated_object(opts, o, *args)}
|
1948
1959
|
end
|
1949
1960
|
|
1950
1961
|
if clearer = opts[:clearer]
|
1951
|
-
association_module_private_def(opts
|
1952
|
-
association_module_def(opts
|
1962
|
+
association_module_private_def(opts[:_remove_all_method], opts, &clearer)
|
1963
|
+
association_module_def(opts[:remove_all_method], opts){|*args| remove_all_associated_objects(opts, *args)}
|
1953
1964
|
end
|
1954
1965
|
end
|
1955
1966
|
|
@@ -1976,7 +1987,10 @@ module Sequel
|
|
1976
1987
|
join_table = (opts[:join_table] ||= opts.default_join_table)
|
1977
1988
|
opts[:left_key_alias] ||= opts.default_associated_key_alias
|
1978
1989
|
opts[:graph_join_table_join_type] ||= opts[:graph_join_type]
|
1979
|
-
|
1990
|
+
if opts[:uniq]
|
1991
|
+
opts[:after_load] ||= []
|
1992
|
+
opts[:after_load].unshift(:array_uniq!)
|
1993
|
+
end
|
1980
1994
|
opts[:dataset] ||= opts.association_dataset_proc
|
1981
1995
|
opts[:eager_loader] ||= opts.method(:default_eager_loader)
|
1982
1996
|
|
@@ -2273,7 +2287,7 @@ module Sequel
|
|
2273
2287
|
|
2274
2288
|
# Return a dataset for the association after applying any dynamic callback.
|
2275
2289
|
def _associated_dataset(opts, dynamic_opts)
|
2276
|
-
ds =
|
2290
|
+
ds = public_send(opts.dataset_method)
|
2277
2291
|
if callback = dynamic_opts[:callback]
|
2278
2292
|
ds = callback.call(ds)
|
2279
2293
|
end
|
@@ -2353,7 +2367,8 @@ module Sequel
|
|
2353
2367
|
raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
|
2354
2368
|
ensure_associated_primary_key(opts, o, *args)
|
2355
2369
|
return if run_association_callbacks(opts, :before_add, o) == false
|
2356
|
-
|
2370
|
+
# Allow calling private _add method
|
2371
|
+
return if !send(opts[:_add_method], o, *args) && opts.handle_silent_modification_failure?
|
2357
2372
|
if array = associations[opts[:name]] and !array.include?(o)
|
2358
2373
|
array.push(o)
|
2359
2374
|
end
|
@@ -2407,28 +2422,10 @@ module Sequel
|
|
2407
2422
|
self
|
2408
2423
|
end
|
2409
2424
|
|
2410
|
-
#
|
2411
|
-
# reasons, you can pass true/false/nil or a callable argument to
|
2412
|
-
# associations. That will be going away in Sequel 5, but we'll still
|
2413
|
-
# support it until then.
|
2425
|
+
# If a block is given, assign it as the :callback option in the hash, and return the hash.
|
2414
2426
|
def load_association_objects_options(dynamic_opts, &block)
|
2415
|
-
|
2416
|
-
|
2417
|
-
Sequel::Deprecation.deprecate("Passing #{dynamic_opts.inspect} an argument to an association loading method", "Pass {:reload=>#{dynamic_opts.inspect}} instead")
|
2418
|
-
{:reload=>dynamic_opts}
|
2419
|
-
when Hash
|
2420
|
-
Hash[dynamic_opts]
|
2421
|
-
else
|
2422
|
-
if dynamic_opts.respond_to?(:call)
|
2423
|
-
Sequel::Deprecation.deprecate("Passing callbable argument #{dynamic_opts.inspect} to an association loading method", "Pass a block to the method to use a callback")
|
2424
|
-
{:callback=>dynamic_opts}
|
2425
|
-
else
|
2426
|
-
Sequel::Deprecation.deprecate("Passing #{dynamic_opts.inspect} an argument to an association loading method", "Pass {:reload=>true} if you would like to reload the association")
|
2427
|
-
{:reload=>true}
|
2428
|
-
end
|
2429
|
-
end
|
2430
|
-
|
2431
|
-
if block_given?
|
2427
|
+
if block
|
2428
|
+
dynamic_opts = Hash[dynamic_opts]
|
2432
2429
|
dynamic_opts[:callback] = block
|
2433
2430
|
end
|
2434
2431
|
|
@@ -2436,7 +2433,7 @@ module Sequel
|
|
2436
2433
|
end
|
2437
2434
|
|
2438
2435
|
# Load the associated objects using the dataset, handling callbacks, reciprocals, and caching.
|
2439
|
-
def load_associated_objects(opts, dynamic_opts
|
2436
|
+
def load_associated_objects(opts, dynamic_opts, &block)
|
2440
2437
|
dynamic_opts = load_association_objects_options(dynamic_opts, &block)
|
2441
2438
|
name = opts[:name]
|
2442
2439
|
if associations.include?(name) && !dynamic_opts[:callback] && !dynamic_opts[:reload]
|
@@ -2490,7 +2487,8 @@ module Sequel
|
|
2490
2487
|
# Remove all associated objects from the given association
|
2491
2488
|
def remove_all_associated_objects(opts, *args)
|
2492
2489
|
raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
|
2493
|
-
|
2490
|
+
# Allow calling private _remove_all method
|
2491
|
+
send(opts[:_remove_all_method], *args)
|
2494
2492
|
ret = associations[opts[:name]].each{|o| remove_reciprocal_object(opts, o)} if associations.include?(opts[:name])
|
2495
2493
|
associations[opts[:name]] = []
|
2496
2494
|
ret
|
@@ -2503,13 +2501,14 @@ module Sequel
|
|
2503
2501
|
o = remove_check_existing_object_from_pk(opts, o, *args)
|
2504
2502
|
elsif !o.is_a?(klass)
|
2505
2503
|
raise(Sequel::Error, "associated object #{o.inspect} not of correct type #{klass}")
|
2506
|
-
elsif opts.remove_should_check_existing? &&
|
2504
|
+
elsif opts.remove_should_check_existing? && public_send(opts.dataset_method).where(o.pk_hash).empty?
|
2507
2505
|
raise(Sequel::Error, "associated object #{o.inspect} is not currently associated to #{inspect}")
|
2508
2506
|
end
|
2509
2507
|
raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
|
2510
2508
|
raise(Sequel::Error, "associated object #{o.inspect} does not have a primary key") if opts.need_associated_primary_key? && !o.pk
|
2511
2509
|
return if run_association_callbacks(opts, :before_remove, o) == false
|
2512
|
-
|
2510
|
+
# Allow calling private _remove method
|
2511
|
+
return if !send(opts[:_remove_method], o, *args) && opts.handle_silent_modification_failure?
|
2513
2512
|
associations[opts[:name]].delete_if{|x| o === x} if associations.include?(opts[:name])
|
2514
2513
|
remove_reciprocal_object(opts, o)
|
2515
2514
|
run_association_callbacks(opts, :after_remove, o)
|
@@ -2522,7 +2521,7 @@ module Sequel
|
|
2522
2521
|
def remove_check_existing_object_from_pk(opts, o, *args)
|
2523
2522
|
key = o
|
2524
2523
|
pkh = opts.associated_class.qualified_primary_key_hash(key)
|
2525
|
-
raise(Sequel::Error, "no object with key(s) #{key.inspect} is currently associated to #{inspect}") unless o =
|
2524
|
+
raise(Sequel::Error, "no object with key(s) #{key.inspect} is currently associated to #{inspect}") unless o = public_send(opts.dataset_method).first(pkh)
|
2526
2525
|
o
|
2527
2526
|
end
|
2528
2527
|
|
@@ -2540,30 +2539,28 @@ module Sequel
|
|
2540
2539
|
|
2541
2540
|
# Run the callback for the association with the object.
|
2542
2541
|
def run_association_callbacks(reflection, callback_type, object)
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
raise Error, "callbacks should either be Procs or Symbols"
|
2557
|
-
end
|
2558
|
-
|
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")
|
2561
|
-
raise(HookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false")
|
2542
|
+
return unless cbs = reflection[callback_type]
|
2543
|
+
|
2544
|
+
begin
|
2545
|
+
cbs.each do |cb|
|
2546
|
+
res = case cb
|
2547
|
+
when Symbol
|
2548
|
+
# Allow calling private methods in association callbacks
|
2549
|
+
send(cb, object)
|
2550
|
+
when Proc
|
2551
|
+
cb.call(self, object)
|
2552
|
+
else
|
2553
|
+
raise Error, "callbacks should either be Procs or Symbols"
|
2554
|
+
end
|
2562
2555
|
end
|
2556
|
+
rescue HookFailed
|
2557
|
+
# The reason we automatically set raise_error for singular associations is that
|
2558
|
+
# assignment in ruby always returns the argument instead of the result of the
|
2559
|
+
# method, so we can't return nil to signal that the association callback prevented
|
2560
|
+
# the modification
|
2561
|
+
return false unless raise_on_save_failure || !reflection.returns_array?
|
2562
|
+
raise
|
2563
2563
|
end
|
2564
|
-
rescue HookFailed
|
2565
|
-
return false unless raise_error
|
2566
|
-
raise
|
2567
2564
|
end
|
2568
2565
|
|
2569
2566
|
# Set the given object as the associated object for the given *_to_one association reflection
|
@@ -2572,7 +2569,8 @@ module Sequel
|
|
2572
2569
|
return if a && a == o && !set_associated_object_if_same?
|
2573
2570
|
run_association_callbacks(opts, :before_set, o)
|
2574
2571
|
remove_reciprocal_object(opts, a) if a
|
2575
|
-
|
2572
|
+
# Allow calling private _setter method
|
2573
|
+
send(opts[:_setter_method], o)
|
2576
2574
|
associations[opts[:name]] = o
|
2577
2575
|
add_reciprocal_object(opts, o) if o
|
2578
2576
|
run_association_callbacks(opts, :after_set, o)
|
@@ -2630,37 +2628,35 @@ module Sequel
|
|
2630
2628
|
# Album.eager_graph(:artist, :genre).all
|
2631
2629
|
# Album.eager(:artist).eager(:genre).all
|
2632
2630
|
# Album.eager_graph(:artist).eager(:genre).all
|
2633
|
-
# Artist.eager(:
|
2634
|
-
# Artist.eager_graph(:
|
2635
|
-
# Artist.eager(:
|
2636
|
-
# Artist.eager_graph(:
|
2631
|
+
# Artist.eager(albums: :tracks).all
|
2632
|
+
# Artist.eager_graph(albums: :tracks).all
|
2633
|
+
# Artist.eager(albums: {tracks: :genre}).all
|
2634
|
+
# Artist.eager_graph(albums: {tracks: :genre}).all
|
2637
2635
|
#
|
2638
2636
|
# You can also pass a callback as a hash value in order to customize the dataset being
|
2639
2637
|
# eager loaded at query time, analogous to the way the :eager_block association option
|
2640
2638
|
# allows you to customize it at association definition time. For example,
|
2641
2639
|
# if you wanted artists with their albums since 1990:
|
2642
2640
|
#
|
2643
|
-
# Artist.eager(:
|
2641
|
+
# Artist.eager(albums: proc{|ds| ds.where{year > 1990}})
|
2644
2642
|
#
|
2645
2643
|
# Or if you needed albums and their artist's name only, using a single query:
|
2646
2644
|
#
|
2647
|
-
# Albums.eager_graph(:
|
2645
|
+
# Albums.eager_graph(artist: proc{|ds| ds.select(:name)})
|
2648
2646
|
#
|
2649
2647
|
# To cascade eager loading while using a callback, you substitute the cascaded
|
2650
2648
|
# associations with a single entry hash that has the proc callback as the key and
|
2651
2649
|
# the cascaded associations as the value. This will load artists with their albums
|
2652
2650
|
# since 1990, and also the tracks on those albums and the genre for those tracks:
|
2653
2651
|
#
|
2654
|
-
# Artist.eager(:
|
2652
|
+
# Artist.eager(albums: {proc{|ds| ds.where{year > 1990}}=>{tracks: :genre}})
|
2655
2653
|
module DatasetMethods
|
2656
|
-
Sequel::Dataset.def_mutation_method(:eager, :eager_graph, :module=>self)
|
2657
|
-
|
2658
2654
|
%w'inner left right full'.each do |type|
|
2659
|
-
class_eval
|
2655
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
2660
2656
|
def association_#{type}_join(*associations)
|
2661
2657
|
_association_join(:#{type}, associations)
|
2662
2658
|
end
|
2663
|
-
END
|
2659
|
+
END
|
2664
2660
|
end
|
2665
2661
|
|
2666
2662
|
# Adds one or more INNER JOINs to the existing dataset using the keys and conditions
|
@@ -2741,7 +2737,7 @@ END
|
|
2741
2737
|
# it avoids problems such as aliasing conflicts and creating cartesian product
|
2742
2738
|
# result sets if multiple one_to_many or many_to_many eager associations are requested.
|
2743
2739
|
#
|
2744
|
-
# One limitation of using this method is that you cannot filter the dataset
|
2740
|
+
# One limitation of using this method is that you cannot filter the current dataset
|
2745
2741
|
# based on values of columns in an associated table, since the associations are loaded
|
2746
2742
|
# in separate queries. To do that you need to load all associations in the
|
2747
2743
|
# same query, and extract an object graph from the results of that query. If you
|
@@ -2758,7 +2754,8 @@ END
|
|
2758
2754
|
end
|
2759
2755
|
|
2760
2756
|
# The secondary eager loading method. Loads all associations in a single query. This
|
2761
|
-
# method should only be used if you need to filter or order based on columns in associated tables
|
2757
|
+
# method should only be used if you need to filter or order based on columns in associated tables,
|
2758
|
+
# or if you have done comparative benchmarking it and determined it is faster.
|
2762
2759
|
#
|
2763
2760
|
# This method uses <tt>Dataset#graph</tt> to create appropriate aliases for columns in all the
|
2764
2761
|
# tables. Then it uses the graph's metadata to build the associations from the single hash, and
|
@@ -2766,7 +2763,7 @@ END
|
|
2766
2763
|
#
|
2767
2764
|
# Be very careful when using this with multiple one_to_many or many_to_many associations, as you can
|
2768
2765
|
# create large cartesian products. If you must graph multiple one_to_many and many_to_many associations,
|
2769
|
-
# make sure your filters are narrow if
|
2766
|
+
# make sure your filters are narrow if the datasets are large.
|
2770
2767
|
#
|
2771
2768
|
# Each association's order, if defined, is respected. +eager_graph+ probably
|
2772
2769
|
# won't work correctly on a limited dataset, unless you are
|
@@ -2890,7 +2887,7 @@ END
|
|
2890
2887
|
limit_strategy = r.eager_graph_limit_strategy(local_opts[:limit_strategy])
|
2891
2888
|
|
2892
2889
|
if r[:conditions] && !Sequel.condition_specifier?(r[:conditions]) && !r[:orig_opts].has_key?(:graph_conditions) && !r[:orig_opts].has_key?(:graph_only_conditions) && !r.has_key?(:graph_block)
|
2893
|
-
|
2890
|
+
raise Error, "Cannot eager_graph association when :conditions specified and not a hash or an array of pairs. Specify :graph_conditions, :graph_only_conditions, or :graph_block for the association. Model: #{r[:model]}, association: #{r[:name]}"
|
2894
2891
|
end
|
2895
2892
|
|
2896
2893
|
ds = loader.call(:self=>ds, :table_alias=>assoc_table_alias, :implicit_qualifier=>(ta == ds.opts[:eager_graph][:master]) ? first_source : qualifier_from_alias_symbol(ta, first_source), :callback=>callback, :join_type=>local_opts[:join_type], :join_only=>local_opts[:join_only], :limit_strategy=>limit_strategy, :from_self_alias=>ds.opts[:eager_graph][:master])
|
@@ -2982,6 +2979,7 @@ END
|
|
2982
2979
|
# Return an expression for filtering by the given association reflection and associated object.
|
2983
2980
|
def association_filter_expression(op, ref, obj)
|
2984
2981
|
meth = :"#{ref[:type]}_association_filter_expression"
|
2982
|
+
# Allow calling private association specific method to get filter expression
|
2985
2983
|
send(meth, op, ref, obj) if respond_to?(meth, true)
|
2986
2984
|
end
|
2987
2985
|
|
@@ -3042,10 +3040,9 @@ END
|
|
3042
3040
|
# Eagerly load all specified associations
|
3043
3041
|
def eager_load(a, eager_assoc=@opts[:eager])
|
3044
3042
|
return if a.empty?
|
3045
|
-
# Key is foreign/primary key name symbol
|
3043
|
+
# Key is foreign/primary key name symbol.
|
3046
3044
|
# Value is hash with keys being foreign/primary key values (generally integers)
|
3047
|
-
#
|
3048
|
-
# specific foreign/primary key
|
3045
|
+
# and values being an array of current model objects with that specific foreign/primary key
|
3049
3046
|
key_hash = {}
|
3050
3047
|
# Reflections for all associations to eager load
|
3051
3048
|
reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
|
@@ -3088,7 +3085,7 @@ END
|
|
3088
3085
|
eager_block, associations = pr_assoc
|
3089
3086
|
end
|
3090
3087
|
loader.call(:key_hash=>key_hash, :rows=>a, :associations=>associations, :self=>self, :eager_block=>eager_block, :id_map=>id_map)
|
3091
|
-
a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])}
|
3088
|
+
a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])} if r[:after_load]
|
3092
3089
|
end
|
3093
3090
|
end
|
3094
3091
|
|
@@ -3220,7 +3217,7 @@ END
|
|
3220
3217
|
after_load_map = @after_load_map = {}
|
3221
3218
|
reflection_map.each do |k, v|
|
3222
3219
|
alias_map[k] = v[:name]
|
3223
|
-
after_load_map[k] = v[:after_load]
|
3220
|
+
after_load_map[k] = v[:after_load] if v[:after_load]
|
3224
3221
|
type_map[k] = if v.returns_array?
|
3225
3222
|
true
|
3226
3223
|
elsif (limit_and_offset = limit_map[k]) && !limit_and_offset.last.nil?
|
@@ -3261,7 +3258,7 @@ END
|
|
3261
3258
|
@records_map = records_map
|
3262
3259
|
|
3263
3260
|
datasets = opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
|
3264
|
-
column_aliases = opts[:
|
3261
|
+
column_aliases = opts[:graph][:column_aliases]
|
3265
3262
|
primary_keys = {}
|
3266
3263
|
column_maps = {}
|
3267
3264
|
models = {}
|
@@ -3383,7 +3380,7 @@ END
|
|
3383
3380
|
# Return a suitable hash key for any subhash +h+, which is an array of values by column order.
|
3384
3381
|
# This is only used if the primary key cannot be used.
|
3385
3382
|
def hkey(h)
|
3386
|
-
h.sort_by{|x| x[0]
|
3383
|
+
h.sort_by{|x| x[0]}
|
3387
3384
|
end
|
3388
3385
|
|
3389
3386
|
# Return the subhash for the master table by parsing the values out of the main hash +h+
|
@@ -3428,7 +3425,7 @@ END
|
|
3428
3425
|
records.each do |record|
|
3429
3426
|
dependency_map.each do |ta, deps|
|
3430
3427
|
assoc_name = alias_map[ta]
|
3431
|
-
list = record.
|
3428
|
+
list = record.public_send(assoc_name)
|
3432
3429
|
rec_list = if type_map[ta]
|
3433
3430
|
list.uniq!
|
3434
3431
|
if lo = limit_map[ta]
|