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
data/doc/association_basics.rdoc
CHANGED
@@ -16,13 +16,13 @@ database tables. Without associations, if you had classes such as:
|
|
16
16
|
And you wanted to get all of the albums for a given artist (assuming each
|
17
17
|
album was associated with only one artist):
|
18
18
|
|
19
|
-
Album.where(:
|
19
|
+
Album.where(artist_id: @artist.id).all
|
20
20
|
|
21
21
|
Or maybe you want to add an album for a given artist:
|
22
22
|
|
23
|
-
Album.create(:
|
23
|
+
Album.create(artist_id: @artist.id, name: 'RF')
|
24
24
|
|
25
|
-
With
|
25
|
+
With associations, you can make the above code simpler, by setting up associations
|
26
26
|
between the two models:
|
27
27
|
|
28
28
|
class Artist < Sequel::Model
|
@@ -39,7 +39,7 @@ Then, the code to retrieve albums related to the artist is simpler:
|
|
39
39
|
|
40
40
|
As is the code to add a related album to an artist:
|
41
41
|
|
42
|
-
@artist.add_album(:
|
42
|
+
@artist.add_album(name: 'RF')
|
43
43
|
|
44
44
|
It also makes it easier to creating queries that use joins based on the association:
|
45
45
|
|
@@ -109,8 +109,6 @@ first record returned.
|
|
109
109
|
The many_to_many association allows each row in the current table to be associated
|
110
110
|
to many rows in the associated table, and each row in the associated table to
|
111
111
|
many rows in the current table, by using a join table to associate the two tables.
|
112
|
-
If you assume each artist can have multiple albums and each album can have multiple
|
113
|
-
artists:
|
114
112
|
|
115
113
|
The one_through_one association can be thought of as a subset of the many_to_many
|
116
114
|
association, but where there can only be 0 or 1 records in the associated table.
|
@@ -188,10 +186,10 @@ Then the default :key option will not be correct. To fix this, you need to
|
|
188
186
|
specify an explicit :key option:
|
189
187
|
|
190
188
|
class Album
|
191
|
-
many_to_one :artist, :
|
189
|
+
many_to_one :artist, key: :artistid
|
192
190
|
end
|
193
191
|
class Artist
|
194
|
-
one_to_many :albums, :
|
192
|
+
one_to_many :albums, key: :artistid
|
195
193
|
end
|
196
194
|
|
197
195
|
For many_to_many associations, the :left_key and :right_key options can be
|
@@ -211,17 +209,17 @@ option can be used to specify the name of the join table:
|
|
211
209
|
# Note that :left_key refers to the foreign key pointing to the
|
212
210
|
# current table, and :right_key the foreign key pointing to the
|
213
211
|
# associated table.
|
214
|
-
many_to_many :albums, :
|
215
|
-
:
|
212
|
+
many_to_many :albums, left_key: :artistid, right_key: :albumid,
|
213
|
+
join_table: :albumsartists
|
216
214
|
end
|
217
215
|
class Album
|
218
|
-
many_to_many :artists, :
|
219
|
-
:
|
216
|
+
many_to_many :artists, left_key: :albumid, right_key: :artistid,
|
217
|
+
join_table: :albumsartists
|
220
218
|
end
|
221
219
|
|
222
220
|
=== :class
|
223
221
|
|
224
|
-
If the class of the association
|
222
|
+
If the class of the association cannot be guessed directly by looking at
|
225
223
|
the association name, you need to specify it via the :class option. For
|
226
224
|
example, if you have two separate foreign keys in the albums table that
|
227
225
|
both point to the artists table, maybe to indicate one artist is the
|
@@ -235,12 +233,12 @@ vocalist and one is the composer, you'd have to use the :class option:
|
|
235
233
|
# :name
|
236
234
|
|
237
235
|
class Album
|
238
|
-
many_to_one :vocalist, :
|
239
|
-
many_to_one :composer, :
|
236
|
+
many_to_one :vocalist, class: :Artist
|
237
|
+
many_to_one :composer, class: :Artist
|
240
238
|
end
|
241
239
|
class Artist
|
242
|
-
one_to_many :vocalist_albums, :
|
243
|
-
one_to_many :composer_albums, :
|
240
|
+
one_to_many :vocalist_albums, class: :Album, key: :vocalist_id
|
241
|
+
one_to_many :composer_albums, class: :Album, key: :composer_id
|
244
242
|
end
|
245
243
|
|
246
244
|
== Self-referential Associations
|
@@ -255,8 +253,8 @@ example is a tree structure:
|
|
255
253
|
# :name
|
256
254
|
|
257
255
|
class Node
|
258
|
-
many_to_one :parent, :
|
259
|
-
one_to_many :children, :
|
256
|
+
many_to_one :parent, class: self
|
257
|
+
one_to_many :children, key: :parent_id, class: self
|
260
258
|
end
|
261
259
|
|
262
260
|
For many_to_many self_referential associations, it's fairly similar. Here's
|
@@ -268,10 +266,10 @@ an example of a directed graph:
|
|
268
266
|
# :name \----- :predecessor_id
|
269
267
|
|
270
268
|
class Node
|
271
|
-
many_to_many :direct_predecessors, :
|
272
|
-
:
|
273
|
-
many_to_many :direct_successors, :
|
274
|
-
:
|
269
|
+
many_to_many :direct_predecessors, left_key: :successor_id,
|
270
|
+
right_key: :predecessor_id, join_table: :edges, class: self
|
271
|
+
many_to_many :direct_successors, right_key: :successor_id,
|
272
|
+
left_key: :predecessor_id, join_table: :edges, class: self
|
275
273
|
end
|
276
274
|
|
277
275
|
== Methods Added
|
@@ -288,13 +286,13 @@ same name as the association:
|
|
288
286
|
many_to_one and one_to_one associations will also have a setter method
|
289
287
|
added to change the associated object:
|
290
288
|
|
291
|
-
@album.artist = Artist.create(:
|
289
|
+
@album.artist = Artist.create(name: 'YJM')
|
292
290
|
|
293
291
|
many_to_many and one_to_many associations will have three methods added:
|
294
292
|
|
295
|
-
|
296
|
-
|
297
|
-
|
293
|
+
add_* :: to associate an object to the current object
|
294
|
+
remove_* :: to disassociate an object from the current object
|
295
|
+
remove_all_* :: to dissociate all currently associated objects
|
298
296
|
|
299
297
|
Examples:
|
300
298
|
|
@@ -305,7 +303,11 @@ Examples:
|
|
305
303
|
Note that the remove_all_* method does not call remove hooks defined on
|
306
304
|
the association, it just issues a single query to the database. If you
|
307
305
|
want to remove all associated objects and call remove hooks, iterate
|
308
|
-
over the array of associated objects and call remove_* for each
|
306
|
+
over the array of associated objects and call remove_* for each:
|
307
|
+
|
308
|
+
@artist.albums.each do |album|
|
309
|
+
@artist.remove_album(album)
|
310
|
+
end
|
309
311
|
|
310
312
|
== Caching
|
311
313
|
|
@@ -398,70 +400,70 @@ all albums for a given artist, you would usually do:
|
|
398
400
|
|
399
401
|
You can also do the following:
|
400
402
|
|
401
|
-
Album.where(:artist
|
403
|
+
Album.where(artist: @artist).all
|
402
404
|
# or leave off the .all for a dataset
|
403
405
|
|
404
406
|
For filtering by a single association, this isn't very useful. However, unlike
|
405
407
|
using the association method, using a filter allows you to filter by multiple
|
406
408
|
associations:
|
407
409
|
|
408
|
-
Album.where(:artist
|
410
|
+
Album.where(artist: @artist, publisher: @publisher)
|
409
411
|
|
410
412
|
This will return all albums by that artist and published by that publisher.
|
411
413
|
This isn't possible using just the association method approach, though you
|
412
414
|
can combine the approaches:
|
413
415
|
|
414
|
-
@artist.albums_dataset.where(:publisher
|
416
|
+
@artist.albums_dataset.where(publisher: @publisher)
|
415
417
|
|
416
418
|
This doesn't just work for +many_to_one+ associations, it also works for
|
417
419
|
the other associations:
|
418
420
|
|
419
421
|
Album.one_to_one :album_info
|
420
422
|
# The album related to that AlbumInfo instance
|
421
|
-
Album.where(:
|
423
|
+
Album.where(album_info: AlbumInfo[2])
|
422
424
|
|
423
425
|
Album.one_to_many :tracks
|
424
426
|
# The album related to that Track instance
|
425
|
-
Album.where(:
|
427
|
+
Album.where(tracks: Track[3])
|
426
428
|
|
427
429
|
Album.many_to_many :tags
|
428
430
|
# All albums related to that Tag instance
|
429
|
-
Album.where(:
|
431
|
+
Album.where(tags: Tag[4])
|
430
432
|
|
431
433
|
Album.one_through_one :tag
|
432
434
|
# All albums related to that Tag instance
|
433
|
-
Album.where(:
|
435
|
+
Album.where(tag: Tag[4])
|
434
436
|
|
435
437
|
Note that for +one_to_many+ and +many_to_many+ associations, you still
|
436
438
|
use the plural form even though only a single model object is given.
|
437
439
|
|
438
440
|
You can also exclude by associations:
|
439
441
|
|
440
|
-
Album.exclude(:artist
|
442
|
+
Album.exclude(artist: @artist).all
|
441
443
|
|
442
444
|
This will return all albums not by that artist.
|
443
445
|
|
444
446
|
You can also provide an array with multiple model objects:
|
445
447
|
|
446
|
-
Album.where(:
|
448
|
+
Album.where(artist: [@artist1, @artist2]).all
|
447
449
|
|
448
450
|
Similar to using an array of integers or strings, this will return
|
449
451
|
all albums whose artist is one of those two artists. You can also
|
450
452
|
use +exclude+ if you want all albums not by either of those artists:
|
451
453
|
|
452
|
-
Album.exclude(:
|
454
|
+
Album.exclude(artist: [@artist1, @artist2]).all
|
453
455
|
|
454
456
|
If you are using a +one_to_many+ or +many_to_many+ association, you
|
455
457
|
may want to return records where the records matches all of multiple
|
456
458
|
records, instead of matching any of them. For example:
|
457
459
|
|
458
|
-
Album.where(:
|
460
|
+
Album.where(tags: [@tag1, @tag2])
|
459
461
|
|
460
462
|
This matches albums that are associated with either @tag1 or @tag2 or
|
461
463
|
both. If you only want ones that you are associated with both, you can
|
462
464
|
use separate filter calls:
|
463
465
|
|
464
|
-
Album.where(:
|
466
|
+
Album.where(tags: @tag1).where(tags: @tag2)
|
465
467
|
|
466
468
|
Or the array form of condition specifiers:
|
467
469
|
|
@@ -471,22 +473,22 @@ These will return albums associated with both @tag1 and @tag2.
|
|
471
473
|
|
472
474
|
You can also provide a dataset value when filtering by associations:
|
473
475
|
|
474
|
-
Album.where(:
|
476
|
+
Album.where(artist: Artist.where(Sequel.like(:name, 'A%'))).all
|
475
477
|
|
476
478
|
This will return all albums whose artist starts with 'A'. Like
|
477
479
|
the other forms, this can be inverted:
|
478
480
|
|
479
|
-
Album.exclude(:
|
481
|
+
Album.exclude(artist: Artist.where(Sequel.like(:name, 'A%'))).all
|
480
482
|
|
481
483
|
This will return all albums whose artist does not start with 'A'.
|
482
484
|
|
483
485
|
Filtering by associations even works for associations that have
|
484
486
|
conditions added via the :conditions option or a block:
|
485
487
|
|
486
|
-
Album.one_to_many :popular_tags, :
|
488
|
+
Album.one_to_many :popular_tags, clone: :tags do |ds|
|
487
489
|
ds.where{times_used > 1000}
|
488
490
|
end
|
489
|
-
Album.where(:
|
491
|
+
Album.where(popular_tags: [@tag1, @tag2])
|
490
492
|
|
491
493
|
This will return all albums that whose popular tags would include
|
492
494
|
at least one of those tags.
|
@@ -530,14 +532,14 @@ Which could be created using the following Sequel code:
|
|
530
532
|
DB.create_table(:artists) do
|
531
533
|
# Primary key must be set explicitly
|
532
534
|
primary_key :id
|
533
|
-
String :name
|
535
|
+
String :name, :null=>false, :unique=>true
|
534
536
|
end
|
535
537
|
DB.create_table(:albums) do
|
536
538
|
primary_key :id
|
537
539
|
# Table that foreign key references needs to be set explicitly
|
538
540
|
# for a database foreign key reference to be created.
|
539
|
-
foreign_key :artist_id, :artists
|
540
|
-
String :name
|
541
|
+
foreign_key :artist_id, :artists, :null=>false
|
542
|
+
String :name, :null=>false, :unique=>true
|
541
543
|
end
|
542
544
|
|
543
545
|
If you already had a schema such as:
|
@@ -550,7 +552,7 @@ If you already had a schema such as:
|
|
550
552
|
Then you just need to add the column:
|
551
553
|
|
552
554
|
DB.alter_table(:albums) do
|
553
|
-
add_foreign_key :artist_id, :artists
|
555
|
+
add_foreign_key :artist_id, :artists, :null=>false
|
554
556
|
end
|
555
557
|
|
556
558
|
=== many_to_many
|
@@ -589,8 +591,10 @@ You could use the following Sequel code:
|
|
589
591
|
DB.create_join_table(:album_id=>:albums, :artist_id=>:artists)
|
590
592
|
# or
|
591
593
|
DB.create_table(:albums_artists) do
|
592
|
-
foreign_key :album_id, :albums
|
593
|
-
foreign_key :artist_id, :artists
|
594
|
+
foreign_key :album_id, :albums, :null=>false
|
595
|
+
foreign_key :artist_id, :artists, :null=>false
|
596
|
+
primary_key [:album_id, :artist_id]
|
597
|
+
index [:artist_id, :album_id]
|
594
598
|
end
|
595
599
|
|
596
600
|
== Association Scope
|
@@ -627,12 +631,12 @@ To fix this, you need to specify the full model class name using the
|
|
627
631
|
|
628
632
|
module App1
|
629
633
|
class Artist < Sequel::Model
|
630
|
-
one_to_many :albums, :
|
634
|
+
one_to_many :albums, class: "App2::Album"
|
631
635
|
end
|
632
636
|
end
|
633
637
|
module App2
|
634
638
|
class Album < Sequel::Model
|
635
|
-
many_to_one :artist, :
|
639
|
+
many_to_one :artist, class: "App1::Artist"
|
636
640
|
end
|
637
641
|
end
|
638
642
|
|
@@ -645,7 +649,7 @@ used is not correct, you need to specify the full class name with the
|
|
645
649
|
one_to_many :albums
|
646
650
|
end
|
647
651
|
class Album < Sequel::Model
|
648
|
-
many_to_one :artist, :
|
652
|
+
many_to_one :artist, class: "App1::AlbumArtist"
|
649
653
|
end
|
650
654
|
end
|
651
655
|
|
@@ -698,11 +702,11 @@ association name is used in this method.
|
|
698
702
|
In addition to passing an actual associated object, you can pass a hash,
|
699
703
|
and a new associated object will be created from them:
|
700
704
|
|
701
|
-
@artist.add_album(:
|
705
|
+
@artist.add_album(name: 'RF') # creates Album object
|
702
706
|
|
703
707
|
The add_<i>association</i> method returns the new associated object:
|
704
708
|
|
705
|
-
@album = @artist.add_album(:
|
709
|
+
@album = @artist.add_album(name: 'RF')
|
706
710
|
|
707
711
|
Note that the add_* methods for +one_to_many+ persist the changes by
|
708
712
|
saving the passed in (or newly created) object. However, to avoid
|
@@ -787,7 +791,7 @@ only difference between the two is that if you use an association option
|
|
787
791
|
to change the method Sequel defines, you cannot call super to get the
|
788
792
|
default behavior.
|
789
793
|
|
790
|
-
=== _<i>association</i>=
|
794
|
+
=== :setter (_<i>association</i>= method)
|
791
795
|
|
792
796
|
Let's say you want to set a specific field whenever associating an object
|
793
797
|
using the association setter method. For example, let's say you have
|
@@ -796,11 +800,7 @@ album is associated with an artist, it should be filed under the artist's
|
|
796
800
|
name and the album's name, otherwise it should just use the album's name.
|
797
801
|
|
798
802
|
class Album < Sequel::Model
|
799
|
-
many_to_one :artist
|
800
|
-
|
801
|
-
private
|
802
|
-
|
803
|
-
def _artist=(artist)
|
803
|
+
many_to_one :artist, setter: (lambda do |artist|
|
804
804
|
if artist
|
805
805
|
self.artist_id = artist.id
|
806
806
|
self.file_under = "#{artist.name}-#{name}"
|
@@ -808,58 +808,46 @@ name and the album's name, otherwise it should just use the album's name.
|
|
808
808
|
self.artist_id = nil
|
809
809
|
self.file_under = name
|
810
810
|
end
|
811
|
-
end
|
811
|
+
end)
|
812
812
|
end
|
813
813
|
|
814
814
|
The above example is contrived, as you would generally use a before_save model
|
815
815
|
hook to handle such a modification. However, if you only modify the album's
|
816
816
|
artist using the artist= method, this approach may perform better.
|
817
817
|
|
818
|
-
=== \_add_<i>association</i>
|
818
|
+
=== :adder (\_add_<i>association</i> method)
|
819
819
|
|
820
820
|
Continuing with the same example, here's how you would handle the same case if
|
821
821
|
you also wanted to handle the Artist#add_album method:
|
822
822
|
|
823
823
|
class Artist < Sequel::Model
|
824
|
-
one_to_many :albums
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
def _add_album(album)
|
829
|
-
album.update(:artist_id => id, :file_under=>"#{name}-#{album.name}")
|
830
|
-
end
|
824
|
+
one_to_many :albums, adder: (lambda do |album|
|
825
|
+
album.update(artist_id: id, file_under: "#{name}-#{album.name}")
|
826
|
+
end)
|
831
827
|
end
|
832
828
|
|
833
|
-
=== \_remove_<i>association</i>
|
829
|
+
=== :remover (\_remove_<i>association</i> method)
|
834
830
|
|
835
831
|
Continuing with the same example, here's how you would handle the same case if
|
836
832
|
you also wanted to handle the Artist#remove_album method:
|
837
833
|
|
838
834
|
class Artist < Sequel::Model
|
839
|
-
one_to_many :albums
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
def _remove_album(album)
|
844
|
-
album.update(:artist_id => nil, :file_under=>album.name)
|
845
|
-
end
|
835
|
+
one_to_many :albums, remover: (lambda do |album|
|
836
|
+
album.update(artist_id: nil, file_under: album.name)
|
837
|
+
end)
|
846
838
|
end
|
847
839
|
|
848
|
-
=== \_remove_all_<i>association</i>
|
840
|
+
=== :clearer (\_remove_all_<i>association</i> method)
|
849
841
|
|
850
842
|
Continuing with the same example, here's how you would handle the same case if
|
851
843
|
you also wanted to handle the Artist#remove_all_albums method:
|
852
844
|
|
853
845
|
class Artist < Sequel::Model
|
854
|
-
one_to_many :albums
|
855
|
-
|
856
|
-
private
|
857
|
-
|
858
|
-
def _remove_all_albums
|
859
|
-
# This is Dataset#update, not Model#update, so the :file_under=>:name
|
846
|
+
one_to_many :albums, clearer: (lambda do
|
847
|
+
# This is Dataset#update, not Model#update, so the file_under: :name
|
860
848
|
# ends up being "SET file_under = name" in SQL.
|
861
|
-
albums_dataset.update(:
|
862
|
-
end
|
849
|
+
albums_dataset.update(artist_id: nil, file_under: :name)
|
850
|
+
end)
|
863
851
|
end
|
864
852
|
|
865
853
|
== Association Options
|
@@ -868,10 +856,16 @@ Sequel's associations mostly share the same options. For ease of understanding,
|
|
868
856
|
they are grouped here by section.
|
869
857
|
|
870
858
|
The defaults for any of these options can be set at the class level using
|
871
|
-
<tt>Sequel::Model.default_association_options</tt>.
|
872
|
-
|
873
|
-
|
874
|
-
|
859
|
+
<tt>Sequel::Model.default_association_options</tt>. To make
|
860
|
+
associations read only by default:
|
861
|
+
|
862
|
+
Sequel::Model.default_association_options[:read_only] = true
|
863
|
+
|
864
|
+
Many of these options are specific to particular association types, and
|
865
|
+
the defaults can be set on a per association type basis. To make one_to_many
|
866
|
+
associations read only by default:
|
867
|
+
|
868
|
+
Sequel::Model.default_association_type_options[:one_to_many] = {read_only: true}
|
875
869
|
|
876
870
|
=== Association Dataset Modification Options
|
877
871
|
|
@@ -883,7 +877,7 @@ use for the association. For example, if you wanted an association
|
|
883
877
|
that returns all albums of an artist that went gold (sold at least
|
884
878
|
500,000 copies):
|
885
879
|
|
886
|
-
Artist.one_to_many :gold_albums, :
|
880
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
887
881
|
ds.where{copies_sold > 500000}
|
888
882
|
end
|
889
883
|
|
@@ -891,7 +885,7 @@ The result of the block is cached as an optimization. One of the side
|
|
891
885
|
effects of that is that if your block depends on external state, it won't
|
892
886
|
work correctly unless you setup a delayed evaluation. For example:
|
893
887
|
|
894
|
-
Artist.one_to_many :gold_albums, :
|
888
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
895
889
|
ds.where{copies_sold > $gold_limit}
|
896
890
|
end
|
897
891
|
|
@@ -899,7 +893,7 @@ In this case if you change <tt>$gold_limit</tt> later, the changes won't
|
|
899
893
|
effect the association. If you want to pick up changes to <tt>$gold_limit</tt>,
|
900
894
|
you need to setup a delayed evaluation:
|
901
895
|
|
902
|
-
Artist.one_to_many :gold_albums, :
|
896
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
903
897
|
ds.where{copies_sold > Sequel.delay{$gold_limit}}
|
904
898
|
end
|
905
899
|
|
@@ -908,7 +902,7 @@ you need to setup a delayed evaluation:
|
|
908
902
|
This is the class of the associated objects that will be used. It's
|
909
903
|
one of the most commonly used options. If it is not given, it guesses
|
910
904
|
based on the name of the association, including considering the namespace
|
911
|
-
of the current model. If a *_to_many association is used, uses the
|
905
|
+
of the current model. If a *_to_many association is used, this uses the
|
912
906
|
singular form of the association name. For example:
|
913
907
|
|
914
908
|
Album.many_to_one :artist # guesses Artist
|
@@ -927,47 +921,47 @@ default class guessed will be wrong:
|
|
927
921
|
You can specify the :class option using the class itself, a Symbol,
|
928
922
|
or a String:
|
929
923
|
|
930
|
-
Album.many_to_one :artist, :
|
931
|
-
Album.many_to_one :artist, :
|
932
|
-
Album.many_to_one :artist, :
|
924
|
+
Album.many_to_one :artist, class: Artist # Class
|
925
|
+
Album.many_to_one :artist, class: :Artist # Symbol
|
926
|
+
Album.many_to_one :artist, class: "Artist" # String
|
933
927
|
|
934
928
|
If you are namespacing your models, and you need to specify the :class
|
935
929
|
option, the path you give to the :class option should be the full path
|
936
930
|
to the associated class including any namespaces:
|
937
931
|
|
938
|
-
Foo::Album.many_to_one :artist
|
939
|
-
Foo::Album.many_to_one :artist, :
|
940
|
-
Foo::Album.many_to_one :artist, :
|
932
|
+
Foo::Album.many_to_one :artist # Uses Foo::Artist
|
933
|
+
Foo::Album.many_to_one :artist, class: "Artist" # Uses Artist
|
934
|
+
Foo::Album.many_to_one :artist, class: "Foo::Artist" # Uses Foo::Artist
|
941
935
|
|
942
936
|
==== :key
|
943
937
|
|
944
938
|
For +many_to_one+ associations, this is the foreign_key in the current model's
|
945
939
|
table that references the associated model's primary key as a symbol.
|
946
|
-
Defaults to :<i>association</i>_id.
|
947
|
-
composite key association.
|
940
|
+
Defaults to :<i>association</i>_id.
|
948
941
|
|
949
|
-
Album.many_to_one :artist
|
942
|
+
Album.many_to_one :artist, key: :artistid
|
950
943
|
|
951
944
|
For +one_to_one+ and +one_to_many+ associations, is the foreign key in
|
952
945
|
associated model's table that references current model's primary key, as a
|
953
946
|
symbol. Defaults to :"#{self.name.underscore}_id".
|
954
947
|
|
955
|
-
Artist.one_to_many :albums
|
948
|
+
Artist.one_to_many :albums, key: :artistid
|
956
949
|
|
957
950
|
In both cases an array of symbols can be used for a composite key association:
|
958
951
|
|
959
|
-
Apartment.many_to_one :building
|
952
|
+
Apartment.many_to_one :building, key: [:city, :address]
|
960
953
|
|
961
954
|
==== :conditions
|
962
955
|
|
963
956
|
The conditions to use to filter the association, can be any argument passed to +where+.
|
964
957
|
If you use a hash or an array of two element arrays, this will also be used as a
|
965
|
-
filter when using eager_graph or association_join to load the association.
|
966
|
-
|
967
|
-
|
968
|
-
|
958
|
+
filter when using eager_graph or association_join to load the association.
|
959
|
+
|
960
|
+
If you do not use a hash or array of two element arrays, you should use the
|
961
|
+
:graph_conditions, :graph_only_conditions, or :graph_block option or you will not
|
962
|
+
be able to use eager_graph or association_join with the association.
|
969
963
|
|
970
|
-
Artist.one_to_many :good_albums, :
|
964
|
+
Artist.one_to_many :good_albums, class: :Album, conditions: {:good=>true}
|
971
965
|
@artist.good_albums
|
972
966
|
# SELECT * FROM albums WHERE ((artist_id = 1) AND (good IS TRUE))
|
973
967
|
|
@@ -976,10 +970,8 @@ eager_graph or association_join.
|
|
976
970
|
The column(s) by which to order the association dataset. Can be a
|
977
971
|
singular column or an array.
|
978
972
|
|
979
|
-
Artist.one_to_many :albums_by_name, :
|
980
|
-
|
981
|
-
Artist.one_to_many :albums_by_num_tracks, :class=>:Album,
|
982
|
-
:order=>[:num_tracks, :name]
|
973
|
+
Artist.one_to_many :albums_by_name, class: :Album, order: :name
|
974
|
+
Artist.one_to_many :albums_by_num_tracks, class: :Album, order: [:num_tracks, :name]
|
983
975
|
|
984
976
|
==== :select
|
985
977
|
|
@@ -995,20 +987,19 @@ can clash with columns from the associated table, so you should alias any
|
|
995
987
|
columns that have the same name in both the join table and the associated
|
996
988
|
table. Example:
|
997
989
|
|
998
|
-
Artist.one_to_many :albums, :
|
999
|
-
Album.many_to_many :tags, :
|
990
|
+
Artist.one_to_many :albums, select: [:id, :name]
|
991
|
+
Album.many_to_many :tags, select: [Sequel[:tags].*, Sequel[:albums_tags][:number]]
|
1000
992
|
|
1001
993
|
==== :limit
|
1002
994
|
|
1003
995
|
Limit the number of records to the provided value:
|
1004
996
|
|
1005
|
-
Artist.one_to_many :best_selling_albums, :
|
1006
|
-
:order=>:copies_sold, :limit=>5 # LIMIT 5
|
997
|
+
Artist.one_to_many :best_selling_albums, class: :Album, order: :copies_sold, limit: 5
|
1007
998
|
|
1008
999
|
Use an array with two arguments for the value to specify a limit and an offset.
|
1009
1000
|
|
1010
|
-
Artist.one_to_many :next_best_selling_albums, :
|
1011
|
-
|
1001
|
+
Artist.one_to_many :next_best_selling_albums, class: :Album, order: :copies_sold, limit: [10, 5]
|
1002
|
+
# LIMIT 10 OFFSET 5
|
1012
1003
|
|
1013
1004
|
This probably doesn't make a lot of sense for *_to_one associations, though you
|
1014
1005
|
could use it to specify an offset.
|
@@ -1020,16 +1011,16 @@ associated model, as a symbol. Defaults to the name of current model and name
|
|
1020
1011
|
of associated model, pluralized, underscored, sorted, and joined with '_'.
|
1021
1012
|
Here's an example of the defaults:
|
1022
1013
|
|
1023
|
-
Artist.many_to_many :albums
|
1024
|
-
Album.many_to_many :artists
|
1025
|
-
Person.many_to_many :colleges
|
1014
|
+
Artist.many_to_many :albums, join_table: :albums_artists
|
1015
|
+
Album.many_to_many :artists, join_table: :albums_artists
|
1016
|
+
Person.many_to_many :colleges, join_table: :colleges_people
|
1026
1017
|
|
1027
1018
|
==== :left_key [+many_to_many+, +one_through_one+]
|
1028
1019
|
|
1029
1020
|
Foreign key in join table that points to current model's primary key, as a
|
1030
1021
|
symbol. Defaults to :"#{model_name.underscore}_id".
|
1031
1022
|
|
1032
|
-
Album.many_to_many :tags
|
1023
|
+
Album.many_to_many :tags, left_key: :album_id
|
1033
1024
|
|
1034
1025
|
Can use an array of symbols for a composite key association.
|
1035
1026
|
|
@@ -1039,7 +1030,7 @@ Foreign key in join table that points to associated model's primary key, as a
|
|
1039
1030
|
symbol. Defaults to :"#{association_name.singularize}_id" for +many_to_many+
|
1040
1031
|
and :"#{association_name}_id" for +one_through_one+.
|
1041
1032
|
|
1042
|
-
Album.many_to_many :tags
|
1033
|
+
Album.many_to_many :tags, right_key: :tag_id
|
1043
1034
|
|
1044
1035
|
Can use an array of symbols for a composite key association.
|
1045
1036
|
|
@@ -1065,10 +1056,10 @@ into the cloned options.
|
|
1065
1056
|
This is commonly used if you have a bunch of similar associations that
|
1066
1057
|
you want to DRY up:
|
1067
1058
|
|
1068
|
-
one_to_many :english_verses, :
|
1069
|
-
:
|
1070
|
-
one_to_many :romaji_verses, :
|
1071
|
-
one_to_many :japanese_verses, :
|
1059
|
+
one_to_many :english_verses, class: :LyricVerse, key: :lyricsongid,
|
1060
|
+
order: :number, conditions: {languageid: 1}
|
1061
|
+
one_to_many :romaji_verses, clone: :english_verses, conditions: {languageid: 2}
|
1062
|
+
one_to_many :japanese_verses, clone: :english_verses, conditions: {languageid: 3}
|
1072
1063
|
|
1073
1064
|
Note that for the final two asociations, you didn't have to specify the :class,
|
1074
1065
|
:key, or :order options, as they were copied by the :clone option. By specifying
|
@@ -1077,7 +1068,7 @@ option of the first association, it doesn't attempt to merge them.
|
|
1077
1068
|
|
1078
1069
|
In addition to the options hash, the :clone option will copy a block argument
|
1079
1070
|
from the existing situation. If you want a cloned association to not have the
|
1080
|
-
same block as the association you are cloning from, specify the :
|
1071
|
+
same block as the association you are cloning from, specify the block: nil option
|
1081
1072
|
in additon to the :clone option.
|
1082
1073
|
|
1083
1074
|
==== :dataset
|
@@ -1096,16 +1087,14 @@ already applied, and the proc should return a modified copy of this dataset.
|
|
1096
1087
|
Here's an example of an association of songs to artists through lyrics, where
|
1097
1088
|
the artist can perform any one of four tasks for the lyric:
|
1098
1089
|
|
1099
|
-
Album.one_to_many :songs, :
|
1090
|
+
Album.one_to_many :songs, dataset: (lambda do |r|
|
1100
1091
|
r.associated_dataset.select_all(:songs).
|
1101
|
-
join(
|
1102
|
-
id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
|
1092
|
+
join(:lyrics, id: :lyricid, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
|
1103
1093
|
end)
|
1104
1094
|
Artist.first.songs_dataset
|
1105
1095
|
# SELECT songs.* FROM songs
|
1106
|
-
# INNER JOIN lyrics ON
|
1107
|
-
#
|
1108
|
-
# 1 IN (composer_id, arranger_id, vocalist_id, lyricist_id)
|
1096
|
+
# INNER JOIN lyrics ON ((lyrics.id = songs.lyric_id)
|
1097
|
+
# AND (1 IN (composer_id, arranger_id, vocalist_id, lyricist_id))
|
1109
1098
|
|
1110
1099
|
==== :extend
|
1111
1100
|
|
@@ -1122,8 +1111,8 @@ it defaults to the primary key of the table. Can use an
|
|
1122
1111
|
array of symbols for a composite key association.
|
1123
1112
|
|
1124
1113
|
Artist.set_primary_key :arid
|
1125
|
-
Artist.one_to_many :albums
|
1126
|
-
Album.one_to_many :artist
|
1114
|
+
Artist.one_to_many :albums, primary_key: :arid
|
1115
|
+
Album.one_to_many :artist, primary_key: :arid
|
1127
1116
|
|
1128
1117
|
==== :left_primary_key [+many_to_many+, +one_through_one+]
|
1129
1118
|
|
@@ -1131,7 +1120,7 @@ Column in current table that :left_key option points to, as a symbol.
|
|
1131
1120
|
Defaults to primary key of current table.
|
1132
1121
|
|
1133
1122
|
Album.set_primary_key :alid
|
1134
|
-
Album.many_to_many :tags
|
1123
|
+
Album.many_to_many :tags, left_primary_key: :alid
|
1135
1124
|
|
1136
1125
|
Can use an array of symbols for a composite key association.
|
1137
1126
|
|
@@ -1141,7 +1130,7 @@ Column in associated table that :right_key points to, as a symbol.
|
|
1141
1130
|
Defaults to primary key of the associated table.
|
1142
1131
|
|
1143
1132
|
Tag.set_primary_key :tid
|
1144
|
-
Album.many_to_many :tags
|
1133
|
+
Album.many_to_many :tags, right_primary_key: :tid
|
1145
1134
|
|
1146
1135
|
Can use an array of symbols for a composite key association.
|
1147
1136
|
|
@@ -1153,9 +1142,9 @@ join of the join table and the associated table, whereas this option just
|
|
1153
1142
|
applies to the join table. It can be used to make sure that filters are used
|
1154
1143
|
when deleting.
|
1155
1144
|
|
1156
|
-
Artist.many_to_many :lead_guitar_albums, :join_table_block=>
|
1157
|
-
ds.where(:
|
1158
|
-
end
|
1145
|
+
Artist.many_to_many :lead_guitar_albums, class: :Album, :join_table_block=>(lambda do |ds|
|
1146
|
+
ds.where(instrument_id: 5)
|
1147
|
+
end)
|
1159
1148
|
|
1160
1149
|
=== Callback Options
|
1161
1150
|
|
@@ -1165,14 +1154,10 @@ that are called with the associated object. Procs are called with the receiver
|
|
1165
1154
|
as the first argument and the associated object as the second argument. If
|
1166
1155
|
an array is given, all of them are called in order.
|
1167
1156
|
|
1168
|
-
Before callbacks are often used to check preconditions, they can
|
1169
|
-
|
1170
|
-
|
1171
|
-
is aborted.
|
1172
|
-
object or the associated object.
|
1173
|
-
|
1174
|
-
After callbacks are often used for notification (logging, email) after a
|
1175
|
-
successful modification has been made.
|
1157
|
+
Before callbacks are often used to check preconditions, they can call Model#cancel_action
|
1158
|
+
to signal Sequel to abort the modification. If any before callback
|
1159
|
+
calls cancel_action, the remaining before callbacks are not called and the modification
|
1160
|
+
is aborted.
|
1176
1161
|
|
1177
1162
|
==== :before_add [+one_to_many+, +many_to_many+]
|
1178
1163
|
|
@@ -1180,7 +1165,7 @@ Called before adding an object to the association:
|
|
1180
1165
|
|
1181
1166
|
class Artist
|
1182
1167
|
# Don't allow adding an album to an artist if it has no tracks
|
1183
|
-
one_to_many :albums, :
|
1168
|
+
one_to_many :albums, before_add: lambda{|ar, al| artist.cancel_action if al.num_tracks == 0}
|
1184
1169
|
end
|
1185
1170
|
|
1186
1171
|
==== :after_add [+one_to_many+, +many_to_many+]
|
@@ -1189,12 +1174,12 @@ Called after adding an object to the association:
|
|
1189
1174
|
|
1190
1175
|
class Artist
|
1191
1176
|
# Log all associations of albums to an audit logging table
|
1192
|
-
one_to_many :albums, :
|
1177
|
+
one_to_many :albums, after_add: :log_add_album
|
1193
1178
|
|
1194
1179
|
private
|
1195
1180
|
|
1196
1181
|
def log_add_album(album)
|
1197
|
-
DB[:audit_logs].insert(:
|
1182
|
+
DB[:audit_logs].insert(log: "Album #{album.inspect} associated to #{inspect}")
|
1198
1183
|
end
|
1199
1184
|
end
|
1200
1185
|
|
@@ -1204,7 +1189,7 @@ Called before removing an object from the association using <tt>remove_<i>associ
|
|
1204
1189
|
|
1205
1190
|
class Artist
|
1206
1191
|
# Don't allow removing a self-titled album
|
1207
|
-
one_to_many :albums, :
|
1192
|
+
one_to_many :albums, before_remove: lambda{|ar, al| artist.cancel_action if al.name == ar.name}
|
1208
1193
|
end
|
1209
1194
|
|
1210
1195
|
This is not called when using <tt>remove_all_<i>association</i></tt>.
|
@@ -1215,12 +1200,12 @@ Called after removing an object from the association using <tt>remove_<i>associa
|
|
1215
1200
|
|
1216
1201
|
class Artist
|
1217
1202
|
# Log all disassociations of albums to an audit logging table
|
1218
|
-
one_to_many :albums, :
|
1203
|
+
one_to_many :albums, after_remove: :log_remove_album
|
1219
1204
|
|
1220
1205
|
private
|
1221
1206
|
|
1222
1207
|
def log_remove_album(album)
|
1223
|
-
DB[:audit_logs].insert(:
|
1208
|
+
DB[:audit_logs].insert(log: "Album #{album.inspect} disassociated from #{inspect}")
|
1224
1209
|
end
|
1225
1210
|
end
|
1226
1211
|
|
@@ -1233,7 +1218,7 @@ Called before the _<i>association</i>= method is called to modify the objects:
|
|
1233
1218
|
class Album
|
1234
1219
|
# Don't associate the album with an artist if the year the album was
|
1235
1220
|
# released is less than the year the artist/band started.
|
1236
|
-
many_to_one :artist, :
|
1221
|
+
many_to_one :artist, before_set: lambda{|al, ar| al.cancel_action if al.year < ar.year_started}
|
1237
1222
|
end
|
1238
1223
|
|
1239
1224
|
==== :after_set [+many_to_one+, +one_to_one+]
|
@@ -1242,12 +1227,12 @@ Called after the _<i>association</i>= method is called to modify the objects:
|
|
1242
1227
|
|
1243
1228
|
class Album
|
1244
1229
|
# Log all disassociations of albums to an audit logging table
|
1245
|
-
many_to_one :artist, :
|
1230
|
+
many_to_one :artist, after_set: :log_artist_set
|
1246
1231
|
|
1247
1232
|
private
|
1248
1233
|
|
1249
1234
|
def log_artist_set(artist)
|
1250
|
-
DB[:audit_logs].insert(:
|
1235
|
+
DB[:audit_logs].insert(log: "Artist for album #{inspect} set to #{artist.inspect}")
|
1251
1236
|
end
|
1252
1237
|
end
|
1253
1238
|
|
@@ -1256,16 +1241,15 @@ Called after the _<i>association</i>= method is called to modify the objects:
|
|
1256
1241
|
Called after retrieving the associated records from the database.
|
1257
1242
|
|
1258
1243
|
class Artist
|
1259
|
-
# Cache all album names to a single string when retrieving the
|
1260
|
-
|
1261
|
-
one_to_many :albums, :after_load=>:cache_album_names
|
1244
|
+
# Cache all album names to a single string when retrieving the albums.
|
1245
|
+
one_to_many :albums, after_load: :cache_album_names
|
1262
1246
|
|
1263
1247
|
attr_reader :album_names
|
1264
1248
|
|
1265
1249
|
private
|
1266
1250
|
|
1267
1251
|
def cache_album_names(albums)
|
1268
|
-
@album_names = albums.map
|
1252
|
+
@album_names = albums.map(&:name).join(", ")
|
1269
1253
|
end
|
1270
1254
|
end
|
1271
1255
|
|
@@ -1293,17 +1277,17 @@ For example, if you know that any time that you want to load an artist's
|
|
1293
1277
|
albums, you are also going to want access to the album's tracks as well:
|
1294
1278
|
|
1295
1279
|
# Eager load tracks when loading the albums
|
1296
|
-
Artist.one_to_many :albums, :
|
1280
|
+
Artist.one_to_many :albums, eager: :tracks
|
1297
1281
|
|
1298
1282
|
You can also use a hash or array to specify multiple dependent associations
|
1299
1283
|
to eagerly load:
|
1300
1284
|
|
1301
1285
|
# Eager load the albums' tracks and the tracks' tags when loading the albums
|
1302
|
-
Artist.one_to_many :albums, :
|
1286
|
+
Artist.one_to_many :albums, eager: {tracks: :tags}
|
1303
1287
|
# Eager load the albums' tags and tracks when loading the albums
|
1304
|
-
Artist.one_to_many :albums, :
|
1288
|
+
Artist.one_to_many :albums, eager: [:tags, :tracks]
|
1305
1289
|
# Eager load the albums' tags, tracks, and tracks' tags when loading the albums
|
1306
|
-
Artist.one_to_many :albums, :
|
1290
|
+
Artist.one_to_many :albums, eager: [:tags, {tracks: :tags}]
|
1307
1291
|
|
1308
1292
|
==== :eager_loader
|
1309
1293
|
|
@@ -1322,7 +1306,7 @@ performance if a custom eager loader does not use the key_hash).
|
|
1322
1306
|
|
1323
1307
|
If given, should be a proc to use instead of the association method block
|
1324
1308
|
when eagerly loading. To not use a block when eager loading when one is
|
1325
|
-
used normally,
|
1309
|
+
used normally, set to nil. It's very uncommon to need this option.
|
1326
1310
|
|
1327
1311
|
=== Eager Loading via eager_graph (one query with joins) Options
|
1328
1312
|
|
@@ -1333,12 +1317,10 @@ object(s). This is useful for example if you always want to eagerly load depende
|
|
1333
1317
|
associations when loading this association, but you want to filter or order the
|
1334
1318
|
association based on dependent associations:
|
1335
1319
|
|
1336
|
-
Artist.one_to_many :albums_with_short_tracks, :
|
1337
|
-
:eager_graph=>:tracks do |ds|
|
1320
|
+
Artist.one_to_many :albums_with_short_tracks, class: :Album, eager_graph: :tracks do |ds|
|
1338
1321
|
ds.where{tracks[:seconds] < 120}
|
1339
1322
|
end
|
1340
|
-
Artist.one_to_many :albums_by_track_name, :
|
1341
|
-
:eager_graph=>:tracks do |ds|
|
1323
|
+
Artist.one_to_many :albums_by_track_name, class: :Album, eager_graph: :tracks do |ds|
|
1342
1324
|
ds.order{tracks[:name]}
|
1343
1325
|
end
|
1344
1326
|
|
@@ -1352,8 +1334,7 @@ association via eager_graph. Should be a hash or an array of two element
|
|
1352
1334
|
arrays. If not specified, the :conditions option is used if it is a hash or
|
1353
1335
|
array of two element arrays.
|
1354
1336
|
|
1355
|
-
Artist.one_to_many :active_albums, :
|
1356
|
-
:graph_conditions=>{:active=>true}
|
1337
|
+
Artist.one_to_many :active_albums, class: :Album, graph_conditions: {active: true}
|
1357
1338
|
|
1358
1339
|
Note that these conditions on the association are in addition to the default
|
1359
1340
|
conditions specified by the foreign/primary keys. If you want to replace
|
@@ -1366,8 +1347,8 @@ The block to pass to Dataset#join_table when eagerly loading the association
|
|
1366
1347
|
via eager_graph. This is useful to specify conditions that can't be specified
|
1367
1348
|
in a hash or array of two element arrays.
|
1368
1349
|
|
1369
|
-
Artist.one_to_many :gold_albums, :
|
1370
|
-
:
|
1350
|
+
Artist.one_to_many :gold_albums, class: :Album,
|
1351
|
+
graph_block: proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
|
1371
1352
|
|
1372
1353
|
==== :graph_join_type
|
1373
1354
|
|
@@ -1375,7 +1356,7 @@ The type of SQL join to use when eagerly loading the association via
|
|
1375
1356
|
eager_graph. Defaults to :left_outer. This is useful if you want to
|
1376
1357
|
ensure that only artists that have albums are returned:
|
1377
1358
|
|
1378
|
-
Artist.one_to_many :albums, :
|
1359
|
+
Artist.one_to_many :albums, graph_join_type: :inner
|
1379
1360
|
# Will exclude artists without an album
|
1380
1361
|
Artist.eager_graph(:albums).all
|
1381
1362
|
|
@@ -1397,10 +1378,11 @@ that the album was associated to the artist by name. However, you weren't
|
|
1397
1378
|
enforcing case sensitivity between the keys, so you still want to return albums
|
1398
1379
|
where the artist's name differs in case:
|
1399
1380
|
|
1400
|
-
Artist.one_to_many :albums, :
|
1401
|
-
:
|
1402
|
-
:
|
1403
|
-
Sequel.function(:lower, Sequel[lj][:name])}
|
1381
|
+
Artist.one_to_many :albums, key: :artist_name,
|
1382
|
+
graph_only_conditions: nil,
|
1383
|
+
graph_block: (proc do |j,lj,js|
|
1384
|
+
{Sequel.function(:lower, Sequel[j][:artist_name])=> Sequel.function(:lower, Sequel[lj][:name])}
|
1385
|
+
end)
|
1404
1386
|
|
1405
1387
|
Note how :graph_only_conditions is set to nil to ignore any existing conditions,
|
1406
1388
|
and :graph_block is used to set up the case insensitive comparison.
|
@@ -1409,12 +1391,10 @@ Another case where :graph_only_conditions may be used is if you want to use
|
|
1409
1391
|
a JOIN USING or NATURAL JOIN for the graph:
|
1410
1392
|
|
1411
1393
|
# JOIN USING
|
1412
|
-
Artist.one_to_many :albums, :
|
1413
|
-
:graph_only_conditions=>[:artist_name]
|
1394
|
+
Artist.one_to_many :albums, key: :artist_name, graph_only_conditions: [:artist_name]
|
1414
1395
|
|
1415
1396
|
# NATURAL JOIN
|
1416
|
-
Artist.one_to_many :albums, :
|
1417
|
-
:graph_only_conditions=>nil, :graph_join_type=>:natural
|
1397
|
+
Artist.one_to_many :albums, key: :artist_name, graph_only_conditions: nil, graph_join_type: :natural
|
1418
1398
|
|
1419
1399
|
==== :graph_alias_base
|
1420
1400
|
|
@@ -1427,7 +1407,7 @@ This is mostly useful if you have associations with the same name in many models
|
|
1427
1407
|
to be able to easily tell which table alias corresponds to which association when eagerly
|
1428
1408
|
graphing multiple associations with the same name.
|
1429
1409
|
|
1430
|
-
You can override this option on a per-
|
1410
|
+
You can override this option on a per-eager_graph basis by specifying the association as an
|
1431
1411
|
SQL::AliasedExpression instead of a symbol:
|
1432
1412
|
|
1433
1413
|
Album.eager_graph(Sequel.as(:artist, :a))
|
@@ -1452,10 +1432,10 @@ at least the following keys:
|
|
1452
1432
|
|
1453
1433
|
Example:
|
1454
1434
|
|
1455
|
-
Artist.one_to_many :self_title_albums, :
|
1456
|
-
:eager_grapher=>(
|
1457
|
-
eo[:self].graph(
|
1458
|
-
:
|
1435
|
+
Artist.one_to_many :self_title_albums, class: :Album,
|
1436
|
+
:eager_grapher=>(lambda do |eo|
|
1437
|
+
eo[:self].graph(:albums, {artist_id: :id, name: :name},
|
1438
|
+
table_alias: eo[:table_alias], implicit_qualifier: eo[:implicit_qualifier])
|
1459
1439
|
end)
|
1460
1440
|
|
1461
1441
|
==== :order_eager_graph
|
@@ -1486,9 +1466,9 @@ degrees_received that includes a string field specifying the name of the
|
|
1486
1466
|
degree, and you want to eager load all colleges for people where the person
|
1487
1467
|
has received a specific degree:
|
1488
1468
|
|
1489
|
-
Person.many_to_many :bs_degree_colleges, :
|
1490
|
-
:
|
1491
|
-
:
|
1469
|
+
Person.many_to_many :bs_degree_colleges, class: :College,
|
1470
|
+
join_table: :degrees_received,
|
1471
|
+
graph_join_table_conditions: {degree: 'BS'}
|
1492
1472
|
|
1493
1473
|
==== :graph_join_table_block [+many_to_many+, +one_through_one+]
|
1494
1474
|
|
@@ -1505,9 +1485,9 @@ degrees_received that includes a string field specifying the name of the
|
|
1505
1485
|
degree, and you want to eager load all colleges for people where the person
|
1506
1486
|
has received a bachelor's degree (degree starting with B):
|
1507
1487
|
|
1508
|
-
Person.many_to_many :bachelor_degree_colleges, :
|
1509
|
-
:
|
1510
|
-
:
|
1488
|
+
Person.many_to_many :bachelor_degree_colleges, class: :College,
|
1489
|
+
join_table: :degrees_received,
|
1490
|
+
graph_join_table_block: proc{|j,lj,js| Sequel[j][:degree].like('B%')}
|
1511
1491
|
|
1512
1492
|
This should be done when graphing the join table, instead of when graphing the
|
1513
1493
|
final table, as :degree is a column of the join table.
|
@@ -1534,7 +1514,7 @@ would use when eagerly graphing.
|
|
1534
1514
|
Sequel's associations can work not just with columns, but also with
|
1535
1515
|
arbitrary SQL expressions. For example, on PostgreSQL, you can store
|
1536
1516
|
foreign keys to other tables in hstore, json, or jsonb columns, and Sequel
|
1537
|
-
can
|
1517
|
+
can work with such constructs, including full support for
|
1538
1518
|
eager loading.
|
1539
1519
|
|
1540
1520
|
There's actually two parts to supporting associations based on SQL
|
@@ -1547,7 +1527,7 @@ to a model instance, but needs to use the SQL expression in a query,
|
|
1547
1527
|
it will use the SQL expression object.
|
1548
1528
|
|
1549
1529
|
Below is an example storing foreign keys to other tables in a
|
1550
|
-
PostgreSQL hstore column, using the +
|
1530
|
+
PostgreSQL hstore column, using the +pg_json+ and +pg_json_ops+
|
1551
1531
|
extensions.
|
1552
1532
|
|
1553
1533
|
# Example schema:
|
@@ -1556,14 +1536,14 @@ extensions.
|
|
1556
1536
|
# :meta ---/ :name
|
1557
1537
|
# :name
|
1558
1538
|
class Album < Sequel::Model
|
1559
|
-
many_to_one :artist, :
|
1539
|
+
many_to_one :artist, key_column: Sequel.pg_jsonb(:meta)['artist_id'].cast(String).cast(Integer)
|
1560
1540
|
|
1561
1541
|
def artist_id
|
1562
1542
|
meta['artist_id'].to_i
|
1563
1543
|
end
|
1564
1544
|
end
|
1565
1545
|
class Artist < Sequel::Model
|
1566
|
-
one_to_many :albums, :
|
1546
|
+
one_to_many :albums, key: Sequel.pg_jsonb(:meta)['artist_id'].cast(String).cast(Integer), key_method: :artist_id
|
1567
1547
|
end
|
1568
1548
|
|
1569
1549
|
# Example schema:
|
@@ -1571,12 +1551,12 @@ extensions.
|
|
1571
1551
|
# :id <----- :meta -------> :id
|
1572
1552
|
# :name :name
|
1573
1553
|
class Album < Sequel::Model
|
1574
|
-
many_to_many :artists, :
|
1575
|
-
:
|
1554
|
+
many_to_many :artists, left_key: Sequel.pg_jsonb(:meta)['album_id'].cast(String).cast(Integer)
|
1555
|
+
right_key: Sequel.pg_jsonb(:meta)['artist_id'].cast(String).cast(Integer)
|
1576
1556
|
end
|
1577
1557
|
class Artist < Sequel::Model
|
1578
|
-
many_to_many :albums, :
|
1579
|
-
:
|
1558
|
+
many_to_many :albums, left_key: Sequel.pg_jsonb(:meta)['artist_id'].cast(String).cast(Integer)
|
1559
|
+
right_key: Sequel.pg_jsonb(:meta)['album_id'].cast(String).cast(Integer)
|
1580
1560
|
end
|
1581
1561
|
|
1582
1562
|
==== :key_column [+many_to_one+]
|
@@ -1609,62 +1589,6 @@ Like the :left_primary_key option, but :left_primary_key references the method n
|
|
1609
1589
|
Like the :right_primary_key option, but :right_primary_key references the column/expression
|
1610
1590
|
name, while :right_primary_key_method references the method name.
|
1611
1591
|
|
1612
|
-
=== Private Method Overriding Options
|
1613
|
-
|
1614
|
-
These options override the private methods that Sequel defines to do
|
1615
|
-
the actual work of associating and deassociating objects.
|
1616
|
-
|
1617
|
-
==== :setter [*_to_one associations]
|
1618
|
-
|
1619
|
-
This overrides the default behavior when you call an association setter
|
1620
|
-
method. Let's say you want to set a specific field whenever associating an object
|
1621
|
-
using the association setter method.
|
1622
|
-
|
1623
|
-
class Album < Sequel::Model
|
1624
|
-
many_to_one :artist, :setter=>(proc do |artist|
|
1625
|
-
if artist
|
1626
|
-
self.artist_id = artist.id
|
1627
|
-
self.file_under = "#{artist.name}-#{name}"
|
1628
|
-
else
|
1629
|
-
self.artist_id = nil
|
1630
|
-
self.file_under = name
|
1631
|
-
end
|
1632
|
-
end)
|
1633
|
-
end
|
1634
|
-
|
1635
|
-
==== :adder [*_to_many associations]
|
1636
|
-
|
1637
|
-
Continuing with the same example, here's how you would handle the same case if
|
1638
|
-
you also wanted to handle the Artist#add_album method:
|
1639
|
-
|
1640
|
-
class Artist < Sequel::Model
|
1641
|
-
one_to_many :albums, :adder=>(proc do |album|
|
1642
|
-
album.update(:artist_id => id, :file_under=>"#{name}-#{album.name}")
|
1643
|
-
end)
|
1644
|
-
end
|
1645
|
-
|
1646
|
-
==== :remover [*_to_many associations]
|
1647
|
-
|
1648
|
-
Continuing with the same example, here's how you would handle the same case if
|
1649
|
-
you also wanted to handle the Artist#remove_album method:
|
1650
|
-
|
1651
|
-
class Artist < Sequel::Model
|
1652
|
-
one_to_many :albums, :remover=>(proc do |album|
|
1653
|
-
album.update(:artist_id => nil, :file_under=>album.name)
|
1654
|
-
end)
|
1655
|
-
end
|
1656
|
-
|
1657
|
-
==== :clearer [*_to_many associations]
|
1658
|
-
|
1659
|
-
Continuing with the same example, here's how you would handle the same case if
|
1660
|
-
you also wanted to handle the Artist#remove_all_albums method:
|
1661
|
-
|
1662
|
-
class Artist < Sequel::Model
|
1663
|
-
one_to_many :albums, :clearer=>(proc do
|
1664
|
-
albums_dataset.update(:artist_id => nil, :file_under=>:name)
|
1665
|
-
end)
|
1666
|
-
end
|
1667
|
-
|
1668
1592
|
=== Advanced Options
|
1669
1593
|
|
1670
1594
|
==== :reciprocal
|
@@ -1676,7 +1600,7 @@ Set to nil to not use a reciprocal.
|
|
1676
1600
|
|
1677
1601
|
Reciprocals are used in Sequel to modify the matching cached associations
|
1678
1602
|
in associated objects when calling association methods on the current object.
|
1679
|
-
For example, when you retrieve objects in a one_to_many association,
|
1603
|
+
For example, when you retrieve objects in a one_to_many association, Sequel will
|
1680
1604
|
automatically set the matching many_to_one association in the associated
|
1681
1605
|
objects. The result of this is that code that does this:
|
1682
1606
|
|
@@ -1732,7 +1656,7 @@ the validate option should be set to false.
|
|
1732
1656
|
Set to false to not raise an exception when validation or a before hook
|
1733
1657
|
fails when implicitly saving an associated object in the add_* or remove_*
|
1734
1658
|
methods. This mirrors the raise_on_save_failure model setting, which these
|
1735
|
-
methods do not respect (by design
|
1659
|
+
methods do not respect (by design).
|
1736
1660
|
|
1737
1661
|
If you use this option, you must explicitly check all add_* and remove_* return
|
1738
1662
|
values to see if they were successful.
|
@@ -1742,7 +1666,7 @@ values to see if they were successful.
|
|
1742
1666
|
If set to false, you cannot load the association eagerly via eager or
|
1743
1667
|
eager_graph.
|
1744
1668
|
|
1745
|
-
Artist.one_to_many :albums, :
|
1669
|
+
Artist.one_to_many :albums, allow_eager: false
|
1746
1670
|
Artist.eager(:albums) # Raises Sequel::Error
|
1747
1671
|
|
1748
1672
|
This is usually used if the association dataset depends on specific values in
|
@@ -1778,18 +1702,18 @@ in which to look up the class. If the :class option is not specified as a
|
|
1778
1702
|
symbol or string, this option is ignored. This namespace can be overridden
|
1779
1703
|
by starting the string or symbol with <tt>::</tt>:
|
1780
1704
|
|
1781
|
-
Foo::Album.many_to_one :artist, :
|
1782
|
-
Foo::Album.many_to_one :artist, :
|
1783
|
-
Foo::Album.many_to_one :artist, :
|
1784
|
-
Foo::Album.many_to_one :artist, :
|
1785
|
-
Foo::Album.many_to_one :artist, :
|
1705
|
+
Foo::Album.many_to_one :artist, class: "Artist" # Uses Artist
|
1706
|
+
Foo::Album.many_to_one :artist, class: "Artist", class_namespace: 'Foo' # Uses Foo::Artist
|
1707
|
+
Foo::Album.many_to_one :artist, class: "Foo::Artist", class_namespace: 'Foo' # Uses Foo::Foo::Artist
|
1708
|
+
Foo::Album.many_to_one :artist, class: "::Artist", class_namespace: 'Foo' # Uses Artist
|
1709
|
+
Foo::Album.many_to_one :artist, class: "::Foo::Artist", class_namespace: 'Foo' # Uses Foo::Artist
|
1786
1710
|
|
1787
1711
|
==== :methods_module
|
1788
1712
|
|
1789
1713
|
The module that the methods created by the association will be placed
|
1790
|
-
into. Defaults to the module containing the model's columns.
|
1791
|
-
is not included in the model's class,
|
1792
|
-
that manually.
|
1714
|
+
into. Defaults to the module containing the model's columns. Any module
|
1715
|
+
given to this option is not included in the model's class automatically,
|
1716
|
+
so you are responsible for doing that manually.
|
1793
1717
|
|
1794
1718
|
This is only useful in rare cases, such as when a plugin that adds
|
1795
1719
|
associations depends on another plugin that defines instance methods of
|
@@ -1833,4 +1757,3 @@ Sequel will choose either a :distinct_on, :window_function, or
|
|
1833
1757
|
:correlated_subquery strategy based on the association type and what
|
1834
1758
|
the database supports, but you can override that if necessary using
|
1835
1759
|
this option.
|
1836
|
-
|