sequel 4.36.0 → 5.61.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 +548 -5749
- data/MIT-LICENSE +1 -1
- data/README.rdoc +265 -159
- data/bin/sequel +34 -12
- data/doc/advanced_associations.rdoc +228 -187
- data/doc/association_basics.rdoc +281 -291
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +86 -51
- data/doc/code_order.rdoc +25 -19
- 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/fork_safety.rdoc +84 -0
- data/doc/mass_assignment.rdoc +74 -31
- data/doc/migration.rdoc +59 -51
- 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 +58 -68
- data/doc/opening_databases.rdoc +85 -95
- data/doc/postgresql.rdoc +263 -38
- data/doc/prepared_statements.rdoc +29 -24
- data/doc/querying.rdoc +189 -167
- 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.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.4.0.txt +80 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.5.0.txt +61 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/release_notes/5.59.0.txt +73 -0
- data/doc/release_notes/5.6.0.txt +31 -0
- data/doc/release_notes/5.60.0.txt +22 -0
- data/doc/release_notes/5.61.0.txt +43 -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 +95 -75
- data/doc/security.rdoc +109 -80
- data/doc/sharding.rdoc +74 -47
- data/doc/sql.rdoc +147 -122
- data/doc/testing.rdoc +43 -20
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +97 -18
- data/doc/validations.rdoc +52 -50
- data/doc/virtual_rows.rdoc +90 -109
- data/lib/sequel/adapters/ado/access.rb +15 -17
- data/lib/sequel/adapters/ado/mssql.rb +6 -15
- data/lib/sequel/adapters/ado.rb +150 -20
- data/lib/sequel/adapters/amalgalite.rb +11 -23
- data/lib/sequel/adapters/ibmdb.rb +47 -55
- data/lib/sequel/adapters/jdbc/db2.rb +29 -39
- data/lib/sequel/adapters/jdbc/derby.rb +58 -54
- data/lib/sequel/adapters/jdbc/h2.rb +93 -35
- data/lib/sequel/adapters/jdbc/hsqldb.rb +24 -31
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -10
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -11
- data/lib/sequel/adapters/jdbc/mysql.rb +17 -20
- data/lib/sequel/adapters/jdbc/oracle.rb +22 -18
- data/lib/sequel/adapters/jdbc/postgresql.rb +69 -71
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -23
- data/lib/sequel/adapters/jdbc/sqlite.rb +47 -11
- data/lib/sequel/adapters/jdbc/sqlserver.rb +34 -9
- data/lib/sequel/adapters/jdbc/transactions.rb +22 -38
- data/lib/sequel/adapters/jdbc.rb +145 -130
- data/lib/sequel/adapters/mock.rb +100 -111
- data/lib/sequel/adapters/mysql.rb +114 -122
- data/lib/sequel/adapters/mysql2.rb +147 -63
- data/lib/sequel/adapters/odbc/db2.rb +1 -1
- data/lib/sequel/adapters/odbc/mssql.rb +8 -14
- data/lib/sequel/adapters/odbc/oracle.rb +11 -0
- data/lib/sequel/adapters/odbc.rb +20 -25
- data/lib/sequel/adapters/oracle.rb +50 -56
- data/lib/sequel/adapters/postgres.rb +305 -327
- data/lib/sequel/adapters/postgresql.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +74 -78
- data/lib/sequel/adapters/shared/db2.rb +118 -71
- data/lib/sequel/adapters/shared/mssql.rb +301 -220
- data/lib/sequel/adapters/shared/mysql.rb +299 -217
- data/lib/sequel/adapters/shared/oracle.rb +226 -65
- data/lib/sequel/adapters/shared/postgres.rb +935 -395
- data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -126
- data/lib/sequel/adapters/shared/sqlite.rb +447 -173
- data/lib/sequel/adapters/sqlanywhere.rb +48 -35
- data/lib/sequel/adapters/sqlite.rb +156 -111
- data/lib/sequel/adapters/tinytds.rb +30 -38
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +3 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -2
- 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 +1 -4
- data/lib/sequel/adapters/utils/stored_procedures.rb +7 -22
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
- data/lib/sequel/ast_transformer.rb +17 -89
- data/lib/sequel/connection_pool/sharded_single.rb +18 -15
- data/lib/sequel/connection_pool/sharded_threaded.rb +130 -111
- data/lib/sequel/connection_pool/single.rb +18 -13
- data/lib/sequel/connection_pool/threaded.rb +121 -120
- data/lib/sequel/connection_pool.rb +48 -29
- data/lib/sequel/core.rb +351 -301
- data/lib/sequel/database/connecting.rb +69 -57
- data/lib/sequel/database/dataset.rb +13 -5
- data/lib/sequel/database/dataset_defaults.rb +18 -102
- data/lib/sequel/database/features.rb +18 -4
- data/lib/sequel/database/logging.rb +12 -11
- data/lib/sequel/database/misc.rb +180 -122
- data/lib/sequel/database/query.rb +47 -27
- data/lib/sequel/database/schema_generator.rb +178 -84
- data/lib/sequel/database/schema_methods.rb +172 -97
- data/lib/sequel/database/transactions.rb +205 -44
- data/lib/sequel/database.rb +17 -2
- data/lib/sequel/dataset/actions.rb +339 -155
- data/lib/sequel/dataset/dataset_module.rb +46 -0
- data/lib/sequel/dataset/features.rb +90 -35
- data/lib/sequel/dataset/graph.rb +80 -58
- data/lib/sequel/dataset/misc.rb +137 -47
- data/lib/sequel/dataset/placeholder_literalizer.rb +63 -25
- data/lib/sequel/dataset/prepared_statements.rb +188 -85
- data/lib/sequel/dataset/query.rb +530 -222
- data/lib/sequel/dataset/sql.rb +590 -368
- data/lib/sequel/dataset.rb +26 -16
- data/lib/sequel/deprecated.rb +12 -2
- data/lib/sequel/exceptions.rb +46 -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 +2 -5
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/caller_logging.rb +79 -0
- data/lib/sequel/extensions/columns_introspection.rb +4 -3
- data/lib/sequel/extensions/connection_expiration.rb +20 -10
- data/lib/sequel/extensions/connection_validator.rb +11 -10
- data/lib/sequel/extensions/constant_sql_override.rb +65 -0
- data/lib/sequel/extensions/constraint_validations.rb +62 -39
- data/lib/sequel/extensions/core_extensions.rb +42 -48
- data/lib/sequel/extensions/core_refinements.rb +80 -59
- data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -4
- data/lib/sequel/extensions/date_arithmetic.rb +98 -39
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +41 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +21 -14
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +12 -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 +1 -34
- data/lib/sequel/extensions/graph_each.rb +4 -4
- 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 +13 -5
- data/lib/sequel/extensions/integer64.rb +32 -0
- data/lib/sequel/extensions/is_distinct_from.rb +141 -0
- data/lib/sequel/extensions/looser_typecasting.rb +17 -8
- data/lib/sequel/extensions/migration.rb +119 -78
- data/lib/sequel/extensions/named_timezones.rb +88 -23
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -82
- data/lib/sequel/extensions/null_dataset.rb +8 -8
- data/lib/sequel/extensions/pagination.rb +32 -29
- data/lib/sequel/extensions/pg_array.rb +221 -287
- data/lib/sequel/extensions/pg_array_ops.rb +17 -9
- data/lib/sequel/extensions/pg_enum.rb +63 -23
- data/lib/sequel/extensions/pg_extended_date_support.rb +241 -0
- data/lib/sequel/extensions/pg_hstore.rb +45 -54
- data/lib/sequel/extensions/pg_hstore_ops.rb +58 -6
- data/lib/sequel/extensions/pg_inet.rb +31 -12
- data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
- data/lib/sequel/extensions/pg_interval.rb +56 -29
- data/lib/sequel/extensions/pg_json.rb +417 -140
- data/lib/sequel/extensions/pg_json_ops.rb +270 -18
- data/lib/sequel/extensions/pg_loose_count.rb +4 -2
- data/lib/sequel/extensions/pg_multirange.rb +372 -0
- data/lib/sequel/extensions/pg_range.rb +131 -191
- data/lib/sequel/extensions/pg_range_ops.rb +42 -13
- data/lib/sequel/extensions/pg_row.rb +48 -81
- data/lib/sequel/extensions/pg_row_ops.rb +33 -14
- data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
- data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
- data/lib/sequel/extensions/query.rb +9 -7
- data/lib/sequel/extensions/round_timestamps.rb +0 -6
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +60 -0
- data/lib/sequel/extensions/schema_caching.rb +10 -1
- data/lib/sequel/extensions/schema_dumper.rb +71 -48
- data/lib/sequel/extensions/select_remove.rb +4 -4
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
- data/lib/sequel/extensions/server_block.rb +51 -27
- data/lib/sequel/extensions/split_array_nil.rb +4 -4
- data/lib/sequel/extensions/sql_comments.rb +119 -7
- data/lib/sequel/extensions/sql_expr.rb +2 -1
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +11 -8
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref.rb +55 -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/to_dot.rb +10 -4
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model/associations.rb +1006 -284
- data/lib/sequel/model/base.rb +560 -805
- data/lib/sequel/model/dataset_module.rb +11 -10
- data/lib/sequel/model/default_inflections.rb +1 -1
- data/lib/sequel/model/errors.rb +10 -3
- data/lib/sequel/model/exceptions.rb +8 -10
- data/lib/sequel/model/inflections.rb +7 -20
- data/lib/sequel/model/plugins.rb +114 -0
- data/lib/sequel/model.rb +32 -82
- data/lib/sequel/plugins/active_model.rb +30 -14
- data/lib/sequel/plugins/after_initialize.rb +1 -1
- data/lib/sequel/plugins/association_dependencies.rb +25 -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 +147 -70
- data/lib/sequel/plugins/association_proxies.rb +33 -9
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +95 -28
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/before_after_save.rb +0 -42
- data/lib/sequel/plugins/blacklist_security.rb +21 -12
- data/lib/sequel/plugins/boolean_readers.rb +5 -5
- data/lib/sequel/plugins/boolean_subsets.rb +13 -8
- data/lib/sequel/plugins/caching.rb +25 -16
- data/lib/sequel/plugins/class_table_inheritance.rb +179 -100
- data/lib/sequel/plugins/column_conflicts.rb +16 -3
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/column_select.rb +7 -5
- data/lib/sequel/plugins/columns_updated.rb +42 -0
- data/lib/sequel/plugins/composition.rb +42 -26
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +20 -14
- data/lib/sequel/plugins/csv_serializer.rb +56 -35
- data/lib/sequel/plugins/dataset_associations.rb +40 -17
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/defaults_setter.rb +65 -10
- data/lib/sequel/plugins/delay_add_association.rb +1 -1
- data/lib/sequel/plugins/dirty.rb +62 -24
- data/lib/sequel/plugins/eager_each.rb +3 -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/enum.rb +124 -0
- data/lib/sequel/plugins/error_splitter.rb +17 -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 +7 -12
- data/lib/sequel/plugins/hook_class_methods.rb +37 -54
- data/lib/sequel/plugins/input_transformer.rb +18 -10
- data/lib/sequel/plugins/insert_conflict.rb +76 -0
- data/lib/sequel/plugins/insert_returning_select.rb +2 -2
- data/lib/sequel/plugins/instance_filters.rb +10 -8
- data/lib/sequel/plugins/instance_hooks.rb +34 -17
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/inverted_subsets.rb +22 -13
- data/lib/sequel/plugins/json_serializer.rb +124 -64
- data/lib/sequel/plugins/lazy_attributes.rb +21 -14
- data/lib/sequel/plugins/list.rb +35 -21
- data/lib/sequel/plugins/many_through_many.rb +134 -21
- data/lib/sequel/plugins/modification_detection.rb +15 -5
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +6 -5
- data/lib/sequel/plugins/nested_attributes.rb +61 -31
- data/lib/sequel/plugins/optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/pg_array_associations.rb +103 -53
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +350 -0
- data/lib/sequel/plugins/pg_row.rb +5 -51
- data/lib/sequel/plugins/prepared_statements.rb +60 -72
- data/lib/sequel/plugins/prepared_statements_safe.rb +9 -4
- data/lib/sequel/plugins/rcte_tree.rb +68 -82
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- data/lib/sequel/plugins/serialization.rb +43 -46
- data/lib/sequel/plugins/serialization_modification_detection.rb +3 -2
- data/lib/sequel/plugins/sharding.rb +15 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +67 -28
- data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/split_values.rb +11 -6
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +77 -53
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +3 -3
- data/lib/sequel/plugins/subclasses.rb +43 -10
- data/lib/sequel/plugins/subset_conditions.rb +15 -5
- data/lib/sequel/plugins/table_select.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +96 -12
- data/lib/sequel/plugins/throw_failures.rb +110 -0
- data/lib/sequel/plugins/timestamps.rb +20 -8
- data/lib/sequel/plugins/touch.rb +19 -8
- data/lib/sequel/plugins/tree.rb +62 -32
- data/lib/sequel/plugins/typecast_on_load.rb +12 -4
- data/lib/sequel/plugins/unlimited_update.rb +1 -7
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +4 -4
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/plugins/update_refresh.rb +26 -15
- data/lib/sequel/plugins/uuid.rb +7 -11
- data/lib/sequel/plugins/validate_associated.rb +18 -0
- data/lib/sequel/plugins/validation_class_methods.rb +38 -19
- data/lib/sequel/plugins/validation_contexts.rb +49 -0
- data/lib/sequel/plugins/validation_helpers.rb +57 -41
- data/lib/sequel/plugins/whitelist_security.rb +122 -0
- data/lib/sequel/plugins/xml_serializer.rb +30 -31
- data/lib/sequel/sql.rb +471 -331
- data/lib/sequel/timezones.rb +78 -47
- data/lib/sequel/version.rb +7 -2
- data/lib/sequel.rb +1 -1
- metadata +217 -521
- data/Rakefile +0 -164
- data/doc/active_record.rdoc +0 -928
- 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.27.0.txt +0 -78
- data/doc/release_notes/4.28.0.txt +0 -57
- data/doc/release_notes/4.29.0.txt +0 -41
- data/doc/release_notes/4.3.0.txt +0 -40
- data/doc/release_notes/4.30.0.txt +0 -37
- data/doc/release_notes/4.31.0.txt +0 -57
- data/doc/release_notes/4.32.0.txt +0 -132
- data/doc/release_notes/4.33.0.txt +0 -88
- data/doc/release_notes/4.34.0.txt +0 -86
- data/doc/release_notes/4.35.0.txt +0 -130
- data/doc/release_notes/4.36.0.txt +0 -116
- 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 -144
- data/lib/sequel/adapters/do/mysql.rb +0 -66
- data/lib/sequel/adapters/do/postgres.rb +0 -44
- data/lib/sequel/adapters/do/sqlite3.rb +0 -42
- data/lib/sequel/adapters/do.rb +0 -158
- data/lib/sequel/adapters/jdbc/as400.rb +0 -84
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -64
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -36
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -33
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -33
- data/lib/sequel/adapters/odbc/progress.rb +0 -10
- data/lib/sequel/adapters/shared/cubrid.rb +0 -245
- data/lib/sequel/adapters/shared/firebird.rb +0 -247
- data/lib/sequel/adapters/shared/informix.rb +0 -54
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -152
- data/lib/sequel/adapters/shared/progress.rb +0 -40
- data/lib/sequel/adapters/swift/mysql.rb +0 -49
- data/lib/sequel/adapters/swift/postgres.rb +0 -47
- data/lib/sequel/adapters/swift/sqlite.rb +0 -49
- data/lib/sequel/adapters/swift.rb +0 -160
- data/lib/sequel/adapters/utils/pg_types.rb +0 -70
- data/lib/sequel/dataset/mutation.rb +0 -111
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -5
- data/lib/sequel/extensions/filter_having.rb +0 -63
- data/lib/sequel/extensions/hash_aliases.rb +0 -49
- data/lib/sequel/extensions/meta_def.rb +0 -35
- data/lib/sequel/extensions/query_literals.rb +0 -84
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -122
- data/lib/sequel/extensions/set_overrides.rb +0 -76
- data/lib/sequel/no_core_ext.rb +0 -3
- data/lib/sequel/plugins/association_autoreloading.rb +0 -9
- data/lib/sequel/plugins/identifier_columns.rb +0 -47
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -9
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -81
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -119
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -61
- data/lib/sequel/plugins/schema.rb +0 -82
- data/lib/sequel/plugins/scissors.rb +0 -35
- data/spec/adapter_spec.rb +0 -4
- 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 -733
- data/spec/adapters/mysql_spec.rb +0 -1319
- data/spec/adapters/oracle_spec.rb +0 -313
- data/spec/adapters/postgres_spec.rb +0 -3790
- data/spec/adapters/spec_helper.rb +0 -49
- data/spec/adapters/sqlanywhere_spec.rb +0 -170
- data/spec/adapters/sqlite_spec.rb +0 -688
- data/spec/bin_spec.rb +0 -258
- data/spec/core/connection_pool_spec.rb +0 -1045
- data/spec/core/database_spec.rb +0 -2636
- data/spec/core/dataset_spec.rb +0 -5175
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1247
- data/spec/core/mock_adapter_spec.rb +0 -464
- 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 -203
- data/spec/core/schema_spec.rb +0 -1676
- 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/core_model_spec.rb +0 -2
- data/spec/core_spec.rb +0 -1
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -85
- 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 -405
- data/spec/extensions/association_proxies_spec.rb +0 -86
- data/spec/extensions/auto_validations_spec.rb +0 -192
- data/spec/extensions/before_after_save_spec.rb +0 -40
- 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/boolean_subsets_spec.rb +0 -47
- data/spec/extensions/caching_spec.rb +0 -270
- data/spec/extensions/class_table_inheritance_spec.rb +0 -444
- 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_expiration_spec.rb +0 -121
- data/spec/extensions/connection_validator_spec.rb +0 -127
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -288
- data/spec/extensions/constraint_validations_spec.rb +0 -389
- data/spec/extensions/core_refinements_spec.rb +0 -519
- data/spec/extensions/csv_serializer_spec.rb +0 -180
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -343
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -167
- data/spec/extensions/defaults_setter_spec.rb +0 -102
- data/spec/extensions/delay_add_association_spec.rb +0 -74
- data/spec/extensions/dirty_spec.rb +0 -180
- data/spec/extensions/duplicate_columns_handler_spec.rb +0 -110
- data/spec/extensions/eager_each_spec.rb +0 -66
- 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 -119
- data/spec/extensions/hash_aliases_spec.rb +0 -24
- data/spec/extensions/hook_class_methods_spec.rb +0 -429
- data/spec/extensions/identifier_columns_spec.rb +0 -17
- 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 -304
- data/spec/extensions/lazy_attributes_spec.rb +0 -170
- data/spec/extensions/list_spec.rb +0 -278
- 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 -728
- 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/no_auto_literal_strings_spec.rb +0 -65
- 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 -390
- 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 -275
- 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 -473
- 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 -814
- 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/server_logging_spec.rb +0 -45
- 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_comments_spec.rb +0 -27
- data/spec/extensions/sql_expr_spec.rb +0 -60
- data/spec/extensions/static_cache_spec.rb +0 -361
- data/spec/extensions/string_agg_spec.rb +0 -85
- 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/subset_conditions_spec.rb +0 -38
- data/spec/extensions/table_select_spec.rb +0 -71
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -136
- 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/uuid_spec.rb +0 -106
- 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 -554
- 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/double_migration/001_create_sessions.rb +0 -9
- data/spec/files/double_migration/002_create_nodes.rb +0 -19
- data/spec/files/double_migration/003_3_create_users.rb +0 -4
- 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/empty_migration/001_create_sessions.rb +0 -9
- data/spec/files/empty_migration/002_create_nodes.rb +0 -0
- data/spec/files/empty_migration/003_3_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/reversible_migrations/006_reversible.rb +0 -10
- data/spec/files/reversible_migrations/007_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 -2506
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1858
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -262
- data/spec/integration/model_test.rb +0 -230
- data/spec/integration/plugin_test.rb +0 -2297
- data/spec/integration/prepared_statement_test.rb +0 -467
- data/spec/integration/schema_test.rb +0 -815
- data/spec/integration/spec_helper.rb +0 -56
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -406
- data/spec/integration/type_test.rb +0 -133
- data/spec/model/association_reflection_spec.rb +0 -565
- data/spec/model/associations_spec.rb +0 -4589
- data/spec/model/base_spec.rb +0 -759
- data/spec/model/class_dataset_methods_spec.rb +0 -150
- data/spec/model/dataset_methods_spec.rb +0 -149
- data/spec/model/eager_loading_spec.rb +0 -2197
- data/spec/model/hooks_spec.rb +0 -604
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -1097
- data/spec/model/plugins_spec.rb +0 -299
- data/spec/model/record_spec.rb +0 -2162
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -193
- data/spec/model_no_assoc_spec.rb +0 -1
- data/spec/model_spec.rb +0 -1
- data/spec/plugin_spec.rb +0 -1
- data/spec/sequel_coverage.rb +0 -15
- data/spec/spec_config.rb +0 -10
@@ -1,26 +1,149 @@
|
|
1
1
|
= Advanced Associations
|
2
2
|
|
3
|
-
Sequel::Model
|
3
|
+
Sequel::Model's association support is powerful and flexible, but it can be difficult for
|
4
|
+
new users to understand what the support enables. This guide shows off some of the more
|
5
|
+
advanced Sequel::Model association features.
|
4
6
|
|
5
|
-
|
7
|
+
You should probably review the {Model Associations Basics and Options guide}[rdoc-ref:doc/association_basics.rdoc]
|
8
|
+
before reviewing this guide.
|
9
|
+
|
10
|
+
== Sequel::Model Eager Loading
|
11
|
+
|
12
|
+
Sequel::Model offers two different ways to perform eager loading, +eager+ and
|
13
|
+
+eager_graph+. +eager+ uses an SQL query per association, +eager_graph+ uses a single
|
14
|
+
SQL query containing JOINs.
|
15
|
+
|
16
|
+
Assuming the following associations:
|
17
|
+
|
18
|
+
Artist.one_to_many :albums
|
19
|
+
Album.one_to_many :tracks
|
20
|
+
Tracks.many_to_one :lyric
|
21
|
+
|
22
|
+
Let's say you wanted to load all artists and eagerly load the related albums, tracks, and lyrics.
|
23
|
+
|
24
|
+
Artist.eager(albums: {tracks: :lyric})
|
25
|
+
# 4 Queries:
|
26
|
+
# SELECT * FROM artists;
|
27
|
+
# SELECT * FROM albums WHERE (artist_id IN (...));
|
28
|
+
# SELECT * FROM tracks WHERE (album_id IN (...));
|
29
|
+
# SELECT * FROM lyrics WHERE (id IN (...));
|
30
|
+
|
31
|
+
Artist.eager_graph(albums: {tracks: :lyric})
|
32
|
+
# 1 Query:
|
33
|
+
# SELECT artists.id, artists.name, ...
|
34
|
+
# albums.id AS albums_id, albums.name AS albums_name, ...
|
35
|
+
# tracks.id AS tracks_id, tracks.name AS tracks_name, ...
|
36
|
+
# lyric.id AS lyric_id, ...
|
37
|
+
# FROM artists
|
38
|
+
# LEFT OUTER JOIN albums ON (albums.artist_id = artists.id)
|
39
|
+
# LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)
|
40
|
+
# LEFT OUTER JOIN lyrics AS lyric ON (lyric.id = tracks.lyric_id);
|
41
|
+
|
42
|
+
In general, the recommendation is to use +eager+ unless you have a reason to use +eager_graph+.
|
43
|
+
+eager_graph+ is needed when you want to reference columns in an associated table. For example,
|
44
|
+
if you want to order the loading of returned artists based on the names of the albums, you cannot
|
45
|
+
do:
|
46
|
+
|
47
|
+
Artist.eager(albums: {tracks: :lyric}).order{albums[:name]}
|
48
|
+
|
49
|
+
because the initial query Sequel will use would be:
|
50
|
+
|
51
|
+
# SELECT * FROM artists ORDER BY albums.name;
|
52
|
+
|
53
|
+
and +albums+ is not a valid qualifier in such a query. In this situation, you must use +eager_graph+:
|
54
|
+
|
55
|
+
Artist.eager_graph(albums: {tracks: :lyric}).order{albums[:name]}
|
56
|
+
|
57
|
+
Whether +eager+ or +eager_graph+ performs better is association and database dependent. If
|
58
|
+
you are concerned about performance, you should try benchmarking both cases with appropriate
|
59
|
+
data to see which performs better.
|
60
|
+
|
61
|
+
=== Mixing eager and eager_graph
|
62
|
+
|
63
|
+
Sequel offers the ability to mix +eager+ and +eager_graph+ when loading results. This can
|
64
|
+
be done at the main level by calling both +eager+ and +eager_graph+ on the same dataset:
|
65
|
+
|
66
|
+
Album.eager(:artist).eager_graph(:tracks)
|
67
|
+
# 2 Queries:
|
68
|
+
# SELECT albums.id, albums.name, ...
|
69
|
+
# artist.id AS artist_id, artist.name AS artist_name, ...
|
70
|
+
# FROM albums
|
71
|
+
# LEFT OUTER JOIN artists AS artist ON (artist.id = albums.artist_id);
|
72
|
+
# SELECT * FROM artists WHERE (id IN (...));
|
73
|
+
|
74
|
+
You can also use +eager+ to load initial associations, and +eager_graph+ to load
|
75
|
+
remaining associations, by using +eager_graph+ in an eager load callback:
|
76
|
+
|
77
|
+
Artist.eager(albums: {tracks: proc{|ds| ds.eager_graph(:lyric)}})
|
78
|
+
# 3 Queries:
|
79
|
+
# SELECT * FROM artists;
|
80
|
+
# SELECT * FROM albums WHERE (artist_id IN (...));
|
81
|
+
# SELECT tracks.id, tracks.name, ...
|
82
|
+
# lyric.id AS lyric_id, ...
|
83
|
+
# FROM tracks
|
84
|
+
# LEFT OUTER JOIN lyrics AS lyric ON (lyric.id = tracks.lyric_id)
|
85
|
+
# WHERE (tracks.album_id IN (...));
|
86
|
+
|
87
|
+
Using the +eager_graph_eager+ plugin, you can use +eager_graph+ to load the
|
88
|
+
initial associations, and +eager+ to load the remaining associations. When
|
89
|
+
you call +eager_graph_eager+, you must specify the dependency chain at
|
90
|
+
which to start the eager loading via +eager+:
|
91
|
+
|
92
|
+
Artist.plugin :eager_graph_eager
|
93
|
+
Artist.eager_graph(albums: :tracks).eager_graph_eager([:albums, :tracks], :lyric)
|
94
|
+
# 2 Queries:
|
95
|
+
# SELECT artists.id, artists.name, ...
|
96
|
+
# albums.id AS albums_id, albums.name AS albums_name, ...
|
97
|
+
# tracks.id AS tracks_id, tracks.name AS tracks_name, ...
|
98
|
+
# FROM artists
|
99
|
+
# LEFT OUTER JOIN albums ON (albums.artist_id = artists.id)
|
100
|
+
# LEFT OUTER JOIN tracks ON (tracks.album_id= albums.id);
|
101
|
+
# SELECT * FROM lyrics WHERE (id IN (...));
|
102
|
+
|
103
|
+
These two approaches can also be nested, with +eager+ -> +eager_graph+ -> +eager+:
|
104
|
+
|
105
|
+
Album.plugin :eager_graph_eager
|
106
|
+
Artist.eager(albums: proc{|ds| ds.eager_graph(:tracks).eager_graph_eager([:tracks], :lyric)})
|
107
|
+
# 3 Queries:
|
108
|
+
# SELECT * FROM artists;
|
109
|
+
# SELECT albums.id, albums.name, ...
|
110
|
+
# tracks.id AS tracks_id, tracks.name AS tracks_name, ...
|
111
|
+
# FROM albums
|
112
|
+
# LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)
|
113
|
+
# WHERE (albums.artist_id IN (...));
|
114
|
+
# SELECT * FROM lyrics WHERE (id IN (...));
|
115
|
+
|
116
|
+
Or with 2 separate +eager_graph+ queries:
|
117
|
+
|
118
|
+
Artist.eager_graph(:albums).eager_graph_eager([:albums], :tracks=>proc{|ds| ds.eager_graph(:lyric)})
|
119
|
+
# 2 Queries:
|
120
|
+
# SELECT artists.id, artists.name, ...
|
121
|
+
# albums.id AS albums_id, albums.name AS albums_name, ...
|
122
|
+
# FROM artists
|
123
|
+
# LEFT OUTER JOIN albums ON (albums.artist_id = artists.id);
|
124
|
+
# SELECT tracks.id, tracks.name, ...
|
125
|
+
# lyric.id AS lyric_id, ...
|
126
|
+
# FROM tracks
|
127
|
+
# LEFT OUTER JOIN lyrics AS lyric ON (lyric.id = tracks.lyric_id)
|
128
|
+
# WHERE (tracks.album_id IN (...));
|
129
|
+
|
130
|
+
== Sequel::Model Association Loading Options
|
6
131
|
|
7
132
|
There are a bunch of advanced association options that are available to
|
8
|
-
handle more complex cases. First we'll go over some of
|
9
|
-
the simpler ones:
|
133
|
+
handle more complex cases. First we'll go over some of the simpler ones:
|
10
134
|
|
11
135
|
All associations take a block that can be used to further filter/modify the
|
12
|
-
default dataset
|
13
|
-
a different block when eager loading via <tt>Dataset#eager</tt>. Association blocks are
|
14
|
-
useful for things like:
|
136
|
+
default dataset:
|
15
137
|
|
16
|
-
Artist.one_to_many :gold_albums, :
|
138
|
+
Artist.one_to_many :gold_albums, class: :Album do |ds|
|
17
139
|
ds.where{copies_sold > 500000}
|
18
140
|
end
|
19
141
|
|
20
|
-
There
|
21
|
-
|
22
|
-
|
23
|
-
|
142
|
+
There's also an :eager_block option if you want to use a different block when
|
143
|
+
eager loading via <tt>Dataset#eager</tt>.
|
144
|
+
|
145
|
+
There are many options for changing how the association is eagerly
|
146
|
+
loaded via <tt>Dataset#eager_graph</tt>:
|
24
147
|
|
25
148
|
:graph_join_type :: The type of join to do (<tt>:inner</tt>, <tt>:left</tt>, <tt>:right</tt>)
|
26
149
|
:graph_conditions :: Additional conditions to put on join (needs to be a
|
@@ -42,28 +165,23 @@ These can be used like this:
|
|
42
165
|
|
43
166
|
# Makes Artist.eager_graph(:required_albums).all not return artists that
|
44
167
|
# don't have any albums
|
45
|
-
Artist.one_to_many :required_albums, :
|
168
|
+
Artist.one_to_many :required_albums, class: :Album, graph_join_type: :inner
|
46
169
|
|
47
170
|
# Makes sure all returned albums have the active flag set
|
48
|
-
Artist.one_to_many :active_albums, :
|
49
|
-
:graph_conditions=>{:active=>true}
|
171
|
+
Artist.one_to_many :active_albums, class: :Album, graph_conditions: {active: true}
|
50
172
|
|
51
173
|
# Only returns albums that have sold more than 500,000 copies
|
52
|
-
Artist.one_to_many :gold_albums, :
|
53
|
-
:
|
174
|
+
Artist.one_to_many :gold_albums, class: :Album,
|
175
|
+
graph_block: proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
|
54
176
|
|
55
177
|
# Handles the case where the tables are associated by a case insensitive name string
|
56
|
-
Artist.one_to_many :albums, :
|
57
|
-
:
|
58
|
-
:
|
178
|
+
Artist.one_to_many :albums, key: :artist_name,
|
179
|
+
graph_only_conditions: nil,
|
180
|
+
graph_block: proc{|j,lj,js| {Sequel.function(:lower, Sequel[j][:artist_name])=>Sequel.function(:lower, Sequel[lj][:name])}}
|
59
181
|
|
60
182
|
# Handles the case where both key columns have the name artist_name, and you want to use
|
61
183
|
# a JOIN USING
|
62
|
-
Artist.one_to_many :albums, :
|
63
|
-
|
64
|
-
Remember, using +eager_graph+ is generally only necessary when you need to
|
65
|
-
filter/order based on columns in an associated table, it is recommended to
|
66
|
-
use +eager+ for eager loading if possible.
|
184
|
+
Artist.one_to_many :albums, key: :artist_name, graph_only_conditions: [:artist_name]
|
67
185
|
|
68
186
|
One advantage of using +eager_graph+ is that you can easily filter/order
|
69
187
|
on columns in an associated table on a per-query basis, using regular
|
@@ -73,14 +191,16 @@ ordered by the albums name, you can do:
|
|
73
191
|
|
74
192
|
albums = Artist.
|
75
193
|
eager_graph(:albums).
|
76
|
-
where
|
77
|
-
order
|
194
|
+
where{Sequel.like(albums[:name], 'A%')}.
|
195
|
+
order{albums[:name]}.
|
78
196
|
all
|
79
197
|
|
80
198
|
For lazy loading (e.g. Model[1].association), the <tt>:dataset</tt> option can be used
|
81
199
|
to specify an arbitrary dataset (one that uses different keys, multiple keys,
|
82
200
|
joins to other tables, etc.).
|
83
201
|
|
202
|
+
== Custom Eager Loaders
|
203
|
+
|
84
204
|
For eager loading via +eager+, the <tt>:eager_loader</tt> option can be used to specify
|
85
205
|
how to eagerly load a complex association. This is an extremely powerful
|
86
206
|
option. Though it can often be verbose (compared to other things in Sequel),
|
@@ -211,7 +331,7 @@ and the tracks eager loader looks like:
|
|
211
331
|
Album.one_to_many :tracks, :eager_loader=>(proc do |eo_opts|
|
212
332
|
eo_opts[:rows].each{|album| album.associations[:tracks] = []}
|
213
333
|
id_map = eo_opts[:id_map]
|
214
|
-
Track.where(:
|
334
|
+
Track.where(:album_id=>id_map.keys).all do |track|
|
215
335
|
if albums = id_map[track.album_id]
|
216
336
|
albums.each do |album|
|
217
337
|
album.associations[:tracks] << track
|
@@ -244,7 +364,7 @@ loading.
|
|
244
364
|
|
245
365
|
Sequel supports specifying limits and/or offsets for associations:
|
246
366
|
|
247
|
-
Artist.one_to_many :first_10_albums, :
|
367
|
+
Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10
|
248
368
|
|
249
369
|
For retrieving the associated objects for a single object, this just uses
|
250
370
|
a LIMIT:
|
@@ -260,7 +380,7 @@ approach. Sequel has 4 separate strategies for dealing with such cases.
|
|
260
380
|
The default strategy used on all databases is a UNION-based approach, which
|
261
381
|
will submit multiple subqueries in a UNION query:
|
262
382
|
|
263
|
-
Artist.where(:
|
383
|
+
Artist.where(id: [1,2]).eager(:first_10_albums).all
|
264
384
|
# SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 1) LIMIT 10) UNION ALL
|
265
385
|
# SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 2) LIMIT 10)
|
266
386
|
|
@@ -272,9 +392,9 @@ index, you'll want to manually specify the :eager_limit_strategy option as shown
|
|
272
392
|
On PostgreSQL, for *_one associations that don't use an offset, you can
|
273
393
|
choose to use a the distinct on strategy:
|
274
394
|
|
275
|
-
Artist.one_to_one :first_album, :
|
276
|
-
:
|
277
|
-
Artist.where(:
|
395
|
+
Artist.one_to_one :first_album, class: :Album, order: :release_date,
|
396
|
+
eager_limit_strategy: :distinct_on
|
397
|
+
Artist.where(id: [1,2]).eager(:first_album).all
|
278
398
|
# SELECT DISTINCT ON (albums.artist_id) *
|
279
399
|
# FROM albums
|
280
400
|
# WHERE (albums.artist_id IN (1, 2))
|
@@ -283,8 +403,8 @@ choose to use a the distinct on strategy:
|
|
283
403
|
Otherwise, if the database supports window functions, you can choose to use
|
284
404
|
the window function strategy:
|
285
405
|
|
286
|
-
Artist.one_to_many :first_10_albums, :
|
287
|
-
:
|
406
|
+
Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10,
|
407
|
+
eager_limit_strategy: :window_function
|
288
408
|
Artist.where(:id=>[1,2]).eager(:first_10_albums).all
|
289
409
|
# SELECT * FROM (
|
290
410
|
# SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
|
@@ -304,7 +424,7 @@ known at the time of the association definition), Sequel supports an
|
|
304
424
|
:eager_limit dataset option that can be defined in an eager loading callback:
|
305
425
|
|
306
426
|
Artist.one_to_many :albums
|
307
|
-
Artist.where(:
|
427
|
+
Artist.where(id: [1, 2]).eager(albums: lambda{|ds| ds.order(:release_date).clone(eager_limit: 3)}).all
|
308
428
|
# SELECT * FROM (
|
309
429
|
# SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
|
310
430
|
# FROM albums
|
@@ -314,7 +434,7 @@ known at the time of the association definition), Sequel supports an
|
|
314
434
|
|
315
435
|
You can also customize the :eager_limit_strategy on a case-by-case basis by passing in that option in the same way:
|
316
436
|
|
317
|
-
Artist.where(:
|
437
|
+
Artist.where(id: [1, 2]).eager(albums: lambda{|ds| ds.order(:release_date).clone(eager_limit: 3, eager_limit_strategy: :ruby)}).all
|
318
438
|
# SELECT * FROM albums WHERE (albums.artist_id IN (1, 2)) ORDER BY release_date
|
319
439
|
|
320
440
|
The :eager_limit and :eager_limit_strategy options currently only work when
|
@@ -333,7 +453,7 @@ eager_graph_with_options method with the :limit_strategy option.
|
|
333
453
|
The :distinct_on strategy uses DISTINCT ON in a subquery and JOINs that
|
334
454
|
subquery:
|
335
455
|
|
336
|
-
Artist.eager_graph_with_options(:first_album, :
|
456
|
+
Artist.eager_graph_with_options(:first_album, limit_strategy: :distinct_on).all
|
337
457
|
# SELECT artists.id, artists.name, first_album.id AS first_album_id,
|
338
458
|
# first_album.name AS first_album_name, first_album.artist_id,
|
339
459
|
# first_album.release_date
|
@@ -347,7 +467,7 @@ subquery:
|
|
347
467
|
The :window_function approach JOINs to a nested subquery using a window
|
348
468
|
function:
|
349
469
|
|
350
|
-
Artist.eager_graph_with_options(:first_10_albums, :
|
470
|
+
Artist.eager_graph_with_options(:first_10_albums, limit_strategy: :window_function).all
|
351
471
|
# SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
|
352
472
|
# first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
|
353
473
|
# first_10_albums.release_date
|
@@ -363,7 +483,7 @@ function:
|
|
363
483
|
The :correlated_subquery approach JOINs to a nested subquery using a correlated
|
364
484
|
subquery:
|
365
485
|
|
366
|
-
Artist.eager_graph_with_options(:first_10_albums, :limit_strategy
|
486
|
+
Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>:correlated_subquery).all
|
367
487
|
# SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
|
368
488
|
# first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
|
369
489
|
# first_10_albums.release_date
|
@@ -380,8 +500,6 @@ subquery:
|
|
380
500
|
# )
|
381
501
|
# ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
|
382
502
|
|
383
|
-
(SELECT * FROM tracks WHERE (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1)))
|
384
|
-
|
385
503
|
The reason that Sequel does not automatically use the :distinct_on, :window function
|
386
504
|
or :correlated_subquery strategy for eager_graph is that it can perform much worse than the
|
387
505
|
default of just doing the array slicing in ruby. If you are only using eager_graph to
|
@@ -403,7 +521,7 @@ strategy based on the database you are using, and you can override it using the
|
|
403
521
|
|
404
522
|
The :distinct_on strategy:
|
405
523
|
|
406
|
-
Artist.where(:
|
524
|
+
Artist.where(first_album: Album[1]).all
|
407
525
|
# SELECT *
|
408
526
|
# FROM artists
|
409
527
|
# WHERE (artists.id IN (
|
@@ -417,7 +535,7 @@ The :distinct_on strategy:
|
|
417
535
|
|
418
536
|
The :window_function strategy:
|
419
537
|
|
420
|
-
Artist.where(:
|
538
|
+
Artist.where(first_10_albums: Album[1]).all
|
421
539
|
# SELECT *
|
422
540
|
# FROM artists
|
423
541
|
# WHERE (artists.id IN (
|
@@ -433,7 +551,7 @@ The :window_function strategy:
|
|
433
551
|
|
434
552
|
The :correlated_subquery strategy:
|
435
553
|
|
436
|
-
Artist.where(:
|
554
|
+
Artist.where(first_10_albums: Album[1]).all
|
437
555
|
# SELECT *
|
438
556
|
# FROM artists
|
439
557
|
# WHERE (artists.id IN (
|
@@ -447,11 +565,11 @@ The :correlated_subquery strategy:
|
|
447
565
|
# LIMIT 1
|
448
566
|
# )) AND (albums.id = 1))))
|
449
567
|
|
450
|
-
Note that filtering by limited associations does not work on MySQL, as does not support
|
568
|
+
Note that filtering by limited associations does not work on MySQL, as MySQL does not support
|
451
569
|
any of the strategies. It's also not supported when using composite keys on databases
|
452
570
|
that don't support window functions and don't support multiple columns in IN.
|
453
571
|
|
454
|
-
|
572
|
+
=== Additional Association Types
|
455
573
|
|
456
574
|
While the above examples for limited associations showed one_to_many and one_to_one associations,
|
457
575
|
it's just because those are the simplest examples. Sequel supports all of the same features for
|
@@ -459,29 +577,7 @@ many_to_many and one_through_one associations that are enabled by default, as we
|
|
459
577
|
many_through_many and one_through_many associations that are added by the many_through_many
|
460
578
|
plugin.
|
461
579
|
|
462
|
-
==
|
463
|
-
|
464
|
-
Sequel supports all of associations that ActiveRecord supports, though some
|
465
|
-
require different approaches or custom <tt>:eager_loader</tt> options.
|
466
|
-
|
467
|
-
=== Association callbacks
|
468
|
-
|
469
|
-
Sequel supports the same callbacks that ActiveRecord does for +one_to_many+ and
|
470
|
-
+many_to_many+ associations: <tt>:before_add</tt>, <tt>:before_remove</tt>, <tt>:after_add</tt>, and
|
471
|
-
<tt>:after_remove</tt>. For +many_to_one+ associations and +one_to_one+ associations, Sequel
|
472
|
-
supports the <tt>:before_set</tt> and <tt>:after_set</tt> callbacks. On all associations,
|
473
|
-
Sequel supports <tt>:after_load</tt>, which is called after the association has been
|
474
|
-
loaded.
|
475
|
-
|
476
|
-
Each of these options can be a symbol specifying an instance method
|
477
|
-
that takes one argument (the associated object), or a proc that takes
|
478
|
-
two arguments (the current object and the associated object), or an
|
479
|
-
array of symbols and procs. For <tt>:after_load</tt> with a *_to_many association,
|
480
|
-
the associated object argument is an array of associated objects.
|
481
|
-
|
482
|
-
If any of the before callbacks return +false+, the adding/removing
|
483
|
-
does not happen and it either raises a <tt>Sequel::HookFailed</tt> (the default), or
|
484
|
-
returns false (if +raise_on_save_failure+ is false).
|
580
|
+
== More advanced association examples
|
485
581
|
|
486
582
|
=== Association extensions
|
487
583
|
|
@@ -504,36 +600,21 @@ the model object that created the association dataset via the dataset's
|
|
504
600
|
end
|
505
601
|
end
|
506
602
|
class Author < Sequel::Model
|
507
|
-
one_to_many :authorships, :
|
603
|
+
one_to_many :authorships, extend: FindOrCreate
|
508
604
|
end
|
509
|
-
Author.first.authorships_dataset.find_or_create(:
|
605
|
+
Author.first.authorships_dataset.find_or_create(name: 'Blah', number: 10)
|
510
606
|
|
511
|
-
===
|
607
|
+
=== many_to_many associations through model tables
|
512
608
|
|
513
|
-
|
514
|
-
|
515
|
-
model
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
class Author < ActiveRecord::Base
|
520
|
-
has_many :authorships
|
521
|
-
has_many :books, :through => :authorships
|
522
|
-
end
|
523
|
-
|
524
|
-
class Authorship < ActiveRecord::Base
|
525
|
-
belongs_to :author
|
526
|
-
belongs_to :book
|
527
|
-
end
|
528
|
-
|
529
|
-
@author = Author.find :first
|
530
|
-
@author.books
|
531
|
-
|
532
|
-
Sequel::Model:
|
609
|
+
The many_to_many association can be used even when the join table is a table used for a
|
610
|
+
model. The only requirement is the join table has foreign keys to both the current
|
611
|
+
model and the associated model. Anytime there is a one_to_many association from model A to
|
612
|
+
model B, and model B has a many_to_one association to model C, you can use a many_to_many
|
613
|
+
association from model A to model C.
|
533
614
|
|
534
615
|
class Author < Sequel::Model
|
535
616
|
one_to_many :authorships
|
536
|
-
many_to_many :books, :
|
617
|
+
many_to_many :books, join_table: :authorships
|
537
618
|
end
|
538
619
|
|
539
620
|
class Authorship < Sequel::Model
|
@@ -544,33 +625,17 @@ Sequel::Model:
|
|
544
625
|
@author = Author.first
|
545
626
|
@author.books
|
546
627
|
|
547
|
-
|
548
|
-
you still use a +many_to_many+ association, but you need to use some options:
|
549
|
-
|
550
|
-
ActiveRecord:
|
551
|
-
|
552
|
-
class Firm < ActiveRecord::Base
|
553
|
-
has_many :clients
|
554
|
-
has_many :invoices, :through => :clients
|
555
|
-
end
|
556
|
-
|
557
|
-
class Client < ActiveRecord::Base
|
558
|
-
belongs_to :firm
|
559
|
-
has_many :invoices
|
560
|
-
end
|
561
|
-
|
562
|
-
class Invoice < ActiveRecord::Base
|
563
|
-
belongs_to :client
|
564
|
-
has_one :firm, :through => :client
|
565
|
-
end
|
628
|
+
=== many_to_many for three-level associations
|
566
629
|
|
567
|
-
|
568
|
-
|
569
|
-
|
630
|
+
You can even use a many_to_many association between model A and model C if model A has a
|
631
|
+
one_to_many association to model B, and model B has a one_to_many association to model C.
|
632
|
+
You just need to use the appropriate :right_key and :right_primary_key options. And in
|
633
|
+
the reverse direction from model C to model A, you can use a one_through_one association
|
634
|
+
using the :left_key and :left_primary_key options.
|
570
635
|
|
571
636
|
class Firm < Sequel::Model
|
572
637
|
one_to_many :clients
|
573
|
-
many_to_many :invoices, :
|
638
|
+
many_to_many :invoices, join_table: :clients, right_key: :id, right_primary_key: :client_id
|
574
639
|
end
|
575
640
|
|
576
641
|
class Client < Sequel::Model
|
@@ -580,12 +645,13 @@ Sequel::Model:
|
|
580
645
|
|
581
646
|
class Invoice < Sequel::Model
|
582
647
|
many_to_one :client
|
583
|
-
one_through_one :firm, :
|
648
|
+
one_through_one :firm, join_table: :clients, left_key: :id, left_primary_key: :client_id
|
584
649
|
end
|
585
650
|
|
586
651
|
Firm.first.invoices
|
652
|
+
Invoice.first.firm
|
587
653
|
|
588
|
-
To handle cases where there are multiple join tables, use the many_through_many
|
654
|
+
To handle cases where there are multiple join tables, you can use the many_through_many
|
589
655
|
plugin that ships with Sequel.
|
590
656
|
|
591
657
|
=== Polymorphic Associations
|
@@ -602,38 +668,19 @@ you are stuck with an existing design that uses them.
|
|
602
668
|
If you must use them, look for the sequel_polymorphic external plugin, as it makes using
|
603
669
|
polymorphic associations in Sequel about as easy as it is in ActiveRecord. However,
|
604
670
|
here's how they can be done using Sequel's custom associations (the sequel_polymorphic
|
605
|
-
plugin is just a generic version of this code):
|
606
|
-
|
607
|
-
ActiveRecord:
|
608
|
-
|
609
|
-
class Asset < ActiveRecord::Base
|
610
|
-
belongs_to :attachable, :polymorphic => true
|
611
|
-
end
|
612
|
-
|
613
|
-
class Post < ActiveRecord::Base
|
614
|
-
has_many :assets, :as => :attachable
|
615
|
-
end
|
616
|
-
|
617
|
-
class Note < ActiveRecord::Base
|
618
|
-
has_many :assets, :as => :attachable
|
619
|
-
end
|
620
|
-
|
621
|
-
@asset.attachable = @post
|
622
|
-
@asset.attachable = @note
|
623
|
-
|
624
|
-
Sequel::Model:
|
671
|
+
external plugin is just a generic version of this code):
|
625
672
|
|
626
673
|
class Asset < Sequel::Model
|
627
|
-
many_to_one :attachable, :
|
628
|
-
:
|
674
|
+
many_to_one :attachable, reciprocal: :assets,
|
675
|
+
setter: (lambda do |attachable|
|
629
676
|
self[:attachable_id] = (attachable.pk if attachable)
|
630
677
|
self[:attachable_type] = (attachable.class.name if attachable)
|
631
678
|
end),
|
632
|
-
:
|
679
|
+
dataset: (proc do
|
633
680
|
klass = attachable_type.constantize
|
634
681
|
klass.where(klass.primary_key=>attachable_id)
|
635
682
|
end),
|
636
|
-
:
|
683
|
+
eager_loader: (lambda do |eo|
|
637
684
|
id_map = {}
|
638
685
|
eo[:rows].each do |asset|
|
639
686
|
asset.associations[:attachable] = nil
|
@@ -651,24 +698,22 @@ Sequel::Model:
|
|
651
698
|
end
|
652
699
|
|
653
700
|
class Post < Sequel::Model
|
654
|
-
one_to_many :assets, :
|
655
|
-
:
|
656
|
-
:
|
657
|
-
:
|
701
|
+
one_to_many :assets, key: :attachable_id, reciprocal: :attachable, conditions: {attachable_type: 'Post'},
|
702
|
+
adder: lambda{|asset| asset.update(attachable_id: pk, attachable_type: 'Post')},
|
703
|
+
remover: lambda{|asset| asset.update(attachable_id: nil, attachable_type: nil)},
|
704
|
+
clearer: lambda{assets_dataset.update(attachable_id: nil, attachable_type: nil)}
|
658
705
|
end
|
659
706
|
|
660
707
|
class Note < Sequel::Model
|
661
|
-
one_to_many :assets, :
|
662
|
-
:
|
663
|
-
:
|
664
|
-
:
|
708
|
+
one_to_many :assets, key: :attachable_id, reciprocal: :attachable, conditions: {attachable_type: 'Note'},
|
709
|
+
adder: lambda{|asset| asset.update(attachable_id: pk, attachable_type: 'Note')},
|
710
|
+
remover: lambda{|asset| asset.update(attachable_id: nil, attachable_type: nil)},
|
711
|
+
clearer: lambda{assets_dataset.update(attachable_id: nil, attachable_type: nil)}
|
665
712
|
end
|
666
713
|
|
667
714
|
@asset.attachable = @post
|
668
715
|
@asset.attachable = @note
|
669
716
|
|
670
|
-
== Other advanced associations
|
671
|
-
|
672
717
|
=== Joining on multiple keys
|
673
718
|
|
674
719
|
Let's say you have two tables that are associated with each other with multiple
|
@@ -680,36 +725,36 @@ associations:
|
|
680
725
|
# associated favorite track
|
681
726
|
|
682
727
|
class Track < Sequel::Model
|
683
|
-
many_to_one :favorite_track, :
|
728
|
+
many_to_one :favorite_track, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
|
684
729
|
end
|
685
730
|
class FavoriteTrack < Sequel::Model
|
686
|
-
one_to_one :tracks, :
|
731
|
+
one_to_one :tracks, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
|
687
732
|
end
|
688
733
|
|
689
|
-
=== Tree - All Ancestors and
|
734
|
+
=== Tree - All Ancestors and Descendants
|
690
735
|
|
691
736
|
Let's say you want to store a tree relationship in your database, it's pretty
|
692
737
|
simple:
|
693
738
|
|
694
739
|
class Node < Sequel::Model
|
695
|
-
many_to_one :parent, :
|
696
|
-
one_to_many :children, :
|
740
|
+
many_to_one :parent, class: self
|
741
|
+
one_to_many :children, key: :parent_id, class: self
|
697
742
|
end
|
698
743
|
|
699
744
|
You can easily get a node's parent with node.parent, and a node's children with
|
700
745
|
node.children. You can even eager load the relationship up to a certain depth:
|
701
746
|
|
702
747
|
# Eager load three generations of generations of children for a given node
|
703
|
-
Node.
|
748
|
+
Node.where(id: 1).eager(children: {children: :children}).all.first
|
704
749
|
# Load parents and grandparents for a group of nodes
|
705
|
-
Node.
|
750
|
+
Node.where{id < 10}.eager(parent: :parent).all
|
706
751
|
|
707
|
-
What if you want to get all ancestors up to the root node, or all
|
752
|
+
What if you want to get all ancestors up to the root node, or all descendants,
|
708
753
|
without knowing the depth of the tree?
|
709
754
|
|
710
755
|
class Node < Sequel::Model
|
711
|
-
many_to_one :ancestors, :
|
712
|
-
:
|
756
|
+
many_to_one :ancestors, class: self,
|
757
|
+
eager_loader: (lambda do |eo|
|
713
758
|
# Handle cases where the root node has the same parent_id as primary_key
|
714
759
|
# and also when it is NULL
|
715
760
|
non_root_nodes = eo[:rows].reject do |n|
|
@@ -725,15 +770,15 @@ without knowing the depth of the tree?
|
|
725
770
|
id_map = {}
|
726
771
|
# Create an map of parent_ids to nodes that have that parent id
|
727
772
|
non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
|
728
|
-
# Doesn't cause an
|
773
|
+
# Doesn't cause an infinite loop, because when only the root node
|
729
774
|
# is left, this is not called.
|
730
|
-
Node.where(
|
775
|
+
Node.where(id: id_map.keys).eager(:ancestors).all do |node|
|
731
776
|
# Populate the parent association for each node
|
732
777
|
id_map[node.pk].each{|n| n.associations[:parent] = node}
|
733
778
|
end
|
734
779
|
end
|
735
780
|
end)
|
736
|
-
many_to_one :descendants, :
|
781
|
+
many_to_one :descendants, eager_loader: (lambda do |eo|
|
737
782
|
id_map = {}
|
738
783
|
eo[:rows].each do |n|
|
739
784
|
# Initialize an empty array of child associations for each parent node
|
@@ -745,7 +790,7 @@ without knowing the depth of the tree?
|
|
745
790
|
# if no records are returned. Exclude id = parent_id to avoid infinite loop
|
746
791
|
# if the root note is one of the returned records and it has parent_id = id
|
747
792
|
# instead of parent_id = NULL.
|
748
|
-
Node.where(:
|
793
|
+
Node.where(parent_id: id_map.keys).exclude(id: :parent_id).eager(:descendants).all do |node|
|
749
794
|
# Get the parent from the identity map
|
750
795
|
parent = id_map[node.parent_id]
|
751
796
|
# Set the child's parent association to the parent
|
@@ -756,11 +801,7 @@ without knowing the depth of the tree?
|
|
756
801
|
end)
|
757
802
|
end
|
758
803
|
|
759
|
-
Note that
|
760
|
-
The results are not the same as in the above case, as all descendents are stored in a single association,
|
761
|
-
but all descendants can be both lazy loaded or eager loaded in a single query (assuming your database
|
762
|
-
supports recursive common table expressions). Sequel ships with an +rcte_tree+ plugin that makes
|
763
|
-
this easy:
|
804
|
+
Note that Sequel ships with an rcte_tree plugin that does all of the above and more:
|
764
805
|
|
765
806
|
class Node < Sequel::Model
|
766
807
|
plugin :rcte_tree
|
@@ -780,21 +821,21 @@ What you want to do is get all songs for a given artist, ordered by the song's
|
|
780
821
|
name, with no duplicates?
|
781
822
|
|
782
823
|
class Artist < Sequel::Model
|
783
|
-
one_to_many :songs, :
|
784
|
-
:
|
785
|
-
:
|
824
|
+
one_to_many :songs, order: Sequel[:songs][:name],
|
825
|
+
dataset: proc{Song.select_all(:songs).join(:lyrics, id: :lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])},
|
826
|
+
eager_loader: (lambda do |eo|
|
786
827
|
h = eo[:id_map]
|
787
828
|
ids = h.keys
|
788
829
|
eo[:rows].each{|r| r.associations[:songs] = []}
|
789
830
|
Song.select_all(:songs).
|
790
|
-
select_append
|
791
|
-
join(
|
792
|
-
order
|
793
|
-
|
794
|
-
|
795
|
-
|
831
|
+
select_append{[lyrics[:composer_id], lyrics[:arranger_id], lyrics[:vocalist_id], lyrics[:lyricist_id]]}.
|
832
|
+
join(:lyrics, id: :lyric_id){Sequel.or(composer_id: ids, arranger_id: ids, vocalist_id: ids, lyricist_id: ids)}.
|
833
|
+
order{songs[:name]}.all do |song|
|
834
|
+
[:composer_id, :arranger_id, :vocalist_id, :lyricist_id].each do |x|
|
835
|
+
recs = h[song.values.delete(x)]
|
836
|
+
recs.each{|r| r.associations[:songs] << song} if recs
|
837
|
+
end
|
796
838
|
end
|
797
|
-
end
|
798
839
|
eo[:rows].each{|r| r.associations[:songs].uniq!}
|
799
840
|
end)
|
800
841
|
end
|
@@ -811,11 +852,11 @@ associated tickets.
|
|
811
852
|
|
812
853
|
class Project < Sequel::Model
|
813
854
|
one_to_many :tickets
|
814
|
-
many_to_one :ticket_hours, :
|
815
|
-
:
|
816
|
-
:
|
855
|
+
many_to_one :ticket_hours, read_only: true, key: :id,
|
856
|
+
dataset: proc{Ticket.where(:project_id=>id).select{sum(hours).as(hours)}},
|
857
|
+
eager_loader: (lambda do |eo|
|
817
858
|
eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
|
818
|
-
Ticket.where(:
|
859
|
+
Ticket.where(project_id: eo[:id_map].keys).
|
819
860
|
select_group(:project_id).
|
820
861
|
select_append{sum(hours).as(hours)}.
|
821
862
|
all do |t|
|
@@ -838,4 +879,4 @@ associated tickets.
|
|
838
879
|
end
|
839
880
|
|
840
881
|
Note that it is often better to use a sum cache instead of this approach. You can implement
|
841
|
-
a sum cache using +after_create+ and +after_delete+ hooks, or
|
882
|
+
a sum cache using +after_create+, +after_update+, and +after_delete+ hooks, or preferably using a database trigger.
|