sequel 4.49.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +70 -0
- data/README.rdoc +195 -136
- data/Rakefile +26 -42
- data/bin/sequel +3 -5
- data/doc/advanced_associations.rdoc +86 -163
- data/doc/association_basics.rdoc +197 -274
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +66 -43
- data/doc/code_order.rdoc +1 -8
- data/doc/core_extensions.rdoc +81 -56
- data/doc/dataset_basics.rdoc +8 -17
- data/doc/dataset_filtering.rdoc +81 -86
- data/doc/extensions.rdoc +3 -10
- data/doc/mass_assignment.rdoc +73 -30
- data/doc/migration.rdoc +19 -36
- data/doc/model_dataset_method_design.rdoc +14 -17
- data/doc/model_hooks.rdoc +15 -25
- data/doc/model_plugins.rdoc +10 -10
- data/doc/mssql_stored_procedures.rdoc +3 -3
- data/doc/object_model.rdoc +52 -70
- data/doc/opening_databases.rdoc +39 -32
- data/doc/postgresql.rdoc +48 -38
- data/doc/prepared_statements.rdoc +27 -22
- data/doc/querying.rdoc +173 -150
- data/doc/reflection.rdoc +5 -6
- data/doc/release_notes/5.0.0.txt +159 -0
- data/doc/schema_modification.rdoc +63 -60
- data/doc/security.rdoc +97 -88
- data/doc/sharding.rdoc +43 -30
- data/doc/sql.rdoc +53 -65
- data/doc/testing.rdoc +3 -5
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +18 -17
- data/doc/validations.rdoc +48 -45
- data/doc/virtual_rows.rdoc +87 -115
- data/lib/sequel.rb +1 -1
- data/lib/sequel/adapters/ado.rb +9 -25
- data/lib/sequel/adapters/ado/access.rb +7 -13
- data/lib/sequel/adapters/ado/mssql.rb +2 -9
- data/lib/sequel/adapters/amalgalite.rb +3 -18
- data/lib/sequel/adapters/ibmdb.rb +9 -45
- data/lib/sequel/adapters/jdbc.rb +13 -73
- data/lib/sequel/adapters/jdbc/db2.rb +8 -37
- data/lib/sequel/adapters/jdbc/derby.rb +4 -50
- data/lib/sequel/adapters/jdbc/h2.rb +4 -25
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -26
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -9
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -11
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +4 -26
- data/lib/sequel/adapters/jdbc/postgresql.rb +2 -31
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +4 -17
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -13
- data/lib/sequel/adapters/jdbc/transactions.rb +1 -14
- data/lib/sequel/adapters/mock.rb +4 -30
- data/lib/sequel/adapters/mysql.rb +7 -44
- data/lib/sequel/adapters/mysql2.rb +5 -23
- data/lib/sequel/adapters/odbc.rb +0 -19
- data/lib/sequel/adapters/odbc/db2.rb +1 -1
- data/lib/sequel/adapters/odbc/mssql.rb +4 -12
- data/lib/sequel/adapters/odbc/oracle.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +7 -13
- data/lib/sequel/adapters/postgres.rb +13 -57
- data/lib/sequel/adapters/postgresql.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +11 -51
- data/lib/sequel/adapters/shared/db2.rb +3 -61
- data/lib/sequel/adapters/shared/mssql.rb +21 -157
- data/lib/sequel/adapters/shared/mysql.rb +23 -224
- data/lib/sequel/adapters/shared/oracle.rb +13 -41
- data/lib/sequel/adapters/shared/postgres.rb +44 -259
- data/lib/sequel/adapters/shared/sqlanywhere.rb +4 -96
- data/lib/sequel/adapters/shared/sqlite.rb +12 -101
- data/lib/sequel/adapters/sqlanywhere.rb +4 -23
- data/lib/sequel/adapters/sqlite.rb +2 -19
- data/lib/sequel/adapters/tinytds.rb +5 -15
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -4
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +3 -6
- data/lib/sequel/adapters/utils/replace.rb +0 -5
- data/lib/sequel/adapters/utils/stored_procedures.rb +0 -2
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +2 -0
- data/lib/sequel/ast_transformer.rb +3 -94
- data/lib/sequel/connection_pool.rb +26 -28
- data/lib/sequel/connection_pool/sharded_single.rb +1 -4
- data/lib/sequel/connection_pool/sharded_threaded.rb +97 -95
- data/lib/sequel/connection_pool/single.rb +0 -2
- data/lib/sequel/connection_pool/threaded.rb +94 -110
- data/lib/sequel/core.rb +42 -101
- data/lib/sequel/database.rb +12 -2
- data/lib/sequel/database/connecting.rb +23 -60
- data/lib/sequel/database/dataset.rb +6 -9
- data/lib/sequel/database/dataset_defaults.rb +4 -48
- data/lib/sequel/database/features.rb +5 -4
- data/lib/sequel/database/logging.rb +2 -9
- data/lib/sequel/database/misc.rb +23 -55
- data/lib/sequel/database/query.rb +8 -13
- data/lib/sequel/database/schema_generator.rb +89 -64
- data/lib/sequel/database/schema_methods.rb +61 -79
- data/lib/sequel/database/transactions.rb +4 -24
- data/lib/sequel/dataset.rb +18 -10
- data/lib/sequel/dataset/actions.rb +53 -107
- data/lib/sequel/dataset/dataset_module.rb +3 -15
- data/lib/sequel/dataset/features.rb +30 -30
- data/lib/sequel/dataset/graph.rb +40 -49
- data/lib/sequel/dataset/misc.rb +12 -37
- data/lib/sequel/dataset/placeholder_literalizer.rb +4 -4
- data/lib/sequel/dataset/prepared_statements.rb +23 -51
- data/lib/sequel/dataset/query.rb +71 -155
- data/lib/sequel/dataset/sql.rb +30 -225
- data/lib/sequel/deprecated.rb +18 -27
- data/lib/sequel/exceptions.rb +1 -17
- data/lib/sequel/extensions/_model_pg_row.rb +0 -7
- data/lib/sequel/extensions/_pretty_table.rb +1 -3
- data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
- data/lib/sequel/extensions/connection_expiration.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +11 -11
- data/lib/sequel/extensions/core_extensions.rb +39 -49
- data/lib/sequel/extensions/core_refinements.rb +39 -45
- data/lib/sequel/extensions/current_datetime_timestamp.rb +0 -4
- data/lib/sequel/extensions/date_arithmetic.rb +7 -7
- data/lib/sequel/extensions/duplicate_columns_handler.rb +12 -9
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
- data/lib/sequel/extensions/eval_inspect.rb +4 -11
- data/lib/sequel/extensions/freeze_datasets.rb +1 -69
- data/lib/sequel/extensions/from_block.rb +1 -35
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/identifier_mangling.rb +9 -19
- data/lib/sequel/extensions/implicit_subquery.rb +2 -2
- data/lib/sequel/extensions/inflector.rb +4 -4
- data/lib/sequel/extensions/migration.rb +23 -40
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -84
- data/lib/sequel/extensions/null_dataset.rb +2 -8
- data/lib/sequel/extensions/pagination.rb +1 -17
- data/lib/sequel/extensions/pg_array.rb +20 -189
- data/lib/sequel/extensions/pg_hstore.rb +11 -50
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
- data/lib/sequel/extensions/pg_inet.rb +2 -15
- data/lib/sequel/extensions/pg_interval.rb +1 -20
- data/lib/sequel/extensions/pg_json.rb +7 -27
- data/lib/sequel/extensions/pg_loose_count.rb +1 -1
- data/lib/sequel/extensions/pg_range.rb +6 -121
- data/lib/sequel/extensions/pg_range_ops.rb +1 -3
- data/lib/sequel/extensions/pg_row.rb +5 -77
- data/lib/sequel/extensions/pg_row_ops.rb +2 -13
- data/lib/sequel/extensions/query.rb +3 -4
- data/lib/sequel/extensions/round_timestamps.rb +0 -6
- data/lib/sequel/extensions/schema_dumper.rb +13 -13
- data/lib/sequel/extensions/select_remove.rb +3 -3
- data/lib/sequel/extensions/split_array_nil.rb +2 -2
- data/lib/sequel/extensions/sql_comments.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +11 -8
- data/lib/sequel/extensions/symbol_aref.rb +6 -20
- data/lib/sequel/model.rb +27 -62
- data/lib/sequel/model/associations.rb +128 -131
- data/lib/sequel/model/base.rb +171 -711
- data/lib/sequel/model/default_inflections.rb +1 -1
- data/lib/sequel/model/errors.rb +0 -3
- data/lib/sequel/model/exceptions.rb +2 -6
- data/lib/sequel/model/inflections.rb +1 -26
- data/lib/sequel/model/plugins.rb +1 -0
- data/lib/sequel/plugins/active_model.rb +2 -5
- data/lib/sequel/plugins/association_dependencies.rb +15 -15
- data/lib/sequel/plugins/association_pks.rb +14 -28
- data/lib/sequel/plugins/association_proxies.rb +6 -7
- data/lib/sequel/plugins/auto_validations.rb +4 -4
- data/lib/sequel/plugins/before_after_save.rb +0 -43
- data/lib/sequel/plugins/blacklist_security.rb +9 -8
- data/lib/sequel/plugins/boolean_readers.rb +3 -3
- data/lib/sequel/plugins/boolean_subsets.rb +2 -2
- data/lib/sequel/plugins/caching.rb +5 -5
- data/lib/sequel/plugins/class_table_inheritance.rb +71 -102
- data/lib/sequel/plugins/column_conflicts.rb +2 -2
- data/lib/sequel/plugins/column_select.rb +2 -2
- data/lib/sequel/plugins/composition.rb +15 -24
- data/lib/sequel/plugins/constraint_validations.rb +4 -3
- data/lib/sequel/plugins/csv_serializer.rb +13 -20
- data/lib/sequel/plugins/dataset_associations.rb +2 -2
- data/lib/sequel/plugins/def_dataset_method.rb +5 -5
- data/lib/sequel/plugins/defaults_setter.rb +1 -1
- data/lib/sequel/plugins/delay_add_association.rb +1 -1
- data/lib/sequel/plugins/finder.rb +16 -10
- data/lib/sequel/plugins/force_encoding.rb +1 -7
- data/lib/sequel/plugins/hook_class_methods.rb +4 -106
- data/lib/sequel/plugins/input_transformer.rb +10 -11
- data/lib/sequel/plugins/insert_returning_select.rb +1 -9
- data/lib/sequel/plugins/instance_filters.rb +5 -5
- data/lib/sequel/plugins/instance_hooks.rb +7 -52
- data/lib/sequel/plugins/inverted_subsets.rb +3 -1
- data/lib/sequel/plugins/json_serializer.rb +19 -19
- data/lib/sequel/plugins/lazy_attributes.rb +1 -10
- data/lib/sequel/plugins/list.rb +6 -6
- data/lib/sequel/plugins/many_through_many.rb +11 -8
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/nested_attributes.rb +18 -31
- data/lib/sequel/plugins/optimistic_locking.rb +3 -3
- data/lib/sequel/plugins/pg_array_associations.rb +8 -2
- data/lib/sequel/plugins/pg_row.rb +2 -11
- data/lib/sequel/plugins/prepared_statements.rb +13 -66
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +7 -7
- data/lib/sequel/plugins/serialization.rb +15 -33
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +2 -8
- data/lib/sequel/plugins/single_table_inheritance.rb +10 -13
- data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
- data/lib/sequel/plugins/static_cache.rb +8 -9
- data/lib/sequel/plugins/string_stripper.rb +3 -3
- data/lib/sequel/plugins/subclasses.rb +1 -1
- data/lib/sequel/plugins/subset_conditions.rb +2 -2
- data/lib/sequel/plugins/table_select.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
- data/lib/sequel/plugins/timestamps.rb +6 -7
- data/lib/sequel/plugins/touch.rb +4 -8
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +2 -2
- data/lib/sequel/plugins/unlimited_update.rb +1 -7
- data/lib/sequel/plugins/update_or_create.rb +3 -3
- data/lib/sequel/plugins/update_refresh.rb +3 -3
- data/lib/sequel/plugins/uuid.rb +7 -11
- data/lib/sequel/plugins/validation_class_methods.rb +10 -9
- data/lib/sequel/plugins/validation_contexts.rb +4 -4
- data/lib/sequel/plugins/validation_helpers.rb +26 -25
- data/lib/sequel/plugins/whitelist_security.rb +13 -9
- data/lib/sequel/plugins/xml_serializer.rb +24 -25
- data/lib/sequel/sql.rb +145 -276
- data/lib/sequel/timezones.rb +8 -22
- data/lib/sequel/version.rb +2 -2
- data/spec/adapter_spec.rb +1 -1
- data/spec/adapters/db2_spec.rb +2 -103
- data/spec/adapters/mssql_spec.rb +89 -68
- data/spec/adapters/mysql_spec.rb +101 -480
- data/spec/adapters/oracle_spec.rb +1 -9
- data/spec/adapters/postgres_spec.rb +312 -565
- data/spec/adapters/spec_helper.rb +12 -31
- data/spec/adapters/sqlanywhere_spec.rb +2 -77
- data/spec/adapters/sqlite_spec.rb +8 -146
- data/spec/bin_spec.rb +11 -16
- data/spec/core/connection_pool_spec.rb +173 -74
- data/spec/core/database_spec.rb +64 -244
- data/spec/core/dataset_spec.rb +81 -415
- data/spec/core/deprecated_spec.rb +3 -3
- data/spec/core/expression_filters_spec.rb +37 -144
- data/spec/core/mock_adapter_spec.rb +176 -4
- data/spec/core/object_graph_spec.rb +11 -60
- data/spec/core/placeholder_literalizer_spec.rb +1 -14
- data/spec/core/schema_generator_spec.rb +51 -40
- data/spec/core/schema_spec.rb +74 -77
- data/spec/core/spec_helper.rb +6 -24
- data/spec/core/version_spec.rb +1 -1
- data/spec/core_extensions_spec.rb +7 -83
- data/spec/core_model_spec.rb +2 -2
- data/spec/deprecation_helper.rb +2 -14
- data/spec/extensions/accessed_columns_spec.rb +1 -1
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +2 -2
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +4 -59
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/auto_literal_strings_spec.rb +1 -12
- data/spec/extensions/auto_validations_spec.rb +1 -1
- data/spec/extensions/blacklist_security_spec.rb +1 -1
- data/spec/extensions/blank_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/caching_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +35 -1086
- data/spec/extensions/column_conflicts_spec.rb +1 -1
- data/spec/extensions/column_select_spec.rb +4 -4
- data/spec/extensions/columns_introspection_spec.rb +1 -1
- data/spec/extensions/columns_updated_spec.rb +1 -1
- data/spec/extensions/composition_spec.rb +1 -7
- data/spec/extensions/connection_expiration_spec.rb +3 -3
- data/spec/extensions/connection_validator_spec.rb +3 -3
- data/spec/extensions/constraint_validations_plugin_spec.rb +1 -1
- data/spec/extensions/constraint_validations_spec.rb +1 -1
- data/spec/extensions/core_refinements_spec.rb +1 -3
- data/spec/extensions/csv_serializer_spec.rb +4 -9
- data/spec/extensions/current_datetime_timestamp_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +2 -1
- data/spec/extensions/dataset_source_alias_spec.rb +1 -1
- data/spec/extensions/date_arithmetic_spec.rb +3 -3
- data/spec/extensions/def_dataset_method_spec.rb +1 -1
- data/spec/extensions/defaults_setter_spec.rb +2 -2
- data/spec/extensions/delay_add_association_spec.rb +8 -9
- data/spec/extensions/dirty_spec.rb +1 -1
- data/spec/extensions/duplicate_columns_handler_spec.rb +1 -1
- data/spec/extensions/eager_each_spec.rb +2 -2
- data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
- data/spec/extensions/error_splitter_spec.rb +1 -1
- data/spec/extensions/error_sql_spec.rb +1 -1
- data/spec/extensions/eval_inspect_spec.rb +1 -1
- data/spec/extensions/finder_spec.rb +1 -1
- data/spec/extensions/force_encoding_spec.rb +2 -5
- data/spec/extensions/freeze_datasets_spec.rb +1 -1
- data/spec/extensions/graph_each_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +1 -194
- data/spec/extensions/identifier_mangling_spec.rb +17 -170
- data/spec/extensions/implicit_subquery_spec.rb +1 -5
- data/spec/extensions/inflector_spec.rb +1 -1
- data/spec/extensions/input_transformer_spec.rb +7 -2
- data/spec/extensions/insert_returning_select_spec.rb +1 -1
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/instance_hooks_spec.rb +1 -95
- data/spec/extensions/inverted_subsets_spec.rb +1 -1
- data/spec/extensions/json_serializer_spec.rb +1 -1
- data/spec/extensions/lazy_attributes_spec.rb +1 -7
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +1 -1
- data/spec/extensions/migration_spec.rb +2 -2
- data/spec/extensions/modification_detection_spec.rb +1 -1
- data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
- data/spec/extensions/named_timezones_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +1 -29
- data/spec/extensions/null_dataset_spec.rb +1 -11
- data/spec/extensions/optimistic_locking_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +1 -1
- data/spec/extensions/pg_array_associations_spec.rb +4 -1
- data/spec/extensions/pg_array_ops_spec.rb +1 -1
- data/spec/extensions/pg_array_spec.rb +3 -48
- data/spec/extensions/pg_enum_spec.rb +1 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +1 -1
- data/spec/extensions/pg_hstore_spec.rb +23 -32
- data/spec/extensions/pg_inet_ops_spec.rb +1 -1
- data/spec/extensions/pg_inet_spec.rb +1 -14
- data/spec/extensions/pg_interval_spec.rb +3 -13
- data/spec/extensions/pg_json_ops_spec.rb +1 -1
- data/spec/extensions/pg_json_spec.rb +1 -13
- data/spec/extensions/pg_loose_count_spec.rb +1 -1
- data/spec/extensions/pg_range_ops_spec.rb +1 -1
- data/spec/extensions/pg_range_spec.rb +3 -88
- data/spec/extensions/pg_row_ops_spec.rb +1 -1
- data/spec/extensions/pg_row_plugin_spec.rb +1 -1
- data/spec/extensions/pg_row_spec.rb +1 -44
- data/spec/extensions/pg_static_cache_updater_spec.rb +1 -1
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/prepared_statements_spec.rb +13 -48
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +1 -12
- data/spec/extensions/rcte_tree_spec.rb +1 -1
- data/spec/extensions/round_timestamps_spec.rb +1 -5
- data/spec/extensions/s_spec.rb +1 -1
- data/spec/extensions/schema_caching_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +1 -1
- data/spec/extensions/select_remove_spec.rb +1 -1
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +2 -14
- data/spec/extensions/server_block_spec.rb +1 -1
- data/spec/extensions/server_logging_spec.rb +2 -2
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/shared_caching_spec.rb +1 -28
- data/spec/extensions/single_table_inheritance_spec.rb +2 -5
- data/spec/extensions/singular_table_names_spec.rb +1 -1
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +5 -27
- data/spec/extensions/split_array_nil_spec.rb +1 -1
- data/spec/extensions/split_values_spec.rb +1 -1
- data/spec/extensions/sql_comments_spec.rb +1 -1
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/static_cache_spec.rb +1 -1
- data/spec/extensions/string_agg_spec.rb +2 -2
- data/spec/extensions/string_date_time_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +1 -1
- data/spec/extensions/subclasses_spec.rb +1 -1
- data/spec/extensions/subset_conditions_spec.rb +1 -1
- data/spec/extensions/symbol_aref_refinement_spec.rb +1 -1
- data/spec/extensions/symbol_as_refinement_spec.rb +1 -1
- data/spec/extensions/table_select_spec.rb +4 -4
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -6
- data/spec/extensions/thread_local_timezones_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +3 -3
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/tree_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +1 -1
- data/spec/extensions/unlimited_update_spec.rb +1 -1
- data/spec/extensions/update_or_create_spec.rb +1 -1
- data/spec/extensions/update_primary_key_spec.rb +4 -3
- data/spec/extensions/update_refresh_spec.rb +1 -1
- data/spec/extensions/uuid_spec.rb +10 -12
- data/spec/extensions/validate_associated_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +3 -3
- data/spec/extensions/validation_contexts_spec.rb +1 -1
- data/spec/extensions/validation_helpers_spec.rb +10 -44
- data/spec/extensions/whitelist_security_spec.rb +5 -5
- data/spec/extensions/xml_serializer_spec.rb +3 -3
- data/spec/guards_helper.rb +2 -1
- data/spec/integration/associations_test.rb +1 -23
- data/spec/integration/database_test.rb +7 -7
- data/spec/integration/dataset_test.rb +5 -47
- data/spec/integration/eager_loader_test.rb +1 -1
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +4 -82
- data/spec/integration/plugin_test.rb +6 -22
- data/spec/integration/prepared_statement_test.rb +8 -88
- data/spec/integration/schema_test.rb +6 -6
- data/spec/integration/spec_helper.rb +13 -21
- data/spec/integration/timezone_test.rb +5 -5
- data/spec/integration/transaction_test.rb +3 -55
- data/spec/integration/type_test.rb +9 -9
- data/spec/model/association_reflection_spec.rb +24 -9
- data/spec/model/associations_spec.rb +124 -303
- data/spec/model/base_spec.rb +18 -137
- data/spec/model/class_dataset_methods_spec.rb +2 -20
- data/spec/model/dataset_methods_spec.rb +1 -20
- data/spec/model/eager_loading_spec.rb +17 -11
- data/spec/model/hooks_spec.rb +5 -300
- data/spec/model/inflector_spec.rb +1 -1
- data/spec/model/model_spec.rb +15 -320
- data/spec/model/plugins_spec.rb +2 -16
- data/spec/model/record_spec.rb +29 -121
- data/spec/model/spec_helper.rb +5 -15
- data/spec/model/validations_spec.rb +1 -1
- data/spec/sequel_warning.rb +1 -12
- metadata +8 -64
- data/doc/active_record.rdoc +0 -927
- data/lib/sequel/adapters/cubrid.rb +0 -160
- data/lib/sequel/adapters/do.rb +0 -166
- data/lib/sequel/adapters/do/mysql.rb +0 -69
- data/lib/sequel/adapters/do/postgres.rb +0 -46
- data/lib/sequel/adapters/do/sqlite3.rb +0 -41
- data/lib/sequel/adapters/jdbc/as400.rb +0 -92
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -65
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -37
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -34
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -34
- data/lib/sequel/adapters/odbc/progress.rb +0 -12
- data/lib/sequel/adapters/shared/cubrid.rb +0 -245
- data/lib/sequel/adapters/shared/firebird.rb +0 -261
- data/lib/sequel/adapters/shared/informix.rb +0 -63
- data/lib/sequel/adapters/shared/progress.rb +0 -40
- data/lib/sequel/adapters/swift.rb +0 -169
- data/lib/sequel/adapters/swift/mysql.rb +0 -50
- data/lib/sequel/adapters/swift/postgres.rb +0 -49
- data/lib/sequel/adapters/swift/sqlite.rb +0 -48
- data/lib/sequel/adapters/utils/pg_types.rb +0 -4
- data/lib/sequel/dataset/mutation.rb +0 -98
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +0 -117
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -8
- data/lib/sequel/extensions/filter_having.rb +0 -65
- data/lib/sequel/extensions/hash_aliases.rb +0 -51
- data/lib/sequel/extensions/meta_def.rb +0 -37
- data/lib/sequel/extensions/query_literals.rb +0 -86
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -26
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -133
- data/lib/sequel/extensions/set_overrides.rb +0 -82
- data/lib/sequel/no_core_ext.rb +0 -4
- data/lib/sequel/plugins/association_autoreloading.rb +0 -11
- data/lib/sequel/plugins/identifier_columns.rb +0 -49
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -11
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -90
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -137
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -71
- data/lib/sequel/plugins/schema.rb +0 -84
- data/lib/sequel/plugins/scissors.rb +0 -37
- data/spec/core/dataset_mutation_spec.rb +0 -253
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +0 -314
- data/spec/extensions/before_after_save_spec.rb +0 -40
- data/spec/extensions/filter_having_spec.rb +0 -42
- data/spec/extensions/from_block_spec.rb +0 -21
- data/spec/extensions/hash_aliases_spec.rb +0 -26
- data/spec/extensions/identifier_columns_spec.rb +0 -19
- data/spec/extensions/meta_def_spec.rb +0 -35
- data/spec/extensions/no_auto_literal_strings_spec.rb +0 -69
- data/spec/extensions/pg_typecast_on_load_spec.rb +0 -70
- data/spec/extensions/prepared_statements_associations_spec.rb +0 -212
- data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -40
- data/spec/extensions/query_literals_spec.rb +0 -185
- data/spec/extensions/schema_spec.rb +0 -123
- data/spec/extensions/scissors_spec.rb +0 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -118
- data/spec/extensions/set_overrides_spec.rb +0 -75
data/doc/migration.rdoc
CHANGED
@@ -23,7 +23,7 @@ you generally need to run Sequel's migrator with <tt>bin/sequel -m</tt>:
|
|
23
23
|
|
24
24
|
sequel -m path/to/migrations postgres://host/database
|
25
25
|
|
26
|
-
Migrations in Sequel use a
|
26
|
+
Migrations in Sequel use a DSL via the <tt>Sequel.migration</tt>
|
27
27
|
method, and inside the DSL, use the <tt>Sequel::Database</tt> schema
|
28
28
|
modification methods such as +create_table+ and +alter_table+.
|
29
29
|
See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
@@ -37,7 +37,7 @@ Here is a fairly basic Sequel migration:
|
|
37
37
|
up do
|
38
38
|
create_table(:artists) do
|
39
39
|
primary_key :id
|
40
|
-
String :name, :
|
40
|
+
String :name, null: false
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -49,9 +49,8 @@ Here is a fairly basic Sequel migration:
|
|
49
49
|
This migration has an +up+ block which adds an artist table with an integer primary key named id,
|
50
50
|
and a varchar or text column (depending on the database) named +name+ that doesn't accept +NULL+ values.
|
51
51
|
Migrations should include both up and +down+ blocks, with the +down+ block reversing
|
52
|
-
the change made by up. However, if you never need to be able to migrate down
|
53
|
-
|
54
|
-
the +down+ block. In this case, the +down+ block just reverses the changes made by up,
|
52
|
+
the change made by up. However, if you never need to be able to migrate down,
|
53
|
+
you can leave out the +down+ block. In this case, the +down+ block just reverses the changes made by up,
|
55
54
|
dropping the table.
|
56
55
|
|
57
56
|
You can simplify the migration given above by using a reversible migration with a +change+
|
@@ -61,7 +60,7 @@ block:
|
|
61
60
|
change do
|
62
61
|
create_table(:artists) do
|
63
62
|
primary_key :id
|
64
|
-
String :name, :
|
63
|
+
String :name, null: false
|
65
64
|
end
|
66
65
|
end
|
67
66
|
end
|
@@ -102,7 +101,7 @@ from Sacramento, CA, USA, but now you want to branch out and include artists in
|
|
102
101
|
Sequel.migration do
|
103
102
|
up do
|
104
103
|
add_column :artists, :location, String
|
105
|
-
from(:artists).update(:
|
104
|
+
from(:artists).update(location: 'Sacramento')
|
106
105
|
end
|
107
106
|
|
108
107
|
down do
|
@@ -117,18 +116,13 @@ just drops the +location+ column from the +artists+ table, reversing the actions
|
|
117
116
|
block.
|
118
117
|
|
119
118
|
Note that when updating the +artists+ table in the update, a plain dataset is used, <tt>from(:artists)</tt>.
|
120
|
-
This
|
119
|
+
This may look a little strange, but you need to be aware that inside an up or +down+ block in a migration,
|
121
120
|
self always refers to the <tt>Sequel::Database</tt> object that the migration is being applied to.
|
122
121
|
Since <tt>Database#from</tt> creates datasets, using <tt>from(:artists)</tt> inside the +up+ block creates
|
123
122
|
a dataset on the database representing all columns in the +artists+ table, and updates it to set the
|
124
123
|
+location+ column to <tt>'Sacramento'</tt>. You should avoid referencing the <tt>Sequel::Database</tt>
|
125
124
|
object directly in your migration, and always use self to reference it, otherwise you may run into problems.
|
126
125
|
|
127
|
-
It is possible to use model classes inside migrations, as long as they are loaded into the ruby interpreter,
|
128
|
-
but it's a bad habit as changes to your model classes can then break old migrations, and this breakage is
|
129
|
-
often not caught until much later, such as when a new developer joins the team and wants to run all migrations
|
130
|
-
to create their development database.
|
131
|
-
|
132
126
|
== The +migration+ extension
|
133
127
|
|
134
128
|
The migration code is not technically part of the core of Sequel. It's not loaded by default as it
|
@@ -244,15 +238,13 @@ the +TimestampMigrator+. They both have plusses and minuses:
|
|
244
238
|
* Doesn't allow duplicate migrations
|
245
239
|
* Doesn't allow missing migrations by default
|
246
240
|
* Just stores the version of the last migration run
|
247
|
-
* Good for single developer or small teams with close
|
248
|
-
communication
|
241
|
+
* Good for single developer or small teams with close communication
|
249
242
|
* Lower risk of undetected conflicting migrations
|
250
243
|
* Requires manual merging of simultaneous migrations
|
251
244
|
|
252
245
|
=== +TimeStampMigrator+
|
253
246
|
|
254
|
-
* More complex,
|
255
|
-
represent a timestamp
|
247
|
+
* More complex, uses migration versions where the version should represent a timestamp
|
256
248
|
* Allows duplicate migrations (since you could have multiple in a given second)
|
257
249
|
* Allows missing migrations (since you obviously don't have one every second)
|
258
250
|
* Stores the file names of all applied migrations
|
@@ -360,7 +352,7 @@ you should give it some thought before using it.
|
|
360
352
|
|
361
353
|
== Ignoring missing migrations
|
362
354
|
|
363
|
-
In some cases, you may want to allow a migration in the database that does not exist in the filesystem (deploying to an older version of code without running a down migration when deploy auto-migrates, for example). If required, you can pass <tt
|
355
|
+
In some cases, you may want to allow a migration in the database that does not exist in the filesystem (deploying to an older version of code without running a down migration when deploy auto-migrates, for example). If required, you can pass <tt>allow_missing_migration_files: true</tt> as an option. This will stop errors from being raised if there are migrations in the database that do not exist in the filesystem.
|
364
356
|
|
365
357
|
== Modifying existing migrations
|
366
358
|
|
@@ -369,7 +361,7 @@ Just don't do it.
|
|
369
361
|
In general, you should not modify any migration that has been run on the database and been committed to
|
370
362
|
the source control repository, unless the migration contains an error that causes data loss. As long
|
371
363
|
as it is possible to undo the migration without losing data, you should just add another migration
|
372
|
-
that undoes the actions of the previous bad migration, and
|
364
|
+
that undoes the actions of the previous bad migration, and does the correct action afterward.
|
373
365
|
|
374
366
|
The main problem with modifying existing migrations is that you will have to manually modify any
|
375
367
|
databases that ran the migration before it was modified. If you are a single developer, that may be
|
@@ -409,17 +401,13 @@ artist per album to multiple artists per album:
|
|
409
401
|
Sequel.migration do
|
410
402
|
up do
|
411
403
|
# Create albums_artists table
|
412
|
-
|
413
|
-
foreign_key :album_id, :albums
|
414
|
-
foreign_key :artist_id, :artists
|
415
|
-
index [:album_id, :artist_id], :unique=>true
|
416
|
-
end
|
404
|
+
create_join_table(album_id: :albums, artist_id: :artists)
|
417
405
|
|
418
406
|
# Insert one row in the albums_artists table
|
419
407
|
# for each row in the albums table where there
|
420
408
|
# is an associated artist
|
421
|
-
|
422
|
-
|
409
|
+
from(:albums_artists).insert([:album_id, :artist_id],
|
410
|
+
from(:albums).select(:id, :artist_id).exclude(artist_id: nil))
|
423
411
|
|
424
412
|
# Drop the now unnecesssary column from the albums table
|
425
413
|
drop_column :albums, :artist_id
|
@@ -431,18 +419,13 @@ artist per album to multiple artists per album:
|
|
431
419
|
# If possible, associate each album with one of the artists
|
432
420
|
# it was associated with. This loses information, but
|
433
421
|
# there's no way around that.
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
all do |r|
|
439
|
-
self[:artists].
|
440
|
-
where(:id=>r[:album_id]).
|
441
|
-
update(:artist_id=>r[:artist_id])
|
442
|
-
end
|
422
|
+
from(:albums).update(artist_id: from(:albums_artists).
|
423
|
+
select{max(artist_id)}.
|
424
|
+
where(album_id: Sequel[:albums][:id])
|
425
|
+
)
|
443
426
|
|
444
427
|
# Drop the albums_artists table
|
445
|
-
|
428
|
+
drop_join_table(album_id: :albums, artist_id: :artists)
|
446
429
|
end
|
447
430
|
end
|
448
431
|
|
@@ -9,7 +9,7 @@ call the dataset methods directly:
|
|
9
9
|
|
10
10
|
Album.
|
11
11
|
select(:id, :name, :copies_sold).
|
12
|
-
where(:
|
12
|
+
where(release_year: params[:year].to_i).
|
13
13
|
order(Sequel.desc(:copies_sold)).
|
14
14
|
all
|
15
15
|
|
@@ -19,7 +19,7 @@ One issue with this design is that it ties you to your current database schema,
|
|
19
19
|
dataset_module do
|
20
20
|
def all_albums_released_in_year(year)
|
21
21
|
select(:id, :name, :copies_sold).
|
22
|
-
where(:
|
22
|
+
where(release_year: year).
|
23
23
|
order(Sequel.desc(:copies_sold)).
|
24
24
|
all
|
25
25
|
end
|
@@ -30,7 +30,7 @@ Then your application code just needs to call your dataset method:
|
|
30
30
|
|
31
31
|
Album.all_albums_released_in_year(params[:year].to_i)
|
32
32
|
|
33
|
-
The advantage of this approach is that you can change your schema at any point in the future, and you should only need to change your model code, you should never need to change
|
33
|
+
The advantage of this approach is that you can change your schema at any point in the future, and you should only need to change your model code, you should never need to change other application code.
|
34
34
|
|
35
35
|
== Performance
|
36
36
|
|
@@ -42,16 +42,14 @@ Second, assuming the performance issue is at the Sequel level, you need to under
|
|
42
42
|
|
43
43
|
def all_albums_released_in_year(year)
|
44
44
|
select(:id, :name, :copies_sold). # new dataset allocated
|
45
|
-
where(:
|
45
|
+
where(release_year: year). # new dataset allocated
|
46
46
|
order(Sequel.desc(:copies_sold)). # new dataset allocated
|
47
47
|
all
|
48
48
|
end
|
49
49
|
|
50
|
-
Third, you need to understand that Sequel has optimizations specifically designed to reduce the number of objects allocated, by caching intermediate
|
50
|
+
Third, you need to understand that Sequel has optimizations specifically designed to reduce the number of objects allocated, by caching intermediate datasets. Unfortunately, those optimizations do not apply in this case. The reason for this is that +select+, +where+, and +order+ can potentially receive arbitrary arguments, and enabling caching for them could easily lead to unbounded cache size (denial of service due to memory exhaustion).
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
Note that freezing datasets is not enough to enable caching in this case. The reason for this is that +select+, +where+, and +order+ can potentially receive arbitrary arguments, and enabling caching for them could easily lead to unbounded cache size (denial of service due to memory exhaustion). You need to signal to Sequel that particular arguments to these methods should be cached, and you can do that by calling methods inside +dataset_module+ blocks such as +select+ and +order+. These methods will add dataset methods to the model that can use caching to optimize performance. Here is an example using these methods:
|
52
|
+
To allow intermediate dataset caching to work, you need to signal to Sequel that particular arguments to these methods should be cached, and you can do that by calling methods inside +dataset_module+ blocks such as +select+ and +order+. These methods will add dataset methods to the model that can cache the returned dataset to optimize performance. Here is an example using these methods:
|
55
53
|
|
56
54
|
class Album < Sequel::Model
|
57
55
|
dataset_module do
|
@@ -61,7 +59,7 @@ Note that freezing datasets is not enough to enable caching in this case. The r
|
|
61
59
|
def all_albums_released_in_year(year)
|
62
60
|
with_name_and_units.
|
63
61
|
by_units_sold.
|
64
|
-
where(:
|
62
|
+
where(release_year: year).
|
65
63
|
all
|
66
64
|
end
|
67
65
|
end
|
@@ -74,14 +72,14 @@ By calling +select+ and +order+ here, Sequel expects that the created dataset me
|
|
74
72
|
def all_albums_released_in_year(year)
|
75
73
|
with_name_and_units. # cached dataset returned
|
76
74
|
by_units_sold. # cached dataset returned
|
77
|
-
where(:
|
75
|
+
where(release_year: year). # new dataset allocated
|
78
76
|
all
|
79
77
|
end
|
80
78
|
|
81
79
|
Note that the order of methods here is important. If you instead change the method chain to filter the dataset first, then no caching happens:
|
82
80
|
|
83
81
|
def all_albums_released_in_year(year)
|
84
|
-
where(:
|
82
|
+
where(release_year: year). # new dataset allocated
|
85
83
|
with_name_and_units. # new dataset allocated
|
86
84
|
by_units_sold. # new dataset allocated
|
87
85
|
all
|
@@ -89,7 +87,7 @@ Note that the order of methods here is important. If you instead change the met
|
|
89
87
|
|
90
88
|
This is because any time a new, uncached dataset is returned by a dataset method, all subsequent methods in the method chain cannot benefit from caching.
|
91
89
|
|
92
|
-
Usually, when you are designing methods to process data based on user input, the user input affects the rows selected, and not the columns selected or the order in which the rows are returned. Sequel is aware of this and has
|
90
|
+
Usually, when you are designing methods to process data based on user input, the user input affects the rows selected, and not the columns selected or the order in which the rows are returned. Sequel is aware of this and has dataset methods that specifically take user input (arguments), interpret them as a filter condition and either:
|
93
91
|
|
94
92
|
* Return all matching rows in an array (+where_all+)
|
95
93
|
* Iterate over all matching rows (+where_each+)
|
@@ -101,14 +99,13 @@ After calling these methods on a cached dataset a number of times (currently 3),
|
|
101
99
|
def all_albums_released_in_year(year)
|
102
100
|
with_name_and_units. # cached dataset returned
|
103
101
|
by_units_sold. # cached dataset returned
|
104
|
-
where_all(:
|
102
|
+
where_all(release_year: year) # cached loader used
|
105
103
|
end
|
106
104
|
|
107
105
|
This can significantly improve performance, up to 3x for complex method chains that only return a few rows.
|
108
106
|
|
109
|
-
So the general advice on designing
|
107
|
+
So the general advice on designing dataset methods for performance is:
|
110
108
|
|
111
|
-
* Use frozen datasets
|
112
109
|
* Use +dataset_module+ methods to create named dataset methods that return cached datasets
|
113
110
|
* If any filtering is to be done, have it done last using +where_all+, +where_each+, +first+, or +where_single_value+.
|
114
111
|
|
@@ -120,12 +117,12 @@ The best way to further increase performance at the Sequel level is to switch to
|
|
120
117
|
|
121
118
|
class Album < Sequel::Model
|
122
119
|
ALBUMS_RELEASED_IN_YEAR = select(:id, :name, :copies_sold).
|
123
|
-
where(:
|
120
|
+
where(release_year: :$year).
|
124
121
|
order(Sequel.desc(:copies_sold)).
|
125
122
|
prepare(:all, :all_albums_released_in_year)
|
126
123
|
|
127
124
|
def self.all_albums_released_in_year(year)
|
128
|
-
ALBUMS_RELEASED_IN_YEAR.call(:year
|
125
|
+
ALBUMS_RELEASED_IN_YEAR.call(year: year)
|
129
126
|
end
|
130
127
|
end
|
131
128
|
|
data/doc/model_hooks.rdoc
CHANGED
@@ -4,7 +4,7 @@ This guide is based on http://guides.rubyonrails.org/activerecord_validations_ca
|
|
4
4
|
|
5
5
|
== Overview
|
6
6
|
|
7
|
-
Model hooks
|
7
|
+
Model hooks are used to specify actions that occur at a given point in a model instance's lifecycle, such as before or after the model object is saved, created, updated, destroyed, or validated. There are also around hooks for all types, which wrap the before hooks, the behavior, and the after hooks.
|
8
8
|
|
9
9
|
== Basic Usage
|
10
10
|
|
@@ -51,7 +51,7 @@ Sequel calls hooks in the following order when saving an existing object:
|
|
51
51
|
|
52
52
|
Note that all of the hook calls are the same, except that +around_create+, +before_create+ and +after_create+ are used for a new object, and +around_update+, +before_update+ and +after_update+ are used for an existing object. Note that +around_save+, +before_save+, and +after_save+ are called in both cases.
|
53
53
|
|
54
|
-
|
54
|
+
Note that the validation hooks are still called if <tt>validate: false</tt> option is passed to save. If you call <tt>Model#valid?</tt> manually, then only the validation hooks are called:
|
55
55
|
|
56
56
|
* +around_validation+
|
57
57
|
* +before_validation+
|
@@ -67,26 +67,19 @@ Sequel calls hooks in the following order when destroying an existing object:
|
|
67
67
|
|
68
68
|
Note that these hooks are only called when using <tt>Model#destroy</tt>, they are not called if you use <tt>Model#delete</tt>.
|
69
69
|
|
70
|
-
== Special Hook-Related Instance Variables
|
71
|
-
|
72
|
-
For after_save hooks, a @was_new instance variable is present that indicates whether the record was a new record that was just inserted, or an existing record that was updated. Sequel marks a record as existing as soon as it inserts the record, so in an after_save or after_create hook, the instance is no longer considered new. You have to check @was_new to see if the record was inserted. This exists so that you don't have to have separate after_create and after_update hooks that are mostly the same and only differ slightly depending on whether the record was a new record.
|
73
|
-
|
74
|
-
For after_update hooks, a @columns_updated instance variable is present that is a hash of the values used to update the row (keys are column symbols, values are column values). This should be used by any code that wants to check what columns and values were used during the update. You can't just check the current values of the instance, since Sequel offers ways to manually specify which columns to use during the save.
|
75
|
-
|
76
70
|
== Transaction-related Hooks
|
77
71
|
|
78
|
-
|
79
|
-
|
80
|
-
If you aren't using transactions when saving or destroying model objects, and there isn't a currently open transaction, +after_commit+ and +after_destroy_commit+ will be called after +after_save+ and +after_destroy+, respectively, and +after_rollback+ and +after_destroy_rollback+ won't be called at all.
|
81
|
-
|
82
|
-
The purpose of these hooks is dealing with external systems that are interacting with the same database. For example, let's say you have a model that stores a picture, and you have a background job library that makes thumbnails of all of the pictures. So when a model object is created, you want to add a background job that will create the thumbnail for the picture. If you used after_save for this and transactions are being used, you are subject to a race condition where the background job library will check the database table for the record before the transaction that saved the record commits, and it won't be able to see the record's data. Using after_commit, you are guaranteed that the background job library will not get notified of the record until after the transaction commits and the data is viewable.
|
83
|
-
|
84
|
-
Note that when using the after_commit or after_rollback hooks, you don't know whether the saved object was newly created or updated. If you only want to run an action after commit of a newly created record, you need to use the Database's after_commit inside the model's after_create hook:
|
72
|
+
Sequel::Model no longer offers transaction hooks for model instances. However, you can use the database transaction hooks inside model +before_save+ and +after_save+ hooks:
|
85
73
|
|
86
74
|
class Album < Sequel::Model
|
87
|
-
def
|
75
|
+
def before_save
|
76
|
+
db.after_rollback{rollback_action}
|
77
|
+
super
|
78
|
+
end
|
79
|
+
|
80
|
+
def after_save
|
88
81
|
super
|
89
|
-
db.after_commit{
|
82
|
+
db.after_commit{commit_action}
|
90
83
|
end
|
91
84
|
end
|
92
85
|
|
@@ -96,13 +89,13 @@ Sequel does not provide a simple way to turn off the running of save/create/upda
|
|
96
89
|
|
97
90
|
However, you should note that there are plenty of ways to modify the database without saving a model object. One example is by using plain datasets, or one of the model's dataset methods:
|
98
91
|
|
99
|
-
Album.where(:
|
92
|
+
Album.where(name: 'RF').update(copies_sold: Sequel.+(:copies_sold, 1))
|
100
93
|
# UPDATE albums SET copies_sold = copies_sold + 1 WHERE name = 'RF'
|
101
94
|
|
102
95
|
In this case, the +update+ method is called on the dataset returned by <tt>Album.where</tt>. Even if there is only a single object with the name RF, this will not call any hooks. If you want model hooks to be called, you need to make sure to operate on a model object:
|
103
96
|
|
104
|
-
album = Album.first(:
|
105
|
-
album.update(:
|
97
|
+
album = Album.first(name: 'RF')
|
98
|
+
album.update(copies_sold: album.copies_sold + 1)
|
106
99
|
# UPDATE albums SET copies_sold = 2 WHERE id = 1
|
107
100
|
|
108
101
|
For the destroy hooks, you need to make sure you call +destroy+ on the object:
|
@@ -121,11 +114,11 @@ However, skipping hooks is a bad idea in general and should be avoided. As ment
|
|
121
114
|
|
122
115
|
The +this+ dataset works just like any other dataset, so you can call +update+ on it to modify it:
|
123
116
|
|
124
|
-
album.this.update(:
|
117
|
+
album.this.update(copies_sold: album.copies_sold + 1)
|
125
118
|
|
126
119
|
If you want to insert a row into the model's table without running the creation hooks, you can use <tt>Model.insert</tt> instead of <tt>Model.create</tt>:
|
127
120
|
|
128
|
-
Album.insert(:
|
121
|
+
Album.insert(name: 'RF') # does not run hooks
|
129
122
|
|
130
123
|
== Canceling Actions in Hooks
|
131
124
|
|
@@ -138,8 +131,6 @@ Sometimes want to cancel an action in a before hook, so the action is not perfor
|
|
138
131
|
end
|
139
132
|
end
|
140
133
|
|
141
|
-
For backwards compatibility, Sequel also treats the <tt>before_*</tt> hook methods returning +false+ as an indication that the action should be canceled. This usage is discouraged in new code, but you should be aware of this behavior so that you do not inadvertently return false.
|
142
|
-
|
143
134
|
For around hooks, neglecting to call +super+ halts hook processing in the same way as calling +cancel_action+ in a before hook. It's probably a bad idea to use +cancel_action+ hook processing in after hooks, or after yielding in around hooks, since by then the main processing has already taken place.
|
144
135
|
|
145
136
|
By default, Sequel runs hooks other than validation hooks inside a transaction, so if you cancel the action by calling +cancel_action+ in any hook, Sequel will rollback the transaction. However, note that the implicit use of transactions when saving and destroying model objects is conditional (it depends on the model instance's +use_transactions+ setting and the <tt>:transaction</tt> option passed to save).
|
@@ -216,7 +207,6 @@ This allows the following general principles to be true:
|
|
216
207
|
|
217
208
|
* before hooks are run in reverse order of inclusion
|
218
209
|
* after hooks are run in order of inclusion
|
219
|
-
* returning false in any before hook will pass the false value down the hook method chain, halting the hook processing.
|
220
210
|
|
221
211
|
So if you define the same before hook in both a model and a plugin that the model uses, the hooks will be called in this order:
|
222
212
|
|
data/doc/model_plugins.rdoc
CHANGED
@@ -33,7 +33,7 @@ Doing this, only Node and future subclasses of Node will have the tree plugin lo
|
|
33
33
|
Some plugins require arguments and/or support options. For example, the single_table_inheritance plugin requires an argument containing the column that specifies the class to use, and options:
|
34
34
|
|
35
35
|
class Employee < Sequel::Model
|
36
|
-
plugin :single_table_inheritance, :type_id, :
|
36
|
+
plugin :single_table_inheritance, :type_id, model_map: {1=>:Staff, 2=>:Manager}
|
37
37
|
end
|
38
38
|
|
39
39
|
You should read the documentation for the plugin to determine if it requires arguments and what if any options are supported.
|
@@ -120,7 +120,7 @@ This allows a plugin user to do:
|
|
120
120
|
|
121
121
|
== Calling super to get Previous Behavior
|
122
122
|
|
123
|
-
No matter if you are dealing with class, instance, or dataset methods, you can call super inside the method to get the previous behavior. This makes it easy to hook into the method, add your own behavior, but still
|
123
|
+
No matter if you are dealing with class, instance, or dataset methods, you can call super inside the method to get the previous behavior. This makes it easy to hook into the method, add your own behavior, but still get the previous behavior:
|
124
124
|
|
125
125
|
module Sequel::Plugins::Foo
|
126
126
|
module InstanceMethods
|
@@ -135,14 +135,14 @@ No matter if you are dealing with class, instance, or dataset methods, you can c
|
|
135
135
|
private
|
136
136
|
|
137
137
|
def allow_saving?
|
138
|
-
|
138
|
+
moon =~ /Waxing/
|
139
139
|
end
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
143
|
== Running Code When the Plugin is Loaded
|
144
144
|
|
145
|
-
Some plugins require more than just adding methods. Any plugin that requires state is going to have to initialize that state and store it somewhere. If you want to run code when a plugin is loaded (usually to initialize state, but possibly for other reasons), there are two methods you can define to do so. The first method is apply, and it is called only the first time the plugin is loaded into the class, before it is loaded into the class. This is generally only used if a plugin depends on another plugin or for initializing state. You define this method as a singleton method of the plugin module:
|
145
|
+
Some plugins require more than just adding methods. Any plugin that requires state is going to have to initialize that state and store it somewhere (generally in the model class itself). If you want to run code when a plugin is loaded (usually to initialize state, but possibly for other reasons), there are two methods you can define to do so. The first method is apply, and it is called only the first time the plugin is loaded into the class, before it is loaded into the class. This is generally only used if a plugin depends on another plugin or for initializing state. You define this method as a singleton method of the plugin module:
|
146
146
|
|
147
147
|
module Sequel::Plugins::Foo
|
148
148
|
def self.apply(model)
|
@@ -158,7 +158,7 @@ The other method is called configure, and it is called everytime the plugin is l
|
|
158
158
|
module Sequel::Plugins::Foo
|
159
159
|
def self.configure(model)
|
160
160
|
model.instance_eval do
|
161
|
-
@
|
161
|
+
@foo_states[:initial] ||= :baz
|
162
162
|
end
|
163
163
|
end
|
164
164
|
end
|
@@ -177,7 +177,7 @@ If you want your plugin to take arguments and/or support options, you handle tha
|
|
177
177
|
|
178
178
|
def self.configure(model, opts={})
|
179
179
|
model.instance_eval do
|
180
|
-
@
|
180
|
+
@foo_states[:initial] = opts[:initial_state] || @foo_states[:initial] || :baz
|
181
181
|
end
|
182
182
|
end
|
183
183
|
end
|
@@ -185,7 +185,7 @@ If you want your plugin to take arguments and/or support options, you handle tha
|
|
185
185
|
This allows a user of the plugin to do either of the following
|
186
186
|
|
187
187
|
Bar.plugin :foo
|
188
|
-
Bar.plugin :foo, :
|
188
|
+
Bar.plugin :foo, initial_state: :quux
|
189
189
|
|
190
190
|
If you want to require the initial state to be provided as an argument:
|
191
191
|
|
@@ -199,7 +199,7 @@ If you want to require the initial state to be provided as an argument:
|
|
199
199
|
|
200
200
|
def self.configure(model, initial_state)
|
201
201
|
model.instance_eval do
|
202
|
-
@
|
202
|
+
@foo_states[:initial] = initial_state
|
203
203
|
end
|
204
204
|
end
|
205
205
|
end
|
@@ -216,7 +216,7 @@ Sequel::Model uses a copy-on-subclassing approach to model state. So instead of
|
|
216
216
|
|
217
217
|
module Sequel::Plugins::Foo
|
218
218
|
module ClassMethods
|
219
|
-
Sequel::Plugins.inherited_instance_variables(self, :@
|
219
|
+
Sequel::Plugins.inherited_instance_variables(self, :@foo_states => :dup)
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
@@ -238,7 +238,7 @@ In many plugins, if the model class changes the dataset, you need to change the
|
|
238
238
|
private
|
239
239
|
|
240
240
|
def set_foo_table
|
241
|
-
@
|
241
|
+
@foo_states[:table] = table_name
|
242
242
|
end
|
243
243
|
end
|
244
244
|
end
|
@@ -17,7 +17,7 @@ The following stored procedure is used as an example:
|
|
17
17
|
|
18
18
|
Execute it as follows:
|
19
19
|
|
20
|
-
DB.call_mssql_sproc(:SequelTest, {:
|
20
|
+
DB.call_mssql_sproc(:SequelTest, {args: ['Input String', :output]})
|
21
21
|
|
22
22
|
Use the +:output+ symbol to denote an output variable. The result will contain a
|
23
23
|
hash of the output variables, as well as the result code and number of affected rows:
|
@@ -27,7 +27,7 @@ hash of the output variables, as well as the result code and number of affected
|
|
27
27
|
Output variables will be strings by default. To specify their type, include the
|
28
28
|
SQL type:
|
29
29
|
|
30
|
-
DB.call_mssql_sproc(:SequelTest, {:
|
30
|
+
DB.call_mssql_sproc(:SequelTest, {args: ['Input String', [:output, 'int']]})
|
31
31
|
|
32
32
|
Result:
|
33
33
|
|
@@ -36,7 +36,7 @@ Result:
|
|
36
36
|
Output variables will be named +var#{n}+ where n is their zero indexed position
|
37
37
|
in the parameter list. To name the output variable, include their name:
|
38
38
|
|
39
|
-
DB.call_mssql_sproc(:SequelTest, {:
|
39
|
+
DB.call_mssql_sproc(:SequelTest, {args: ['Input String', [:output, nil, 'Output']]})
|
40
40
|
|
41
41
|
Result:
|
42
42
|
|