sequel 4.26.0 → 5.37.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 +5 -5
- data/CHANGELOG +405 -5656
- data/MIT-LICENSE +1 -1
- data/README.rdoc +232 -157
- data/bin/sequel +32 -9
- data/doc/advanced_associations.rdoc +252 -188
- data/doc/association_basics.rdoc +231 -273
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +75 -48
- data/doc/code_order.rdoc +28 -10
- data/doc/core_extensions.rdoc +104 -63
- data/doc/dataset_basics.rdoc +12 -21
- data/doc/dataset_filtering.rdoc +99 -86
- data/doc/extensions.rdoc +3 -10
- data/doc/mass_assignment.rdoc +74 -31
- data/doc/migration.rdoc +72 -46
- data/doc/model_dataset_method_design.rdoc +129 -0
- data/doc/model_hooks.rdoc +15 -25
- data/doc/model_plugins.rdoc +12 -12
- data/doc/mssql_stored_procedures.rdoc +3 -3
- data/doc/object_model.rdoc +59 -69
- data/doc/opening_databases.rdoc +84 -94
- data/doc/postgresql.rdoc +268 -38
- data/doc/prepared_statements.rdoc +29 -24
- data/doc/querying.rdoc +184 -164
- data/doc/reflection.rdoc +5 -6
- data/doc/release_notes/5.0.0.txt +159 -0
- data/doc/release_notes/5.1.0.txt +31 -0
- data/doc/release_notes/5.10.0.txt +84 -0
- data/doc/release_notes/5.11.0.txt +83 -0
- data/doc/release_notes/5.12.0.txt +141 -0
- data/doc/release_notes/5.13.0.txt +27 -0
- data/doc/release_notes/5.14.0.txt +63 -0
- data/doc/release_notes/5.15.0.txt +39 -0
- data/doc/release_notes/5.16.0.txt +110 -0
- data/doc/release_notes/5.17.0.txt +31 -0
- data/doc/release_notes/5.18.0.txt +69 -0
- data/doc/release_notes/5.19.0.txt +28 -0
- data/doc/release_notes/5.2.0.txt +33 -0
- data/doc/release_notes/5.20.0.txt +89 -0
- data/doc/release_notes/5.21.0.txt +87 -0
- data/doc/release_notes/5.22.0.txt +48 -0
- data/doc/release_notes/5.23.0.txt +56 -0
- data/doc/release_notes/5.24.0.txt +56 -0
- data/doc/release_notes/5.25.0.txt +32 -0
- data/doc/release_notes/5.26.0.txt +35 -0
- data/doc/release_notes/5.27.0.txt +21 -0
- data/doc/release_notes/5.28.0.txt +16 -0
- data/doc/release_notes/5.29.0.txt +22 -0
- data/doc/release_notes/5.3.0.txt +121 -0
- data/doc/release_notes/5.30.0.txt +20 -0
- data/doc/release_notes/5.31.0.txt +148 -0
- data/doc/release_notes/5.32.0.txt +46 -0
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.4.0.txt +80 -0
- data/doc/release_notes/5.5.0.txt +61 -0
- data/doc/release_notes/5.6.0.txt +31 -0
- data/doc/release_notes/5.7.0.txt +108 -0
- data/doc/release_notes/5.8.0.txt +170 -0
- data/doc/release_notes/5.9.0.txt +99 -0
- data/doc/schema_modification.rdoc +102 -77
- data/doc/security.rdoc +160 -87
- data/doc/sharding.rdoc +74 -47
- data/doc/sql.rdoc +135 -122
- data/doc/testing.rdoc +34 -18
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +101 -19
- data/doc/validations.rdoc +64 -51
- data/doc/virtual_rows.rdoc +90 -109
- data/lib/sequel.rb +3 -1
- data/lib/sequel/adapters/ado.rb +154 -22
- data/lib/sequel/adapters/ado/access.rb +21 -21
- data/lib/sequel/adapters/ado/mssql.rb +8 -15
- data/lib/sequel/adapters/amalgalite.rb +17 -25
- data/lib/sequel/adapters/ibmdb.rb +52 -58
- data/lib/sequel/adapters/jdbc.rb +149 -127
- data/lib/sequel/adapters/jdbc/db2.rb +32 -40
- data/lib/sequel/adapters/jdbc/derby.rb +56 -58
- data/lib/sequel/adapters/jdbc/h2.rb +40 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +22 -33
- data/lib/sequel/adapters/jdbc/jtds.rb +4 -10
- data/lib/sequel/adapters/jdbc/mssql.rb +6 -12
- data/lib/sequel/adapters/jdbc/mysql.rb +17 -18
- data/lib/sequel/adapters/jdbc/oracle.rb +25 -19
- data/lib/sequel/adapters/jdbc/postgresql.rb +90 -69
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +14 -24
- data/lib/sequel/adapters/jdbc/sqlite.rb +50 -12
- data/lib/sequel/adapters/jdbc/sqlserver.rb +36 -9
- data/lib/sequel/adapters/jdbc/transactions.rb +25 -39
- data/lib/sequel/adapters/mock.rb +104 -113
- data/lib/sequel/adapters/mysql.rb +42 -61
- data/lib/sequel/adapters/mysql2.rb +126 -35
- data/lib/sequel/adapters/odbc.rb +21 -28
- data/lib/sequel/adapters/odbc/db2.rb +3 -1
- data/lib/sequel/adapters/odbc/mssql.rb +11 -15
- data/lib/sequel/adapters/odbc/oracle.rb +11 -0
- data/lib/sequel/adapters/oracle.rb +62 -68
- data/lib/sequel/adapters/postgres.rb +257 -311
- data/lib/sequel/adapters/postgresql.rb +3 -1
- data/lib/sequel/adapters/shared/access.rb +75 -79
- data/lib/sequel/adapters/shared/db2.rb +96 -74
- data/lib/sequel/adapters/shared/mssql.rb +258 -213
- data/lib/sequel/adapters/shared/mysql.rb +284 -216
- data/lib/sequel/adapters/shared/oracle.rb +175 -60
- data/lib/sequel/adapters/shared/postgres.rb +829 -383
- data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -127
- data/lib/sequel/adapters/shared/sqlite.rb +382 -159
- data/lib/sequel/adapters/sqlanywhere.rb +53 -38
- data/lib/sequel/adapters/sqlite.rb +111 -105
- data/lib/sequel/adapters/tinytds.rb +38 -46
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -9
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
- data/lib/sequel/adapters/utils/replace.rb +3 -4
- data/lib/sequel/adapters/utils/split_alter_table.rb +2 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
- data/lib/sequel/ast_transformer.rb +13 -89
- data/lib/sequel/connection_pool.rb +54 -26
- data/lib/sequel/connection_pool/sharded_single.rb +19 -12
- data/lib/sequel/connection_pool/sharded_threaded.rb +160 -111
- data/lib/sequel/connection_pool/single.rb +21 -12
- data/lib/sequel/connection_pool/threaded.rb +137 -119
- data/lib/sequel/core.rb +352 -320
- data/lib/sequel/database.rb +19 -2
- data/lib/sequel/database/connecting.rb +70 -55
- data/lib/sequel/database/dataset.rb +15 -5
- data/lib/sequel/database/dataset_defaults.rb +20 -102
- data/lib/sequel/database/features.rb +20 -4
- data/lib/sequel/database/logging.rb +25 -7
- data/lib/sequel/database/misc.rb +132 -118
- data/lib/sequel/database/query.rb +51 -28
- data/lib/sequel/database/schema_generator.rb +188 -75
- data/lib/sequel/database/schema_methods.rb +161 -92
- data/lib/sequel/database/transactions.rb +260 -58
- data/lib/sequel/dataset.rb +28 -12
- data/lib/sequel/dataset/actions.rb +354 -170
- data/lib/sequel/dataset/dataset_module.rb +46 -0
- data/lib/sequel/dataset/features.rb +81 -34
- data/lib/sequel/dataset/graph.rb +82 -58
- data/lib/sequel/dataset/misc.rb +139 -47
- data/lib/sequel/dataset/placeholder_literalizer.rb +66 -26
- data/lib/sequel/dataset/prepared_statements.rb +188 -85
- data/lib/sequel/dataset/query.rb +428 -214
- data/lib/sequel/dataset/sql.rb +446 -339
- data/lib/sequel/deprecated.rb +14 -2
- data/lib/sequel/exceptions.rb +48 -16
- data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
- data/lib/sequel/extensions/_model_pg_row.rb +43 -0
- data/lib/sequel/extensions/_pretty_table.rb +10 -9
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +15 -11
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/blank.rb +2 -0
- data/lib/sequel/extensions/caller_logging.rb +79 -0
- data/lib/sequel/extensions/columns_introspection.rb +9 -4
- data/lib/sequel/extensions/connection_expiration.rb +99 -0
- data/lib/sequel/extensions/connection_validator.rb +26 -13
- data/lib/sequel/extensions/constant_sql_override.rb +65 -0
- data/lib/sequel/extensions/constraint_validations.rb +93 -38
- data/lib/sequel/extensions/core_extensions.rb +45 -53
- data/lib/sequel/extensions/core_refinements.rb +44 -46
- data/lib/sequel/extensions/current_datetime_timestamp.rb +5 -4
- data/lib/sequel/extensions/dataset_source_alias.rb +4 -0
- data/lib/sequel/extensions/date_arithmetic.rb +42 -16
- data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +94 -0
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -3
- data/lib/sequel/extensions/error_sql.rb +7 -3
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +14 -15
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/freeze_datasets.rb +3 -0
- data/lib/sequel/extensions/from_block.rb +2 -31
- data/lib/sequel/extensions/graph_each.rb +19 -6
- data/lib/sequel/extensions/identifier_mangling.rb +180 -0
- data/lib/sequel/extensions/implicit_subquery.rb +48 -0
- data/lib/sequel/extensions/index_caching.rb +109 -0
- data/lib/sequel/extensions/inflector.rb +8 -4
- data/lib/sequel/extensions/integer64.rb +32 -0
- data/lib/sequel/extensions/looser_typecasting.rb +19 -9
- data/lib/sequel/extensions/migration.rb +132 -80
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +4 -0
- data/lib/sequel/extensions/named_timezones.rb +88 -23
- data/lib/sequel/extensions/no_auto_literal_strings.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +12 -8
- data/lib/sequel/extensions/pagination.rb +35 -28
- data/lib/sequel/extensions/pg_array.rb +227 -316
- data/lib/sequel/extensions/pg_array_ops.rb +19 -7
- data/lib/sequel/extensions/pg_enum.rb +69 -24
- data/lib/sequel/extensions/pg_extended_date_support.rb +250 -0
- data/lib/sequel/extensions/pg_hstore.rb +50 -59
- data/lib/sequel/extensions/pg_hstore_ops.rb +9 -3
- data/lib/sequel/extensions/pg_inet.rb +34 -15
- data/lib/sequel/extensions/pg_inet_ops.rb +5 -1
- data/lib/sequel/extensions/pg_interval.rb +26 -26
- data/lib/sequel/extensions/pg_json.rb +422 -141
- data/lib/sequel/extensions/pg_json_ops.rb +248 -9
- data/lib/sequel/extensions/pg_loose_count.rb +5 -1
- data/lib/sequel/extensions/pg_range.rb +162 -146
- data/lib/sequel/extensions/pg_range_ops.rb +10 -5
- data/lib/sequel/extensions/pg_row.rb +53 -87
- data/lib/sequel/extensions/pg_row_ops.rb +36 -13
- data/lib/sequel/extensions/pg_static_cache_updater.rb +6 -2
- data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
- data/lib/sequel/extensions/pretty_table.rb +4 -0
- data/lib/sequel/extensions/query.rb +12 -7
- data/lib/sequel/extensions/round_timestamps.rb +6 -9
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +59 -0
- data/lib/sequel/extensions/schema_caching.rb +14 -1
- data/lib/sequel/extensions/schema_dumper.rb +83 -55
- data/lib/sequel/extensions/select_remove.rb +8 -4
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
- data/lib/sequel/extensions/server_block.rb +50 -17
- data/lib/sequel/extensions/server_logging.rb +61 -0
- data/lib/sequel/extensions/split_array_nil.rb +8 -4
- data/lib/sequel/extensions/sql_comments.rb +96 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -1
- data/lib/sequel/extensions/string_agg.rb +181 -0
- data/lib/sequel/extensions/string_date_time.rb +2 -0
- data/lib/sequel/extensions/symbol_aref.rb +53 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
- data/lib/sequel/extensions/symbol_as.rb +23 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
- data/lib/sequel/extensions/synchronize_sql.rb +45 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +4 -0
- data/lib/sequel/extensions/to_dot.rb +15 -5
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +36 -126
- data/lib/sequel/model/associations.rb +850 -257
- data/lib/sequel/model/base.rb +652 -764
- data/lib/sequel/model/dataset_module.rb +13 -10
- data/lib/sequel/model/default_inflections.rb +3 -1
- data/lib/sequel/model/errors.rb +3 -3
- data/lib/sequel/model/exceptions.rb +12 -12
- data/lib/sequel/model/inflections.rb +8 -19
- data/lib/sequel/model/plugins.rb +111 -0
- data/lib/sequel/plugins/accessed_columns.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +32 -7
- data/lib/sequel/plugins/after_initialize.rb +3 -1
- data/lib/sequel/plugins/association_dependencies.rb +27 -18
- data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
- data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
- data/lib/sequel/plugins/association_pks.rb +181 -83
- data/lib/sequel/plugins/association_proxies.rb +33 -9
- data/lib/sequel/plugins/auto_validations.rb +58 -23
- data/lib/sequel/plugins/before_after_save.rb +8 -0
- data/lib/sequel/plugins/blacklist_security.rb +23 -12
- data/lib/sequel/plugins/boolean_readers.rb +9 -6
- data/lib/sequel/plugins/boolean_subsets.rb +64 -0
- data/lib/sequel/plugins/caching.rb +27 -16
- data/lib/sequel/plugins/class_table_inheritance.rb +192 -94
- data/lib/sequel/plugins/column_conflicts.rb +18 -3
- data/lib/sequel/plugins/column_select.rb +9 -5
- data/lib/sequel/plugins/columns_updated.rb +42 -0
- data/lib/sequel/plugins/composition.rb +36 -24
- data/lib/sequel/plugins/constraint_validations.rb +37 -16
- data/lib/sequel/plugins/csv_serializer.rb +58 -35
- data/lib/sequel/plugins/dataset_associations.rb +60 -18
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/defaults_setter.rb +74 -13
- data/lib/sequel/plugins/delay_add_association.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +65 -24
- data/lib/sequel/plugins/eager_each.rb +27 -3
- data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/error_splitter.rb +19 -12
- data/lib/sequel/plugins/finder.rb +246 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/force_encoding.rb +9 -12
- data/lib/sequel/plugins/hook_class_methods.rb +39 -54
- data/lib/sequel/plugins/input_transformer.rb +20 -10
- data/lib/sequel/plugins/insert_conflict.rb +72 -0
- data/lib/sequel/plugins/insert_returning_select.rb +4 -2
- data/lib/sequel/plugins/instance_filters.rb +12 -8
- data/lib/sequel/plugins/instance_hooks.rb +36 -17
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/inverted_subsets.rb +24 -13
- data/lib/sequel/plugins/json_serializer.rb +123 -47
- data/lib/sequel/plugins/lazy_attributes.rb +20 -14
- data/lib/sequel/plugins/list.rb +40 -26
- data/lib/sequel/plugins/many_through_many.rb +28 -12
- data/lib/sequel/plugins/modification_detection.rb +17 -5
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -5
- data/lib/sequel/plugins/nested_attributes.rb +55 -28
- data/lib/sequel/plugins/optimistic_locking.rb +5 -3
- data/lib/sequel/plugins/pg_array_associations.rb +52 -18
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +348 -0
- data/lib/sequel/plugins/pg_row.rb +7 -51
- data/lib/sequel/plugins/prepared_statements.rb +53 -72
- data/lib/sequel/plugins/prepared_statements_safe.rb +13 -5
- data/lib/sequel/plugins/rcte_tree.rb +43 -63
- data/lib/sequel/plugins/serialization.rb +37 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +3 -1
- data/lib/sequel/plugins/sharding.rb +17 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +62 -28
- data/lib/sequel/plugins/singular_table_names.rb +2 -0
- data/lib/sequel/plugins/skip_create_refresh.rb +5 -3
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/split_values.rb +13 -6
- data/lib/sequel/plugins/static_cache.rb +79 -53
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +5 -3
- data/lib/sequel/plugins/subclasses.rb +20 -2
- data/lib/sequel/plugins/subset_conditions.rb +48 -0
- data/lib/sequel/plugins/table_select.rb +4 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +120 -6
- data/lib/sequel/plugins/throw_failures.rb +110 -0
- data/lib/sequel/plugins/timestamps.rb +22 -8
- data/lib/sequel/plugins/touch.rb +21 -8
- data/lib/sequel/plugins/tree.rb +57 -30
- data/lib/sequel/plugins/typecast_on_load.rb +14 -4
- data/lib/sequel/plugins/unlimited_update.rb +3 -7
- data/lib/sequel/plugins/update_or_create.rb +6 -4
- data/lib/sequel/plugins/update_primary_key.rb +3 -1
- data/lib/sequel/plugins/update_refresh.rb +28 -15
- data/lib/sequel/plugins/uuid.rb +70 -0
- data/lib/sequel/plugins/validate_associated.rb +20 -0
- data/lib/sequel/plugins/validation_class_methods.rb +40 -19
- data/lib/sequel/plugins/validation_contexts.rb +49 -0
- data/lib/sequel/plugins/validation_helpers.rb +49 -31
- data/lib/sequel/plugins/whitelist_security.rb +122 -0
- data/lib/sequel/plugins/xml_serializer.rb +31 -30
- data/lib/sequel/sql.rb +479 -329
- data/lib/sequel/timezones.rb +62 -32
- data/lib/sequel/version.rb +10 -3
- metadata +177 -477
- data/Rakefile +0 -165
- data/doc/active_record.rdoc +0 -912
- data/doc/release_notes/1.0.txt +0 -38
- data/doc/release_notes/1.1.txt +0 -143
- data/doc/release_notes/1.3.txt +0 -101
- data/doc/release_notes/1.4.0.txt +0 -53
- data/doc/release_notes/1.5.0.txt +0 -155
- data/doc/release_notes/2.0.0.txt +0 -298
- data/doc/release_notes/2.1.0.txt +0 -271
- data/doc/release_notes/2.10.0.txt +0 -328
- data/doc/release_notes/2.11.0.txt +0 -215
- data/doc/release_notes/2.12.0.txt +0 -534
- data/doc/release_notes/2.2.0.txt +0 -253
- data/doc/release_notes/2.3.0.txt +0 -88
- data/doc/release_notes/2.4.0.txt +0 -106
- data/doc/release_notes/2.5.0.txt +0 -137
- data/doc/release_notes/2.6.0.txt +0 -157
- data/doc/release_notes/2.7.0.txt +0 -166
- data/doc/release_notes/2.8.0.txt +0 -171
- data/doc/release_notes/2.9.0.txt +0 -97
- data/doc/release_notes/3.0.0.txt +0 -221
- data/doc/release_notes/3.1.0.txt +0 -406
- data/doc/release_notes/3.10.0.txt +0 -286
- data/doc/release_notes/3.11.0.txt +0 -254
- data/doc/release_notes/3.12.0.txt +0 -304
- data/doc/release_notes/3.13.0.txt +0 -210
- data/doc/release_notes/3.14.0.txt +0 -118
- data/doc/release_notes/3.15.0.txt +0 -78
- data/doc/release_notes/3.16.0.txt +0 -45
- data/doc/release_notes/3.17.0.txt +0 -58
- data/doc/release_notes/3.18.0.txt +0 -120
- data/doc/release_notes/3.19.0.txt +0 -67
- data/doc/release_notes/3.2.0.txt +0 -268
- data/doc/release_notes/3.20.0.txt +0 -41
- data/doc/release_notes/3.21.0.txt +0 -87
- data/doc/release_notes/3.22.0.txt +0 -39
- data/doc/release_notes/3.23.0.txt +0 -172
- data/doc/release_notes/3.24.0.txt +0 -420
- data/doc/release_notes/3.25.0.txt +0 -88
- data/doc/release_notes/3.26.0.txt +0 -88
- data/doc/release_notes/3.27.0.txt +0 -82
- data/doc/release_notes/3.28.0.txt +0 -304
- data/doc/release_notes/3.29.0.txt +0 -459
- data/doc/release_notes/3.3.0.txt +0 -192
- data/doc/release_notes/3.30.0.txt +0 -135
- data/doc/release_notes/3.31.0.txt +0 -146
- data/doc/release_notes/3.32.0.txt +0 -202
- data/doc/release_notes/3.33.0.txt +0 -157
- data/doc/release_notes/3.34.0.txt +0 -671
- data/doc/release_notes/3.35.0.txt +0 -144
- data/doc/release_notes/3.36.0.txt +0 -245
- data/doc/release_notes/3.37.0.txt +0 -338
- data/doc/release_notes/3.38.0.txt +0 -234
- data/doc/release_notes/3.39.0.txt +0 -237
- data/doc/release_notes/3.4.0.txt +0 -325
- data/doc/release_notes/3.40.0.txt +0 -73
- data/doc/release_notes/3.41.0.txt +0 -155
- data/doc/release_notes/3.42.0.txt +0 -74
- data/doc/release_notes/3.43.0.txt +0 -105
- data/doc/release_notes/3.44.0.txt +0 -152
- data/doc/release_notes/3.45.0.txt +0 -179
- data/doc/release_notes/3.46.0.txt +0 -122
- data/doc/release_notes/3.47.0.txt +0 -270
- data/doc/release_notes/3.48.0.txt +0 -477
- data/doc/release_notes/3.5.0.txt +0 -510
- data/doc/release_notes/3.6.0.txt +0 -366
- data/doc/release_notes/3.7.0.txt +0 -179
- data/doc/release_notes/3.8.0.txt +0 -151
- data/doc/release_notes/3.9.0.txt +0 -233
- data/doc/release_notes/4.0.0.txt +0 -262
- data/doc/release_notes/4.1.0.txt +0 -85
- data/doc/release_notes/4.10.0.txt +0 -226
- data/doc/release_notes/4.11.0.txt +0 -147
- data/doc/release_notes/4.12.0.txt +0 -105
- data/doc/release_notes/4.13.0.txt +0 -169
- data/doc/release_notes/4.14.0.txt +0 -68
- data/doc/release_notes/4.15.0.txt +0 -56
- data/doc/release_notes/4.16.0.txt +0 -36
- data/doc/release_notes/4.17.0.txt +0 -38
- data/doc/release_notes/4.18.0.txt +0 -36
- data/doc/release_notes/4.19.0.txt +0 -45
- data/doc/release_notes/4.2.0.txt +0 -129
- data/doc/release_notes/4.20.0.txt +0 -79
- data/doc/release_notes/4.21.0.txt +0 -94
- data/doc/release_notes/4.22.0.txt +0 -72
- data/doc/release_notes/4.23.0.txt +0 -65
- data/doc/release_notes/4.24.0.txt +0 -99
- data/doc/release_notes/4.25.0.txt +0 -181
- data/doc/release_notes/4.26.0.txt +0 -44
- data/doc/release_notes/4.3.0.txt +0 -40
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.5.0.txt +0 -34
- data/doc/release_notes/4.6.0.txt +0 -30
- data/doc/release_notes/4.7.0.txt +0 -103
- data/doc/release_notes/4.8.0.txt +0 -175
- data/doc/release_notes/4.9.0.txt +0 -190
- data/lib/sequel/adapters/cubrid.rb +0 -142
- data/lib/sequel/adapters/do.rb +0 -156
- data/lib/sequel/adapters/do/mysql.rb +0 -64
- data/lib/sequel/adapters/do/postgres.rb +0 -42
- data/lib/sequel/adapters/do/sqlite3.rb +0 -40
- data/lib/sequel/adapters/jdbc/as400.rb +0 -82
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -62
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -34
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -31
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -31
- data/lib/sequel/adapters/odbc/progress.rb +0 -8
- data/lib/sequel/adapters/shared/cubrid.rb +0 -243
- data/lib/sequel/adapters/shared/firebird.rb +0 -245
- data/lib/sequel/adapters/shared/informix.rb +0 -52
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -150
- data/lib/sequel/adapters/shared/progress.rb +0 -38
- data/lib/sequel/adapters/swift.rb +0 -158
- data/lib/sequel/adapters/swift/mysql.rb +0 -47
- data/lib/sequel/adapters/swift/postgres.rb +0 -45
- data/lib/sequel/adapters/swift/sqlite.rb +0 -47
- data/lib/sequel/adapters/utils/pg_types.rb +0 -68
- data/lib/sequel/dataset/mutation.rb +0 -109
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -3
- data/lib/sequel/extensions/filter_having.rb +0 -59
- data/lib/sequel/extensions/hash_aliases.rb +0 -45
- data/lib/sequel/extensions/meta_def.rb +0 -31
- data/lib/sequel/extensions/query_literals.rb +0 -80
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -22
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -118
- data/lib/sequel/extensions/set_overrides.rb +0 -72
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/association_autoreloading.rb +0 -7
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -7
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -78
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -117
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -59
- data/lib/sequel/plugins/schema.rb +0 -80
- data/lib/sequel/plugins/scissors.rb +0 -33
- data/spec/adapters/db2_spec.rb +0 -160
- data/spec/adapters/firebird_spec.rb +0 -411
- data/spec/adapters/informix_spec.rb +0 -100
- data/spec/adapters/mssql_spec.rb +0 -706
- data/spec/adapters/mysql_spec.rb +0 -1287
- data/spec/adapters/oracle_spec.rb +0 -313
- data/spec/adapters/postgres_spec.rb +0 -3725
- data/spec/adapters/spec_helper.rb +0 -43
- data/spec/adapters/sqlanywhere_spec.rb +0 -170
- data/spec/adapters/sqlite_spec.rb +0 -653
- data/spec/bin_spec.rb +0 -254
- data/spec/core/connection_pool_spec.rb +0 -1016
- data/spec/core/database_spec.rb +0 -2531
- data/spec/core/dataset_spec.rb +0 -5098
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1243
- data/spec/core/mock_adapter_spec.rb +0 -462
- data/spec/core/object_graph_spec.rb +0 -303
- data/spec/core/placeholder_literalizer_spec.rb +0 -163
- data/spec/core/schema_generator_spec.rb +0 -179
- data/spec/core/schema_spec.rb +0 -1659
- data/spec/core/spec_helper.rb +0 -34
- data/spec/core/version_spec.rb +0 -7
- data/spec/core_extensions_spec.rb +0 -699
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -123
- data/spec/extensions/after_initialize_spec.rb +0 -24
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -117
- data/spec/extensions/association_pks_spec.rb +0 -365
- data/spec/extensions/association_proxies_spec.rb +0 -86
- data/spec/extensions/auto_validations_spec.rb +0 -192
- data/spec/extensions/blacklist_security_spec.rb +0 -88
- data/spec/extensions/blank_spec.rb +0 -69
- data/spec/extensions/boolean_readers_spec.rb +0 -93
- data/spec/extensions/caching_spec.rb +0 -270
- data/spec/extensions/class_table_inheritance_spec.rb +0 -420
- data/spec/extensions/column_conflicts_spec.rb +0 -60
- data/spec/extensions/column_select_spec.rb +0 -108
- data/spec/extensions/columns_introspection_spec.rb +0 -91
- data/spec/extensions/composition_spec.rb +0 -242
- data/spec/extensions/connection_validator_spec.rb +0 -120
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -274
- data/spec/extensions/constraint_validations_spec.rb +0 -325
- data/spec/extensions/core_refinements_spec.rb +0 -519
- data/spec/extensions/csv_serializer_spec.rb +0 -173
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -311
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -150
- data/spec/extensions/defaults_setter_spec.rb +0 -101
- data/spec/extensions/delay_add_association_spec.rb +0 -52
- data/spec/extensions/dirty_spec.rb +0 -180
- data/spec/extensions/eager_each_spec.rb +0 -42
- data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
- data/spec/extensions/error_splitter_spec.rb +0 -18
- data/spec/extensions/error_sql_spec.rb +0 -20
- data/spec/extensions/eval_inspect_spec.rb +0 -73
- data/spec/extensions/filter_having_spec.rb +0 -40
- data/spec/extensions/force_encoding_spec.rb +0 -114
- data/spec/extensions/from_block_spec.rb +0 -21
- data/spec/extensions/graph_each_spec.rb +0 -109
- data/spec/extensions/hash_aliases_spec.rb +0 -24
- data/spec/extensions/hook_class_methods_spec.rb +0 -429
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -54
- data/spec/extensions/insert_returning_select_spec.rb +0 -46
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -276
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -291
- data/spec/extensions/lazy_attributes_spec.rb +0 -170
- data/spec/extensions/list_spec.rb +0 -267
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2172
- data/spec/extensions/meta_def_spec.rb +0 -21
- data/spec/extensions/migration_spec.rb +0 -712
- data/spec/extensions/modification_detection_spec.rb +0 -80
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
- data/spec/extensions/named_timezones_spec.rb +0 -108
- data/spec/extensions/nested_attributes_spec.rb +0 -697
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -128
- data/spec/extensions/pagination_spec.rb +0 -118
- data/spec/extensions/pg_array_associations_spec.rb +0 -736
- data/spec/extensions/pg_array_ops_spec.rb +0 -143
- data/spec/extensions/pg_array_spec.rb +0 -395
- data/spec/extensions/pg_enum_spec.rb +0 -92
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
- data/spec/extensions/pg_hstore_spec.rb +0 -206
- data/spec/extensions/pg_inet_ops_spec.rb +0 -101
- data/spec/extensions/pg_inet_spec.rb +0 -52
- data/spec/extensions/pg_interval_spec.rb +0 -76
- data/spec/extensions/pg_json_ops_spec.rb +0 -229
- data/spec/extensions/pg_json_spec.rb +0 -218
- data/spec/extensions/pg_loose_count_spec.rb +0 -17
- data/spec/extensions/pg_range_ops_spec.rb +0 -58
- data/spec/extensions/pg_range_spec.rb +0 -404
- data/spec/extensions/pg_row_ops_spec.rb +0 -60
- data/spec/extensions/pg_row_plugin_spec.rb +0 -62
- data/spec/extensions/pg_row_spec.rb +0 -360
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
- data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
- data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
- data/spec/extensions/prepared_statements_spec.rb +0 -103
- data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
- data/spec/extensions/pretty_table_spec.rb +0 -92
- data/spec/extensions/query_literals_spec.rb +0 -183
- data/spec/extensions/query_spec.rb +0 -102
- data/spec/extensions/rcte_tree_spec.rb +0 -392
- data/spec/extensions/round_timestamps_spec.rb +0 -43
- data/spec/extensions/schema_caching_spec.rb +0 -41
- data/spec/extensions/schema_dumper_spec.rb +0 -789
- data/spec/extensions/schema_spec.rb +0 -117
- data/spec/extensions/scissors_spec.rb +0 -26
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -362
- data/spec/extensions/server_block_spec.rb +0 -90
- data/spec/extensions/set_overrides_spec.rb +0 -61
- data/spec/extensions/sharding_spec.rb +0 -198
- data/spec/extensions/shared_caching_spec.rb +0 -175
- data/spec/extensions/single_table_inheritance_spec.rb +0 -297
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -17
- data/spec/extensions/spec_helper.rb +0 -71
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -22
- data/spec/extensions/sql_expr_spec.rb +0 -60
- data/spec/extensions/static_cache_spec.rb +0 -361
- data/spec/extensions/string_date_time_spec.rb +0 -95
- data/spec/extensions/string_stripper_spec.rb +0 -68
- data/spec/extensions/subclasses_spec.rb +0 -66
- data/spec/extensions/table_select_spec.rb +0 -71
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -82
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/timestamps_spec.rb +0 -175
- data/spec/extensions/to_dot_spec.rb +0 -154
- data/spec/extensions/touch_spec.rb +0 -203
- data/spec/extensions/tree_spec.rb +0 -274
- data/spec/extensions/typecast_on_load_spec.rb +0 -80
- data/spec/extensions/unlimited_update_spec.rb +0 -20
- data/spec/extensions/update_or_create_spec.rb +0 -87
- data/spec/extensions/update_primary_key_spec.rb +0 -100
- data/spec/extensions/update_refresh_spec.rb +0 -53
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1027
- data/spec/extensions/validation_helpers_spec.rb +0 -541
- data/spec/extensions/xml_serializer_spec.rb +0 -207
- data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
- data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
- data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
- data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
- data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
- data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
- data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
- data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
- data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
- data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/reversible_migrations/001_reversible.rb +0 -5
- data/spec/files/reversible_migrations/002_reversible.rb +0 -5
- data/spec/files/reversible_migrations/003_reversible.rb +0 -5
- data/spec/files/reversible_migrations/004_reversible.rb +0 -5
- data/spec/files/reversible_migrations/005_reversible.rb +0 -10
- data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
- data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
- data/spec/guards_helper.rb +0 -55
- data/spec/integration/associations_test.rb +0 -2454
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1808
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -240
- data/spec/integration/model_test.rb +0 -226
- data/spec/integration/plugin_test.rb +0 -2240
- data/spec/integration/prepared_statement_test.rb +0 -467
- data/spec/integration/schema_test.rb +0 -817
- data/spec/integration/spec_helper.rb +0 -48
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -374
- data/spec/integration/type_test.rb +0 -133
- data/spec/model/association_reflection_spec.rb +0 -525
- data/spec/model/associations_spec.rb +0 -4426
- data/spec/model/base_spec.rb +0 -759
- data/spec/model/class_dataset_methods_spec.rb +0 -146
- data/spec/model/dataset_methods_spec.rb +0 -149
- data/spec/model/eager_loading_spec.rb +0 -2137
- data/spec/model/hooks_spec.rb +0 -604
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -982
- data/spec/model/plugins_spec.rb +0 -299
- data/spec/model/record_spec.rb +0 -2147
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -193
- data/spec/sequel_coverage.rb +0 -15
- data/spec/spec_config.rb +0 -10
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.
|
|
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,13 +109,11 @@ 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.
|
|
117
115
|
This is useful if there is a unique constraint on the foreign key in the join table
|
|
118
|
-
that
|
|
116
|
+
that references the current table. It's also useful if you want to impose an order
|
|
119
117
|
on the association and just want the first record returned. The one_through_one
|
|
120
118
|
association is so named because it sets up a one-to-one association through a
|
|
121
119
|
single join 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
|
|
|
@@ -302,12 +300,14 @@ Examples:
|
|
|
302
300
|
@artist.remove_album(@album)
|
|
303
301
|
@artist.remove_all_albums
|
|
304
302
|
|
|
305
|
-
one_through_one associations do not have any modification methods added.
|
|
306
|
-
|
|
307
303
|
Note that the remove_all_* method does not call remove hooks defined on
|
|
308
304
|
the association, it just issues a single query to the database. If you
|
|
309
305
|
want to remove all associated objects and call remove hooks, iterate
|
|
310
|
-
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
|
|
311
311
|
|
|
312
312
|
== Caching
|
|
313
313
|
|
|
@@ -320,11 +320,11 @@ Associations are cached after being retrieved:
|
|
|
320
320
|
@album.artists # Cached - No Database Query
|
|
321
321
|
|
|
322
322
|
You can choose to ignore the cached versions and do a database query to
|
|
323
|
-
retrieve results by passing a true
|
|
323
|
+
retrieve results by passing a :reload=>true option to the association method:
|
|
324
324
|
|
|
325
325
|
@album.artists # Not cached - Database Query
|
|
326
326
|
@album.artists # Cached - No Database Query
|
|
327
|
-
@album.artists(true) # Ignore cache - Database Query
|
|
327
|
+
@album.artists(:reload=>true) # Ignore cache - Database Query
|
|
328
328
|
|
|
329
329
|
If you reload/refresh the object, it will automatically clear the
|
|
330
330
|
associations cache for the object:
|
|
@@ -400,70 +400,70 @@ all albums for a given artist, you would usually do:
|
|
|
400
400
|
|
|
401
401
|
You can also do the following:
|
|
402
402
|
|
|
403
|
-
Album.where(:artist
|
|
403
|
+
Album.where(artist: @artist).all
|
|
404
404
|
# or leave off the .all for a dataset
|
|
405
405
|
|
|
406
406
|
For filtering by a single association, this isn't very useful. However, unlike
|
|
407
407
|
using the association method, using a filter allows you to filter by multiple
|
|
408
408
|
associations:
|
|
409
409
|
|
|
410
|
-
Album.where(:artist
|
|
410
|
+
Album.where(artist: @artist, publisher: @publisher)
|
|
411
411
|
|
|
412
412
|
This will return all albums by that artist and published by that publisher.
|
|
413
413
|
This isn't possible using just the association method approach, though you
|
|
414
414
|
can combine the approaches:
|
|
415
415
|
|
|
416
|
-
@artist.albums_dataset.where(:publisher
|
|
416
|
+
@artist.albums_dataset.where(publisher: @publisher)
|
|
417
417
|
|
|
418
418
|
This doesn't just work for +many_to_one+ associations, it also works for
|
|
419
419
|
the other associations:
|
|
420
420
|
|
|
421
421
|
Album.one_to_one :album_info
|
|
422
422
|
# The album related to that AlbumInfo instance
|
|
423
|
-
Album.where(:
|
|
423
|
+
Album.where(album_info: AlbumInfo[2])
|
|
424
424
|
|
|
425
425
|
Album.one_to_many :tracks
|
|
426
426
|
# The album related to that Track instance
|
|
427
|
-
Album.where(:
|
|
427
|
+
Album.where(tracks: Track[3])
|
|
428
428
|
|
|
429
429
|
Album.many_to_many :tags
|
|
430
430
|
# All albums related to that Tag instance
|
|
431
|
-
Album.where(:
|
|
431
|
+
Album.where(tags: Tag[4])
|
|
432
432
|
|
|
433
433
|
Album.one_through_one :tag
|
|
434
434
|
# All albums related to that Tag instance
|
|
435
|
-
Album.where(:
|
|
435
|
+
Album.where(tag: Tag[4])
|
|
436
436
|
|
|
437
437
|
Note that for +one_to_many+ and +many_to_many+ associations, you still
|
|
438
438
|
use the plural form even though only a single model object is given.
|
|
439
439
|
|
|
440
440
|
You can also exclude by associations:
|
|
441
441
|
|
|
442
|
-
Album.exclude(:artist
|
|
442
|
+
Album.exclude(artist: @artist).all
|
|
443
443
|
|
|
444
444
|
This will return all albums not by that artist.
|
|
445
445
|
|
|
446
446
|
You can also provide an array with multiple model objects:
|
|
447
447
|
|
|
448
|
-
Album.where(:
|
|
448
|
+
Album.where(artist: [@artist1, @artist2]).all
|
|
449
449
|
|
|
450
450
|
Similar to using an array of integers or strings, this will return
|
|
451
451
|
all albums whose artist is one of those two artists. You can also
|
|
452
452
|
use +exclude+ if you want all albums not by either of those artists:
|
|
453
453
|
|
|
454
|
-
Album.exclude(:
|
|
454
|
+
Album.exclude(artist: [@artist1, @artist2]).all
|
|
455
455
|
|
|
456
456
|
If you are using a +one_to_many+ or +many_to_many+ association, you
|
|
457
457
|
may want to return records where the records matches all of multiple
|
|
458
458
|
records, instead of matching any of them. For example:
|
|
459
459
|
|
|
460
|
-
Album.where(:
|
|
460
|
+
Album.where(tags: [@tag1, @tag2])
|
|
461
461
|
|
|
462
462
|
This matches albums that are associated with either @tag1 or @tag2 or
|
|
463
463
|
both. If you only want ones that you are associated with both, you can
|
|
464
464
|
use separate filter calls:
|
|
465
465
|
|
|
466
|
-
Album.where(:
|
|
466
|
+
Album.where(tags: @tag1).where(tags: @tag2)
|
|
467
467
|
|
|
468
468
|
Or the array form of condition specifiers:
|
|
469
469
|
|
|
@@ -473,22 +473,22 @@ These will return albums associated with both @tag1 and @tag2.
|
|
|
473
473
|
|
|
474
474
|
You can also provide a dataset value when filtering by associations:
|
|
475
475
|
|
|
476
|
-
Album.where(:
|
|
476
|
+
Album.where(artist: Artist.where(Sequel.like(:name, 'A%'))).all
|
|
477
477
|
|
|
478
478
|
This will return all albums whose artist starts with 'A'. Like
|
|
479
479
|
the other forms, this can be inverted:
|
|
480
480
|
|
|
481
|
-
Album.exclude(:
|
|
481
|
+
Album.exclude(artist: Artist.where(Sequel.like(:name, 'A%'))).all
|
|
482
482
|
|
|
483
483
|
This will return all albums whose artist does not start with 'A'.
|
|
484
484
|
|
|
485
485
|
Filtering by associations even works for associations that have
|
|
486
486
|
conditions added via the :conditions option or a block:
|
|
487
487
|
|
|
488
|
-
Album.one_to_many :popular_tags, :
|
|
488
|
+
Album.one_to_many :popular_tags, clone: :tags do |ds|
|
|
489
489
|
ds.where{times_used > 1000}
|
|
490
490
|
end
|
|
491
|
-
Album.where(:
|
|
491
|
+
Album.where(popular_tags: [@tag1, @tag2])
|
|
492
492
|
|
|
493
493
|
This will return all albums that whose popular tags would include
|
|
494
494
|
at least one of those tags.
|
|
@@ -532,14 +532,14 @@ Which could be created using the following Sequel code:
|
|
|
532
532
|
DB.create_table(:artists) do
|
|
533
533
|
# Primary key must be set explicitly
|
|
534
534
|
primary_key :id
|
|
535
|
-
String :name
|
|
535
|
+
String :name, :null=>false, :unique=>true
|
|
536
536
|
end
|
|
537
537
|
DB.create_table(:albums) do
|
|
538
538
|
primary_key :id
|
|
539
539
|
# Table that foreign key references needs to be set explicitly
|
|
540
540
|
# for a database foreign key reference to be created.
|
|
541
|
-
foreign_key :artist_id, :artists
|
|
542
|
-
String :name
|
|
541
|
+
foreign_key :artist_id, :artists, :null=>false
|
|
542
|
+
String :name, :null=>false, :unique=>true
|
|
543
543
|
end
|
|
544
544
|
|
|
545
545
|
If you already had a schema such as:
|
|
@@ -552,7 +552,7 @@ If you already had a schema such as:
|
|
|
552
552
|
Then you just need to add the column:
|
|
553
553
|
|
|
554
554
|
DB.alter_table(:albums) do
|
|
555
|
-
add_foreign_key :artist_id, :artists
|
|
555
|
+
add_foreign_key :artist_id, :artists, :null=>false
|
|
556
556
|
end
|
|
557
557
|
|
|
558
558
|
=== many_to_many
|
|
@@ -591,8 +591,10 @@ You could use the following Sequel code:
|
|
|
591
591
|
DB.create_join_table(:album_id=>:albums, :artist_id=>:artists)
|
|
592
592
|
# or
|
|
593
593
|
DB.create_table(:albums_artists) do
|
|
594
|
-
foreign_key :album_id, :albums
|
|
595
|
-
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]
|
|
596
598
|
end
|
|
597
599
|
|
|
598
600
|
== Association Scope
|
|
@@ -629,12 +631,12 @@ To fix this, you need to specify the full model class name using the
|
|
|
629
631
|
|
|
630
632
|
module App1
|
|
631
633
|
class Artist < Sequel::Model
|
|
632
|
-
one_to_many :albums, :
|
|
634
|
+
one_to_many :albums, class: "App2::Album"
|
|
633
635
|
end
|
|
634
636
|
end
|
|
635
637
|
module App2
|
|
636
638
|
class Album < Sequel::Model
|
|
637
|
-
many_to_one :artist, :
|
|
639
|
+
many_to_one :artist, class: "App1::Artist"
|
|
638
640
|
end
|
|
639
641
|
end
|
|
640
642
|
|
|
@@ -647,7 +649,7 @@ used is not correct, you need to specify the full class name with the
|
|
|
647
649
|
one_to_many :albums
|
|
648
650
|
end
|
|
649
651
|
class Album < Sequel::Model
|
|
650
|
-
many_to_one :artist, :
|
|
652
|
+
many_to_one :artist, class: "App1::AlbumArtist"
|
|
651
653
|
end
|
|
652
654
|
end
|
|
653
655
|
|
|
@@ -656,7 +658,7 @@ used is not correct, you need to specify the full class name with the
|
|
|
656
658
|
In all of these methods, _association_ is replaced by the symbol you
|
|
657
659
|
pass to the association.
|
|
658
660
|
|
|
659
|
-
=== _association_(
|
|
661
|
+
=== _association_(opts={}) (e.g. albums)
|
|
660
662
|
|
|
661
663
|
For +many_to_one+ and +one_to_one+ associations, the _association_ method
|
|
662
664
|
returns either the single object associated, or nil if no object is
|
|
@@ -700,11 +702,11 @@ association name is used in this method.
|
|
|
700
702
|
In addition to passing an actual associated object, you can pass a hash,
|
|
701
703
|
and a new associated object will be created from them:
|
|
702
704
|
|
|
703
|
-
@artist.add_album(:
|
|
705
|
+
@artist.add_album(name: 'RF') # creates Album object
|
|
704
706
|
|
|
705
707
|
The add_<i>association</i> method returns the new associated object:
|
|
706
708
|
|
|
707
|
-
@album = @artist.add_album(:
|
|
709
|
+
@album = @artist.add_album(name: 'RF')
|
|
708
710
|
|
|
709
711
|
Note that the add_* methods for +one_to_many+ persist the changes by
|
|
710
712
|
saving the passed in (or newly created) object. However, to avoid
|
|
@@ -779,7 +781,7 @@ Sequel is designed to be very flexible. If the default behavior of the
|
|
|
779
781
|
association modification methods isn't what you desire, you can override
|
|
780
782
|
the methods in your classes. However, you should be aware that for each
|
|
781
783
|
of the association modification methods described, there is a private
|
|
782
|
-
method that is
|
|
784
|
+
method that is preceded by an underscore that does the actual
|
|
783
785
|
modification. The public method without the underscore handles caching
|
|
784
786
|
and callbacks, and shouldn't be overridden by the user.
|
|
785
787
|
|
|
@@ -789,7 +791,7 @@ only difference between the two is that if you use an association option
|
|
|
789
791
|
to change the method Sequel defines, you cannot call super to get the
|
|
790
792
|
default behavior.
|
|
791
793
|
|
|
792
|
-
=== _<i>association</i>=
|
|
794
|
+
=== :setter (_<i>association</i>= method)
|
|
793
795
|
|
|
794
796
|
Let's say you want to set a specific field whenever associating an object
|
|
795
797
|
using the association setter method. For example, let's say you have
|
|
@@ -798,11 +800,7 @@ album is associated with an artist, it should be filed under the artist's
|
|
|
798
800
|
name and the album's name, otherwise it should just use the album's name.
|
|
799
801
|
|
|
800
802
|
class Album < Sequel::Model
|
|
801
|
-
many_to_one :artist
|
|
802
|
-
|
|
803
|
-
private
|
|
804
|
-
|
|
805
|
-
def _artist=(artist)
|
|
803
|
+
many_to_one :artist, setter: (lambda do |artist|
|
|
806
804
|
if artist
|
|
807
805
|
self.artist_id = artist.id
|
|
808
806
|
self.file_under = "#{artist.name}-#{name}"
|
|
@@ -810,64 +808,64 @@ name and the album's name, otherwise it should just use the album's name.
|
|
|
810
808
|
self.artist_id = nil
|
|
811
809
|
self.file_under = name
|
|
812
810
|
end
|
|
813
|
-
end
|
|
811
|
+
end)
|
|
814
812
|
end
|
|
815
813
|
|
|
816
814
|
The above example is contrived, as you would generally use a before_save model
|
|
817
815
|
hook to handle such a modification. However, if you only modify the album's
|
|
818
816
|
artist using the artist= method, this approach may perform better.
|
|
819
817
|
|
|
820
|
-
=== \_add_<i>association</i>
|
|
818
|
+
=== :adder (\_add_<i>association</i> method)
|
|
821
819
|
|
|
822
820
|
Continuing with the same example, here's how you would handle the same case if
|
|
823
821
|
you also wanted to handle the Artist#add_album method:
|
|
824
822
|
|
|
825
823
|
class Artist < Sequel::Model
|
|
826
|
-
one_to_many :albums
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
def _add_album(album)
|
|
831
|
-
album.update(:artist_id => id, :file_under=>"#{name}-#{album.name}")
|
|
832
|
-
end
|
|
824
|
+
one_to_many :albums, adder: (lambda do |album|
|
|
825
|
+
album.update(artist_id: id, file_under: "#{name}-#{album.name}")
|
|
826
|
+
end)
|
|
833
827
|
end
|
|
834
828
|
|
|
835
|
-
=== \_remove_<i>association</i>
|
|
829
|
+
=== :remover (\_remove_<i>association</i> method)
|
|
836
830
|
|
|
837
831
|
Continuing with the same example, here's how you would handle the same case if
|
|
838
832
|
you also wanted to handle the Artist#remove_album method:
|
|
839
833
|
|
|
840
834
|
class Artist < Sequel::Model
|
|
841
|
-
one_to_many :albums
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
def _remove_album(album)
|
|
846
|
-
album.update(:artist_id => nil, :file_under=>album.name)
|
|
847
|
-
end
|
|
835
|
+
one_to_many :albums, remover: (lambda do |album|
|
|
836
|
+
album.update(artist_id: nil, file_under: album.name)
|
|
837
|
+
end)
|
|
848
838
|
end
|
|
849
839
|
|
|
850
|
-
=== \_remove_all_<i>association</i>
|
|
840
|
+
=== :clearer (\_remove_all_<i>association</i> method)
|
|
851
841
|
|
|
852
842
|
Continuing with the same example, here's how you would handle the same case if
|
|
853
843
|
you also wanted to handle the Artist#remove_all_albums method:
|
|
854
844
|
|
|
855
845
|
class Artist < Sequel::Model
|
|
856
|
-
one_to_many :albums
|
|
857
|
-
|
|
858
|
-
private
|
|
859
|
-
|
|
860
|
-
def _remove_all_albums
|
|
861
|
-
# 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
|
|
862
848
|
# ends up being "SET file_under = name" in SQL.
|
|
863
|
-
albums_dataset.update(:
|
|
864
|
-
end
|
|
849
|
+
albums_dataset.update(artist_id: nil, file_under: :name)
|
|
850
|
+
end)
|
|
865
851
|
end
|
|
866
852
|
|
|
867
853
|
== Association Options
|
|
868
854
|
|
|
869
855
|
Sequel's associations mostly share the same options. For ease of understanding,
|
|
870
|
-
they are grouped here by section
|
|
856
|
+
they are grouped here by section.
|
|
857
|
+
|
|
858
|
+
The defaults for any of these options can be set at the class level using
|
|
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}
|
|
871
869
|
|
|
872
870
|
=== Association Dataset Modification Options
|
|
873
871
|
|
|
@@ -879,7 +877,7 @@ use for the association. For example, if you wanted an association
|
|
|
879
877
|
that returns all albums of an artist that went gold (sold at least
|
|
880
878
|
500,000 copies):
|
|
881
879
|
|
|
882
|
-
Artist.one_to_many :gold_albums, :
|
|
880
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
|
883
881
|
ds.where{copies_sold > 500000}
|
|
884
882
|
end
|
|
885
883
|
|
|
@@ -887,7 +885,7 @@ The result of the block is cached as an optimization. One of the side
|
|
|
887
885
|
effects of that is that if your block depends on external state, it won't
|
|
888
886
|
work correctly unless you setup a delayed evaluation. For example:
|
|
889
887
|
|
|
890
|
-
Artist.one_to_many :gold_albums, :
|
|
888
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
|
891
889
|
ds.where{copies_sold > $gold_limit}
|
|
892
890
|
end
|
|
893
891
|
|
|
@@ -895,7 +893,7 @@ In this case if you change <tt>$gold_limit</tt> later, the changes won't
|
|
|
895
893
|
effect the association. If you want to pick up changes to <tt>$gold_limit</tt>,
|
|
896
894
|
you need to setup a delayed evaluation:
|
|
897
895
|
|
|
898
|
-
Artist.one_to_many :gold_albums, :
|
|
896
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
|
899
897
|
ds.where{copies_sold > Sequel.delay{$gold_limit}}
|
|
900
898
|
end
|
|
901
899
|
|
|
@@ -903,11 +901,13 @@ you need to setup a delayed evaluation:
|
|
|
903
901
|
|
|
904
902
|
This is the class of the associated objects that will be used. It's
|
|
905
903
|
one of the most commonly used options. If it is not given, it guesses
|
|
906
|
-
based on the name of the association
|
|
907
|
-
|
|
904
|
+
based on the name of the association, including considering the namespace
|
|
905
|
+
of the current model. If a *_to_many association is used, this uses the
|
|
906
|
+
singular form of the association name. For example:
|
|
908
907
|
|
|
909
908
|
Album.many_to_one :artist # guesses Artist
|
|
910
909
|
Artist.one_to_many :albums # guesses Album
|
|
910
|
+
Foo::Artist.one_to_many :albums # guesses Foo::Album
|
|
911
911
|
|
|
912
912
|
However, for more complex associations, especially ones that add
|
|
913
913
|
additional filters beyond the foreign/primary key relationships, the
|
|
@@ -921,36 +921,47 @@ default class guessed will be wrong:
|
|
|
921
921
|
You can specify the :class option using the class itself, a Symbol,
|
|
922
922
|
or a String:
|
|
923
923
|
|
|
924
|
-
Album.many_to_one :artist, :
|
|
925
|
-
Album.many_to_one :artist, :
|
|
926
|
-
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
|
|
927
|
+
|
|
928
|
+
If you are namespacing your models, and you need to specify the :class
|
|
929
|
+
option, the path you give to the :class option should be the full path
|
|
930
|
+
to the associated class including any namespaces:
|
|
931
|
+
|
|
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
|
|
927
935
|
|
|
928
936
|
==== :key
|
|
929
937
|
|
|
930
938
|
For +many_to_one+ associations, this is the foreign_key in the current model's
|
|
931
939
|
table that references the associated model's primary key as a symbol.
|
|
932
|
-
Defaults to :<i>association</i>_id.
|
|
933
|
-
composite key association.
|
|
940
|
+
Defaults to :<i>association</i>_id.
|
|
934
941
|
|
|
935
|
-
Album.many_to_one :artist
|
|
942
|
+
Album.many_to_one :artist, key: :artistid
|
|
936
943
|
|
|
937
944
|
For +one_to_one+ and +one_to_many+ associations, is the foreign key in
|
|
938
945
|
associated model's table that references current model's primary key, as a
|
|
939
946
|
symbol. Defaults to :"#{self.name.underscore}_id".
|
|
940
947
|
|
|
941
|
-
Artist.one_to_many :albums
|
|
948
|
+
Artist.one_to_many :albums, key: :artistid
|
|
942
949
|
|
|
943
950
|
In both cases an array of symbols can be used for a composite key association:
|
|
944
951
|
|
|
945
|
-
Apartment.many_to_one :building
|
|
952
|
+
Apartment.many_to_one :building, key: [:city, :address]
|
|
946
953
|
|
|
947
954
|
==== :conditions
|
|
948
955
|
|
|
949
956
|
The conditions to use to filter the association, can be any argument passed to +where+.
|
|
950
957
|
If you use a hash or an array of two element arrays, this will also be used as a
|
|
951
|
-
filter when using eager_graph to load the association.
|
|
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.
|
|
952
963
|
|
|
953
|
-
Artist.one_to_many :good_albums, :
|
|
964
|
+
Artist.one_to_many :good_albums, class: :Album, conditions: {:good=>true}
|
|
954
965
|
@artist.good_albums
|
|
955
966
|
# SELECT * FROM albums WHERE ((artist_id = 1) AND (good IS TRUE))
|
|
956
967
|
|
|
@@ -959,10 +970,8 @@ filter when using eager_graph to load the association.
|
|
|
959
970
|
The column(s) by which to order the association dataset. Can be a
|
|
960
971
|
singular column or an array.
|
|
961
972
|
|
|
962
|
-
Artist.one_to_many :albums_by_name, :
|
|
963
|
-
|
|
964
|
-
Artist.one_to_many :albums_by_num_tracks, :class=>:Album,
|
|
965
|
-
: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]
|
|
966
975
|
|
|
967
976
|
==== :select
|
|
968
977
|
|
|
@@ -978,20 +987,19 @@ can clash with columns from the associated table, so you should alias any
|
|
|
978
987
|
columns that have the same name in both the join table and the associated
|
|
979
988
|
table. Example:
|
|
980
989
|
|
|
981
|
-
Artist.one_to_many :albums, :
|
|
982
|
-
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]]
|
|
983
992
|
|
|
984
993
|
==== :limit
|
|
985
994
|
|
|
986
995
|
Limit the number of records to the provided value:
|
|
987
996
|
|
|
988
|
-
Artist.one_to_many :best_selling_albums, :
|
|
989
|
-
:order=>:copies_sold, :limit=>5 # LIMIT 5
|
|
997
|
+
Artist.one_to_many :best_selling_albums, class: :Album, order: :copies_sold, limit: 5
|
|
990
998
|
|
|
991
999
|
Use an array with two arguments for the value to specify a limit and an offset.
|
|
992
1000
|
|
|
993
|
-
Artist.one_to_many :next_best_selling_albums, :
|
|
994
|
-
|
|
1001
|
+
Artist.one_to_many :next_best_selling_albums, class: :Album, order: :copies_sold, limit: [10, 5]
|
|
1002
|
+
# LIMIT 10 OFFSET 5
|
|
995
1003
|
|
|
996
1004
|
This probably doesn't make a lot of sense for *_to_one associations, though you
|
|
997
1005
|
could use it to specify an offset.
|
|
@@ -1003,16 +1011,16 @@ associated model, as a symbol. Defaults to the name of current model and name
|
|
|
1003
1011
|
of associated model, pluralized, underscored, sorted, and joined with '_'.
|
|
1004
1012
|
Here's an example of the defaults:
|
|
1005
1013
|
|
|
1006
|
-
Artist.many_to_many :albums
|
|
1007
|
-
Album.many_to_many :artists
|
|
1008
|
-
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
|
|
1009
1017
|
|
|
1010
1018
|
==== :left_key [+many_to_many+, +one_through_one+]
|
|
1011
1019
|
|
|
1012
1020
|
Foreign key in join table that points to current model's primary key, as a
|
|
1013
1021
|
symbol. Defaults to :"#{model_name.underscore}_id".
|
|
1014
1022
|
|
|
1015
|
-
Album.many_to_many :tags
|
|
1023
|
+
Album.many_to_many :tags, left_key: :album_id
|
|
1016
1024
|
|
|
1017
1025
|
Can use an array of symbols for a composite key association.
|
|
1018
1026
|
|
|
@@ -1022,7 +1030,7 @@ Foreign key in join table that points to associated model's primary key, as a
|
|
|
1022
1030
|
symbol. Defaults to :"#{association_name.singularize}_id" for +many_to_many+
|
|
1023
1031
|
and :"#{association_name}_id" for +one_through_one+.
|
|
1024
1032
|
|
|
1025
|
-
Album.many_to_many :tags
|
|
1033
|
+
Album.many_to_many :tags, right_key: :tag_id
|
|
1026
1034
|
|
|
1027
1035
|
Can use an array of symbols for a composite key association.
|
|
1028
1036
|
|
|
@@ -1048,10 +1056,10 @@ into the cloned options.
|
|
|
1048
1056
|
This is commonly used if you have a bunch of similar associations that
|
|
1049
1057
|
you want to DRY up:
|
|
1050
1058
|
|
|
1051
|
-
one_to_many :english_verses, :
|
|
1052
|
-
:
|
|
1053
|
-
one_to_many :romaji_verses, :
|
|
1054
|
-
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}
|
|
1055
1063
|
|
|
1056
1064
|
Note that for the final two asociations, you didn't have to specify the :class,
|
|
1057
1065
|
:key, or :order options, as they were copied by the :clone option. By specifying
|
|
@@ -1060,8 +1068,8 @@ option of the first association, it doesn't attempt to merge them.
|
|
|
1060
1068
|
|
|
1061
1069
|
In addition to the options hash, the :clone option will copy a block argument
|
|
1062
1070
|
from the existing situation. If you want a cloned association to not have the
|
|
1063
|
-
same block as the association you are cloning from, specify the :
|
|
1064
|
-
in
|
|
1071
|
+
same block as the association you are cloning from, specify the block: nil option
|
|
1072
|
+
in addition to the :clone option.
|
|
1065
1073
|
|
|
1066
1074
|
==== :dataset
|
|
1067
1075
|
|
|
@@ -1079,16 +1087,14 @@ already applied, and the proc should return a modified copy of this dataset.
|
|
|
1079
1087
|
Here's an example of an association of songs to artists through lyrics, where
|
|
1080
1088
|
the artist can perform any one of four tasks for the lyric:
|
|
1081
1089
|
|
|
1082
|
-
Album.one_to_many :songs, :
|
|
1090
|
+
Album.one_to_many :songs, dataset: (lambda do |r|
|
|
1083
1091
|
r.associated_dataset.select_all(:songs).
|
|
1084
|
-
join(
|
|
1085
|
-
id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
|
|
1092
|
+
join(:lyrics, id: :lyricid, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
|
|
1086
1093
|
end)
|
|
1087
1094
|
Artist.first.songs_dataset
|
|
1088
1095
|
# SELECT songs.* FROM songs
|
|
1089
|
-
# INNER JOIN lyrics ON
|
|
1090
|
-
#
|
|
1091
|
-
# 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))
|
|
1092
1098
|
|
|
1093
1099
|
==== :extend
|
|
1094
1100
|
|
|
@@ -1105,8 +1111,8 @@ it defaults to the primary key of the table. Can use an
|
|
|
1105
1111
|
array of symbols for a composite key association.
|
|
1106
1112
|
|
|
1107
1113
|
Artist.set_primary_key :arid
|
|
1108
|
-
Artist.one_to_many :albums
|
|
1109
|
-
Album.one_to_many :artist
|
|
1114
|
+
Artist.one_to_many :albums, primary_key: :arid
|
|
1115
|
+
Album.one_to_many :artist, primary_key: :arid
|
|
1110
1116
|
|
|
1111
1117
|
==== :left_primary_key [+many_to_many+, +one_through_one+]
|
|
1112
1118
|
|
|
@@ -1114,7 +1120,7 @@ Column in current table that :left_key option points to, as a symbol.
|
|
|
1114
1120
|
Defaults to primary key of current table.
|
|
1115
1121
|
|
|
1116
1122
|
Album.set_primary_key :alid
|
|
1117
|
-
Album.many_to_many :tags
|
|
1123
|
+
Album.many_to_many :tags, left_primary_key: :alid
|
|
1118
1124
|
|
|
1119
1125
|
Can use an array of symbols for a composite key association.
|
|
1120
1126
|
|
|
@@ -1124,7 +1130,7 @@ Column in associated table that :right_key points to, as a symbol.
|
|
|
1124
1130
|
Defaults to primary key of the associated table.
|
|
1125
1131
|
|
|
1126
1132
|
Tag.set_primary_key :tid
|
|
1127
|
-
Album.many_to_many :tags
|
|
1133
|
+
Album.many_to_many :tags, right_primary_key: :tid
|
|
1128
1134
|
|
|
1129
1135
|
Can use an array of symbols for a composite key association.
|
|
1130
1136
|
|
|
@@ -1136,9 +1142,9 @@ join of the join table and the associated table, whereas this option just
|
|
|
1136
1142
|
applies to the join table. It can be used to make sure that filters are used
|
|
1137
1143
|
when deleting.
|
|
1138
1144
|
|
|
1139
|
-
Artist.many_to_many :lead_guitar_albums, :join_table_block=>
|
|
1140
|
-
ds.where(:
|
|
1141
|
-
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)
|
|
1142
1148
|
|
|
1143
1149
|
=== Callback Options
|
|
1144
1150
|
|
|
@@ -1148,14 +1154,10 @@ that are called with the associated object. Procs are called with the receiver
|
|
|
1148
1154
|
as the first argument and the associated object as the second argument. If
|
|
1149
1155
|
an array is given, all of them are called in order.
|
|
1150
1156
|
|
|
1151
|
-
Before callbacks are often used to check preconditions, they can
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
is aborted.
|
|
1155
|
-
object or the associated object.
|
|
1156
|
-
|
|
1157
|
-
After callbacks are often used for notification (logging, email) after a
|
|
1158
|
-
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.
|
|
1159
1161
|
|
|
1160
1162
|
==== :before_add [+one_to_many+, +many_to_many+]
|
|
1161
1163
|
|
|
@@ -1163,7 +1165,7 @@ Called before adding an object to the association:
|
|
|
1163
1165
|
|
|
1164
1166
|
class Artist
|
|
1165
1167
|
# Don't allow adding an album to an artist if it has no tracks
|
|
1166
|
-
one_to_many :albums, :
|
|
1168
|
+
one_to_many :albums, before_add: lambda{|ar, al| ar.cancel_action if al.num_tracks == 0}
|
|
1167
1169
|
end
|
|
1168
1170
|
|
|
1169
1171
|
==== :after_add [+one_to_many+, +many_to_many+]
|
|
@@ -1172,12 +1174,12 @@ Called after adding an object to the association:
|
|
|
1172
1174
|
|
|
1173
1175
|
class Artist
|
|
1174
1176
|
# Log all associations of albums to an audit logging table
|
|
1175
|
-
one_to_many :albums, :
|
|
1177
|
+
one_to_many :albums, after_add: :log_add_album
|
|
1176
1178
|
|
|
1177
1179
|
private
|
|
1178
1180
|
|
|
1179
1181
|
def log_add_album(album)
|
|
1180
|
-
DB[:audit_logs].insert(:
|
|
1182
|
+
DB[:audit_logs].insert(log: "Album #{album.inspect} associated to #{inspect}")
|
|
1181
1183
|
end
|
|
1182
1184
|
end
|
|
1183
1185
|
|
|
@@ -1187,7 +1189,7 @@ Called before removing an object from the association using <tt>remove_<i>associ
|
|
|
1187
1189
|
|
|
1188
1190
|
class Artist
|
|
1189
1191
|
# Don't allow removing a self-titled album
|
|
1190
|
-
one_to_many :albums, :
|
|
1192
|
+
one_to_many :albums, before_remove: lambda{|ar, al| ar.cancel_action if al.name == ar.name}
|
|
1191
1193
|
end
|
|
1192
1194
|
|
|
1193
1195
|
This is not called when using <tt>remove_all_<i>association</i></tt>.
|
|
@@ -1198,12 +1200,12 @@ Called after removing an object from the association using <tt>remove_<i>associa
|
|
|
1198
1200
|
|
|
1199
1201
|
class Artist
|
|
1200
1202
|
# Log all disassociations of albums to an audit logging table
|
|
1201
|
-
one_to_many :albums, :
|
|
1203
|
+
one_to_many :albums, after_remove: :log_remove_album
|
|
1202
1204
|
|
|
1203
1205
|
private
|
|
1204
1206
|
|
|
1205
1207
|
def log_remove_album(album)
|
|
1206
|
-
DB[:audit_logs].insert(:
|
|
1208
|
+
DB[:audit_logs].insert(log: "Album #{album.inspect} disassociated from #{inspect}")
|
|
1207
1209
|
end
|
|
1208
1210
|
end
|
|
1209
1211
|
|
|
@@ -1216,7 +1218,7 @@ Called before the _<i>association</i>= method is called to modify the objects:
|
|
|
1216
1218
|
class Album
|
|
1217
1219
|
# Don't associate the album with an artist if the year the album was
|
|
1218
1220
|
# released is less than the year the artist/band started.
|
|
1219
|
-
many_to_one :artist, :
|
|
1221
|
+
many_to_one :artist, before_set: lambda{|al, ar| al.cancel_action if al.year < ar.year_started}
|
|
1220
1222
|
end
|
|
1221
1223
|
|
|
1222
1224
|
==== :after_set [+many_to_one+, +one_to_one+]
|
|
@@ -1225,12 +1227,12 @@ Called after the _<i>association</i>= method is called to modify the objects:
|
|
|
1225
1227
|
|
|
1226
1228
|
class Album
|
|
1227
1229
|
# Log all disassociations of albums to an audit logging table
|
|
1228
|
-
many_to_one :artist, :
|
|
1230
|
+
many_to_one :artist, after_set: :log_artist_set
|
|
1229
1231
|
|
|
1230
1232
|
private
|
|
1231
1233
|
|
|
1232
1234
|
def log_artist_set(artist)
|
|
1233
|
-
DB[:audit_logs].insert(:
|
|
1235
|
+
DB[:audit_logs].insert(log: "Artist for album #{inspect} set to #{artist.inspect}")
|
|
1234
1236
|
end
|
|
1235
1237
|
end
|
|
1236
1238
|
|
|
@@ -1239,16 +1241,15 @@ Called after the _<i>association</i>= method is called to modify the objects:
|
|
|
1239
1241
|
Called after retrieving the associated records from the database.
|
|
1240
1242
|
|
|
1241
1243
|
class Artist
|
|
1242
|
-
# Cache all album names to a single string when retrieving the
|
|
1243
|
-
|
|
1244
|
-
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
|
|
1245
1246
|
|
|
1246
1247
|
attr_reader :album_names
|
|
1247
1248
|
|
|
1248
1249
|
private
|
|
1249
1250
|
|
|
1250
1251
|
def cache_album_names(albums)
|
|
1251
|
-
@album_names = albums.map
|
|
1252
|
+
@album_names = albums.map(&:name).join(", ")
|
|
1252
1253
|
end
|
|
1253
1254
|
end
|
|
1254
1255
|
|
|
@@ -1276,17 +1277,17 @@ For example, if you know that any time that you want to load an artist's
|
|
|
1276
1277
|
albums, you are also going to want access to the album's tracks as well:
|
|
1277
1278
|
|
|
1278
1279
|
# Eager load tracks when loading the albums
|
|
1279
|
-
Artist.one_to_many :albums, :
|
|
1280
|
+
Artist.one_to_many :albums, eager: :tracks
|
|
1280
1281
|
|
|
1281
1282
|
You can also use a hash or array to specify multiple dependent associations
|
|
1282
1283
|
to eagerly load:
|
|
1283
1284
|
|
|
1284
1285
|
# Eager load the albums' tracks and the tracks' tags when loading the albums
|
|
1285
|
-
Artist.one_to_many :albums, :
|
|
1286
|
+
Artist.one_to_many :albums, eager: {tracks: :tags}
|
|
1286
1287
|
# Eager load the albums' tags and tracks when loading the albums
|
|
1287
|
-
Artist.one_to_many :albums, :
|
|
1288
|
+
Artist.one_to_many :albums, eager: [:tags, :tracks]
|
|
1288
1289
|
# Eager load the albums' tags, tracks, and tracks' tags when loading the albums
|
|
1289
|
-
Artist.one_to_many :albums, :
|
|
1290
|
+
Artist.one_to_many :albums, eager: [:tags, {tracks: :tags}]
|
|
1290
1291
|
|
|
1291
1292
|
==== :eager_loader
|
|
1292
1293
|
|
|
@@ -1305,7 +1306,7 @@ performance if a custom eager loader does not use the key_hash).
|
|
|
1305
1306
|
|
|
1306
1307
|
If given, should be a proc to use instead of the association method block
|
|
1307
1308
|
when eagerly loading. To not use a block when eager loading when one is
|
|
1308
|
-
used normally,
|
|
1309
|
+
used normally, set to nil. It's very uncommon to need this option.
|
|
1309
1310
|
|
|
1310
1311
|
=== Eager Loading via eager_graph (one query with joins) Options
|
|
1311
1312
|
|
|
@@ -1316,13 +1317,11 @@ object(s). This is useful for example if you always want to eagerly load depende
|
|
|
1316
1317
|
associations when loading this association, but you want to filter or order the
|
|
1317
1318
|
association based on dependent associations:
|
|
1318
1319
|
|
|
1319
|
-
Artist.one_to_many :albums_with_short_tracks, :
|
|
1320
|
-
|
|
1321
|
-
ds.where{tracks__seconds < 120}
|
|
1320
|
+
Artist.one_to_many :albums_with_short_tracks, class: :Album, eager_graph: :tracks do |ds|
|
|
1321
|
+
ds.where{tracks[:seconds] < 120}
|
|
1322
1322
|
end
|
|
1323
|
-
Artist.one_to_many :albums_by_track_name, :
|
|
1324
|
-
|
|
1325
|
-
ds.order(:tracks__name)
|
|
1323
|
+
Artist.one_to_many :albums_by_track_name, class: :Album, eager_graph: :tracks do |ds|
|
|
1324
|
+
ds.order{tracks[:name]}
|
|
1326
1325
|
end
|
|
1327
1326
|
|
|
1328
1327
|
You can also use a hash or array of arguments for :eager_graph, similar to
|
|
@@ -1335,8 +1334,7 @@ association via eager_graph. Should be a hash or an array of two element
|
|
|
1335
1334
|
arrays. If not specified, the :conditions option is used if it is a hash or
|
|
1336
1335
|
array of two element arrays.
|
|
1337
1336
|
|
|
1338
|
-
Artist.one_to_many :active_albums, :
|
|
1339
|
-
:graph_conditions=>{:active=>true}
|
|
1337
|
+
Artist.one_to_many :active_albums, class: :Album, graph_conditions: {active: true}
|
|
1340
1338
|
|
|
1341
1339
|
Note that these conditions on the association are in addition to the default
|
|
1342
1340
|
conditions specified by the foreign/primary keys. If you want to replace
|
|
@@ -1349,8 +1347,8 @@ The block to pass to Dataset#join_table when eagerly loading the association
|
|
|
1349
1347
|
via eager_graph. This is useful to specify conditions that can't be specified
|
|
1350
1348
|
in a hash or array of two element arrays.
|
|
1351
1349
|
|
|
1352
|
-
Artist.one_to_many :gold_albums, :
|
|
1353
|
-
:
|
|
1350
|
+
Artist.one_to_many :gold_albums, class: :Album,
|
|
1351
|
+
graph_block: proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
|
|
1354
1352
|
|
|
1355
1353
|
==== :graph_join_type
|
|
1356
1354
|
|
|
@@ -1358,7 +1356,7 @@ The type of SQL join to use when eagerly loading the association via
|
|
|
1358
1356
|
eager_graph. Defaults to :left_outer. This is useful if you want to
|
|
1359
1357
|
ensure that only artists that have albums are returned:
|
|
1360
1358
|
|
|
1361
|
-
Artist.one_to_many :albums, :
|
|
1359
|
+
Artist.one_to_many :albums, graph_join_type: :inner
|
|
1362
1360
|
# Will exclude artists without an album
|
|
1363
1361
|
Artist.eager_graph(:albums).all
|
|
1364
1362
|
|
|
@@ -1380,10 +1378,11 @@ that the album was associated to the artist by name. However, you weren't
|
|
|
1380
1378
|
enforcing case sensitivity between the keys, so you still want to return albums
|
|
1381
1379
|
where the artist's name differs in case:
|
|
1382
1380
|
|
|
1383
|
-
Artist.one_to_many :albums, :
|
|
1384
|
-
:
|
|
1385
|
-
:
|
|
1386
|
-
Sequel.function(:lower, Sequel.
|
|
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)
|
|
1387
1386
|
|
|
1388
1387
|
Note how :graph_only_conditions is set to nil to ignore any existing conditions,
|
|
1389
1388
|
and :graph_block is used to set up the case insensitive comparison.
|
|
@@ -1392,12 +1391,10 @@ Another case where :graph_only_conditions may be used is if you want to use
|
|
|
1392
1391
|
a JOIN USING or NATURAL JOIN for the graph:
|
|
1393
1392
|
|
|
1394
1393
|
# JOIN USING
|
|
1395
|
-
Artist.one_to_many :albums, :
|
|
1396
|
-
:graph_only_conditions=>[:artist_name]
|
|
1394
|
+
Artist.one_to_many :albums, key: :artist_name, graph_only_conditions: [:artist_name]
|
|
1397
1395
|
|
|
1398
1396
|
# NATURAL JOIN
|
|
1399
|
-
Artist.one_to_many :albums, :
|
|
1400
|
-
: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
|
|
1401
1398
|
|
|
1402
1399
|
==== :graph_alias_base
|
|
1403
1400
|
|
|
@@ -1410,7 +1407,7 @@ This is mostly useful if you have associations with the same name in many models
|
|
|
1410
1407
|
to be able to easily tell which table alias corresponds to which association when eagerly
|
|
1411
1408
|
graphing multiple associations with the same name.
|
|
1412
1409
|
|
|
1413
|
-
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
|
|
1414
1411
|
SQL::AliasedExpression instead of a symbol:
|
|
1415
1412
|
|
|
1416
1413
|
Album.eager_graph(Sequel.as(:artist, :a))
|
|
@@ -1435,10 +1432,10 @@ at least the following keys:
|
|
|
1435
1432
|
|
|
1436
1433
|
Example:
|
|
1437
1434
|
|
|
1438
|
-
Artist.one_to_many :self_title_albums, :
|
|
1439
|
-
:eager_grapher=>(
|
|
1440
|
-
eo[:self].graph(
|
|
1441
|
-
:
|
|
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])
|
|
1442
1439
|
end)
|
|
1443
1440
|
|
|
1444
1441
|
==== :order_eager_graph
|
|
@@ -1469,9 +1466,9 @@ degrees_received that includes a string field specifying the name of the
|
|
|
1469
1466
|
degree, and you want to eager load all colleges for people where the person
|
|
1470
1467
|
has received a specific degree:
|
|
1471
1468
|
|
|
1472
|
-
Person.many_to_many :bs_degree_colleges, :
|
|
1473
|
-
:
|
|
1474
|
-
:
|
|
1469
|
+
Person.many_to_many :bs_degree_colleges, class: :College,
|
|
1470
|
+
join_table: :degrees_received,
|
|
1471
|
+
graph_join_table_conditions: {degree: 'BS'}
|
|
1475
1472
|
|
|
1476
1473
|
==== :graph_join_table_block [+many_to_many+, +one_through_one+]
|
|
1477
1474
|
|
|
@@ -1488,9 +1485,9 @@ degrees_received that includes a string field specifying the name of the
|
|
|
1488
1485
|
degree, and you want to eager load all colleges for people where the person
|
|
1489
1486
|
has received a bachelor's degree (degree starting with B):
|
|
1490
1487
|
|
|
1491
|
-
Person.many_to_many :bachelor_degree_colleges, :
|
|
1492
|
-
:
|
|
1493
|
-
:
|
|
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%')}
|
|
1494
1491
|
|
|
1495
1492
|
This should be done when graphing the join table, instead of when graphing the
|
|
1496
1493
|
final table, as :degree is a column of the join table.
|
|
@@ -1517,7 +1514,7 @@ would use when eagerly graphing.
|
|
|
1517
1514
|
Sequel's associations can work not just with columns, but also with
|
|
1518
1515
|
arbitrary SQL expressions. For example, on PostgreSQL, you can store
|
|
1519
1516
|
foreign keys to other tables in hstore, json, or jsonb columns, and Sequel
|
|
1520
|
-
can
|
|
1517
|
+
can work with such constructs, including full support for
|
|
1521
1518
|
eager loading.
|
|
1522
1519
|
|
|
1523
1520
|
There's actually two parts to supporting associations based on SQL
|
|
@@ -1530,7 +1527,7 @@ to a model instance, but needs to use the SQL expression in a query,
|
|
|
1530
1527
|
it will use the SQL expression object.
|
|
1531
1528
|
|
|
1532
1529
|
Below is an example storing foreign keys to other tables in a
|
|
1533
|
-
PostgreSQL hstore column, using the +
|
|
1530
|
+
PostgreSQL hstore column, using the +pg_json+ and +pg_json_ops+
|
|
1534
1531
|
extensions.
|
|
1535
1532
|
|
|
1536
1533
|
# Example schema:
|
|
@@ -1539,14 +1536,14 @@ extensions.
|
|
|
1539
1536
|
# :meta ---/ :name
|
|
1540
1537
|
# :name
|
|
1541
1538
|
class Album < Sequel::Model
|
|
1542
|
-
many_to_one :artist, :
|
|
1539
|
+
many_to_one :artist, key_column: Sequel.pg_jsonb(:meta)['artist_id'].cast(String).cast(Integer)
|
|
1543
1540
|
|
|
1544
1541
|
def artist_id
|
|
1545
1542
|
meta['artist_id'].to_i
|
|
1546
1543
|
end
|
|
1547
1544
|
end
|
|
1548
1545
|
class Artist < Sequel::Model
|
|
1549
|
-
one_to_many :albums, :
|
|
1546
|
+
one_to_many :albums, key: Sequel.pg_jsonb(:meta)['artist_id'].cast(String).cast(Integer), key_method: :artist_id
|
|
1550
1547
|
end
|
|
1551
1548
|
|
|
1552
1549
|
# Example schema:
|
|
@@ -1554,12 +1551,12 @@ extensions.
|
|
|
1554
1551
|
# :id <----- :meta -------> :id
|
|
1555
1552
|
# :name :name
|
|
1556
1553
|
class Album < Sequel::Model
|
|
1557
|
-
many_to_many :artists, :
|
|
1558
|
-
:
|
|
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)
|
|
1559
1556
|
end
|
|
1560
1557
|
class Artist < Sequel::Model
|
|
1561
|
-
many_to_many :albums, :
|
|
1562
|
-
:
|
|
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)
|
|
1563
1560
|
end
|
|
1564
1561
|
|
|
1565
1562
|
==== :key_column [+many_to_one+]
|
|
@@ -1592,62 +1589,6 @@ Like the :left_primary_key option, but :left_primary_key references the method n
|
|
|
1592
1589
|
Like the :right_primary_key option, but :right_primary_key references the column/expression
|
|
1593
1590
|
name, while :right_primary_key_method references the method name.
|
|
1594
1591
|
|
|
1595
|
-
=== Private Method Overriding Options
|
|
1596
|
-
|
|
1597
|
-
These options override the private methods that Sequel defines to do
|
|
1598
|
-
the actual work of associating and deassociating objects.
|
|
1599
|
-
|
|
1600
|
-
==== :setter [*_to_one associations]
|
|
1601
|
-
|
|
1602
|
-
This overrides the default behavior when you call an association setter
|
|
1603
|
-
method. Let's say you want to set a specific field whenever associating an object
|
|
1604
|
-
using the association setter method.
|
|
1605
|
-
|
|
1606
|
-
class Album < Sequel::Model
|
|
1607
|
-
many_to_one :artist, :setter=>(proc do |artist|
|
|
1608
|
-
if artist
|
|
1609
|
-
self.artist_id = artist.id
|
|
1610
|
-
self.file_under = "#{artist.name}-#{name}"
|
|
1611
|
-
else
|
|
1612
|
-
self.artist_id = nil
|
|
1613
|
-
self.file_under = name
|
|
1614
|
-
end
|
|
1615
|
-
end)
|
|
1616
|
-
end
|
|
1617
|
-
|
|
1618
|
-
==== :adder [*_to_many associations]
|
|
1619
|
-
|
|
1620
|
-
Continuing with the same example, here's how you would handle the same case if
|
|
1621
|
-
you also wanted to handle the Artist#add_album method:
|
|
1622
|
-
|
|
1623
|
-
class Artist < Sequel::Model
|
|
1624
|
-
one_to_many :albums, :adder=>(proc do |album|
|
|
1625
|
-
album.update(:artist_id => id, :file_under=>"#{name}-#{album.name}")
|
|
1626
|
-
end)
|
|
1627
|
-
end
|
|
1628
|
-
|
|
1629
|
-
==== :remover [*_to_many associations]
|
|
1630
|
-
|
|
1631
|
-
Continuing with the same example, here's how you would handle the same case if
|
|
1632
|
-
you also wanted to handle the Artist#remove_album method:
|
|
1633
|
-
|
|
1634
|
-
class Artist < Sequel::Model
|
|
1635
|
-
one_to_many :albums, :remover=>(proc do |album|
|
|
1636
|
-
album.update(:artist_id => nil, :file_under=>album.name)
|
|
1637
|
-
end)
|
|
1638
|
-
end
|
|
1639
|
-
|
|
1640
|
-
==== :clearer [*_to_many associations]
|
|
1641
|
-
|
|
1642
|
-
Continuing with the same example, here's how you would handle the same case if
|
|
1643
|
-
you also wanted to handle the Artist#remove_all_albums method:
|
|
1644
|
-
|
|
1645
|
-
class Artist < Sequel::Model
|
|
1646
|
-
one_to_many :albums, :clearer=>(proc do
|
|
1647
|
-
albums_dataset.update(:artist_id => nil, :file_under=>:name)
|
|
1648
|
-
end)
|
|
1649
|
-
end
|
|
1650
|
-
|
|
1651
1592
|
=== Advanced Options
|
|
1652
1593
|
|
|
1653
1594
|
==== :reciprocal
|
|
@@ -1659,7 +1600,7 @@ Set to nil to not use a reciprocal.
|
|
|
1659
1600
|
|
|
1660
1601
|
Reciprocals are used in Sequel to modify the matching cached associations
|
|
1661
1602
|
in associated objects when calling association methods on the current object.
|
|
1662
|
-
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
|
|
1663
1604
|
automatically set the matching many_to_one association in the associated
|
|
1664
1605
|
objects. The result of this is that code that does this:
|
|
1665
1606
|
|
|
@@ -1715,7 +1656,7 @@ the validate option should be set to false.
|
|
|
1715
1656
|
Set to false to not raise an exception when validation or a before hook
|
|
1716
1657
|
fails when implicitly saving an associated object in the add_* or remove_*
|
|
1717
1658
|
methods. This mirrors the raise_on_save_failure model setting, which these
|
|
1718
|
-
methods do not respect (by design
|
|
1659
|
+
methods do not respect (by design).
|
|
1719
1660
|
|
|
1720
1661
|
If you use this option, you must explicitly check all add_* and remove_* return
|
|
1721
1662
|
values to see if they were successful.
|
|
@@ -1725,7 +1666,7 @@ values to see if they were successful.
|
|
|
1725
1666
|
If set to false, you cannot load the association eagerly via eager or
|
|
1726
1667
|
eager_graph.
|
|
1727
1668
|
|
|
1728
|
-
Artist.one_to_many :albums, :
|
|
1669
|
+
Artist.one_to_many :albums, allow_eager: false
|
|
1729
1670
|
Artist.eager(:albums) # Raises Sequel::Error
|
|
1730
1671
|
|
|
1731
1672
|
This is usually used if the association dataset depends on specific values in
|
|
@@ -1735,11 +1676,16 @@ instances.
|
|
|
1735
1676
|
==== :instance_specific
|
|
1736
1677
|
|
|
1737
1678
|
This allows you to override the setting of whether the dataset contains instance
|
|
1738
|
-
specific code.
|
|
1679
|
+
specific code. If you are passing a block to the association,
|
|
1739
1680
|
Sequel sets this to true by default, which disables some optimizations that
|
|
1740
1681
|
would be invalid if the association is instance specific. If you know that the
|
|
1741
1682
|
block does not contain instance specific code, you can set this to false to
|
|
1742
|
-
reenable the optimizations.
|
|
1683
|
+
reenable the optimizations. Instance specific code is mostly commonly calling
|
|
1684
|
+
model instance methods inside an association block, but also
|
|
1685
|
+
includes cases where the association block can return different values based
|
|
1686
|
+
on the runtime environment, such as calls to <tt>Time.now</tt> in the block.
|
|
1687
|
+
Associations that use the :dataset option are always considered instance specific,
|
|
1688
|
+
even if explicitly specified otherwise.
|
|
1743
1689
|
|
|
1744
1690
|
==== :cartesian_product_number
|
|
1745
1691
|
|
|
@@ -1754,12 +1700,25 @@ a many_to_many association where there is a unique index in the join table
|
|
|
1754
1700
|
so that you know only one object will ever be associated through the
|
|
1755
1701
|
association.
|
|
1756
1702
|
|
|
1703
|
+
==== :class_namespace
|
|
1704
|
+
|
|
1705
|
+
If the :class option is specified as a symbol or string, the default namespace
|
|
1706
|
+
in which to look up the class. If the :class option is not specified as a
|
|
1707
|
+
symbol or string, this option is ignored. This namespace can be overridden
|
|
1708
|
+
by starting the string or symbol with <tt>::</tt>:
|
|
1709
|
+
|
|
1710
|
+
Foo::Album.many_to_one :artist, class: "Artist" # Uses Artist
|
|
1711
|
+
Foo::Album.many_to_one :artist, class: "Artist", class_namespace: 'Foo' # Uses Foo::Artist
|
|
1712
|
+
Foo::Album.many_to_one :artist, class: "Foo::Artist", class_namespace: 'Foo' # Uses Foo::Foo::Artist
|
|
1713
|
+
Foo::Album.many_to_one :artist, class: "::Artist", class_namespace: 'Foo' # Uses Artist
|
|
1714
|
+
Foo::Album.many_to_one :artist, class: "::Foo::Artist", class_namespace: 'Foo' # Uses Foo::Artist
|
|
1715
|
+
|
|
1757
1716
|
==== :methods_module
|
|
1758
1717
|
|
|
1759
1718
|
The module that the methods created by the association will be placed
|
|
1760
|
-
into. Defaults to the module containing the model's columns.
|
|
1761
|
-
is not included in the model's class,
|
|
1762
|
-
that manually.
|
|
1719
|
+
into. Defaults to the module containing the model's columns. Any module
|
|
1720
|
+
given to this option is not included in the model's class automatically,
|
|
1721
|
+
so you are responsible for doing that manually.
|
|
1763
1722
|
|
|
1764
1723
|
This is only useful in rare cases, such as when a plugin that adds
|
|
1765
1724
|
associations depends on another plugin that defines instance methods of
|
|
@@ -1803,4 +1762,3 @@ Sequel will choose either a :distinct_on, :window_function, or
|
|
|
1803
1762
|
:correlated_subquery strategy based on the association type and what
|
|
1804
1763
|
the database supports, but you can override that if necessary using
|
|
1805
1764
|
this option.
|
|
1806
|
-
|