sequel 5.20.0 → 5.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +398 -1922
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/doc/advanced_associations.rdoc +4 -4
- data/doc/association_basics.rdoc +80 -16
- data/doc/cheat_sheet.rdoc +6 -5
- data/doc/code_order.rdoc +10 -12
- data/doc/dataset_filtering.rdoc +17 -2
- data/doc/fork_safety.rdoc +84 -0
- data/doc/migration.rdoc +11 -5
- data/doc/model_dataset_method_design.rdoc +1 -1
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +10 -2
- data/doc/postgresql.rdoc +82 -3
- data/doc/querying.rdoc +4 -4
- 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.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.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/sharding.rdoc +2 -0
- data/doc/sql.rdoc +13 -1
- data/doc/testing.rdoc +20 -7
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +43 -35
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
- data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
- data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
- data/lib/sequel/adapters/jdbc.rb +24 -6
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +2 -3
- data/lib/sequel/adapters/odbc.rb +8 -6
- data/lib/sequel/adapters/oracle.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +15 -9
- data/lib/sequel/adapters/shared/access.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +66 -21
- data/lib/sequel/adapters/shared/mysql.rb +27 -10
- data/lib/sequel/adapters/shared/oracle.rb +29 -23
- data/lib/sequel/adapters/shared/postgres.rb +271 -32
- data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
- data/lib/sequel/adapters/shared/sqlite.rb +161 -19
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +15 -2
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +4 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
- data/lib/sequel/connection_pool/single.rb +1 -1
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/core.rb +333 -319
- data/lib/sequel/database/connecting.rb +3 -4
- data/lib/sequel/database/logging.rb +7 -1
- data/lib/sequel/database/misc.rb +31 -12
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +53 -51
- data/lib/sequel/database/schema_methods.rb +38 -23
- data/lib/sequel/database/transactions.rb +17 -18
- data/lib/sequel/dataset/actions.rb +14 -9
- data/lib/sequel/dataset/features.rb +16 -0
- data/lib/sequel/dataset/misc.rb +2 -2
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +26 -9
- data/lib/sequel/dataset/sql.rb +76 -25
- data/lib/sequel/dataset.rb +4 -2
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/connection_expiration.rb +2 -2
- data/lib/sequel/extensions/connection_validator.rb +2 -2
- data/lib/sequel/extensions/core_refinements.rb +2 -0
- data/lib/sequel/extensions/date_arithmetic.rb +36 -24
- data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/index_caching.rb +9 -7
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/integer64.rb +2 -0
- data/lib/sequel/extensions/migration.rb +11 -3
- data/lib/sequel/extensions/named_timezones.rb +56 -8
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +5 -0
- data/lib/sequel/extensions/pg_array_ops.rb +14 -6
- data/lib/sequel/extensions/pg_enum.rb +11 -3
- data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +6 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
- data/lib/sequel/extensions/pg_inet.rb +15 -5
- data/lib/sequel/extensions/pg_interval.rb +36 -8
- data/lib/sequel/extensions/pg_json.rb +387 -123
- data/lib/sequel/extensions/pg_json_ops.rb +238 -0
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_range.rb +17 -9
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +4 -2
- data/lib/sequel/extensions/pg_row_ops.rb +24 -0
- data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +24 -7
- data/lib/sequel/extensions/server_block.rb +18 -7
- data/lib/sequel/extensions/sql_comments.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model/associations.rb +356 -117
- data/lib/sequel/model/base.rb +107 -68
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +9 -3
- data/lib/sequel/model.rb +3 -1
- 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 +60 -18
- data/lib/sequel/plugins/association_proxies.rb +8 -2
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_validations.rb +39 -5
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/boolean_subsets.rb +4 -1
- data/lib/sequel/plugins/caching.rb +3 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +7 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/csv_serializer.rb +28 -9
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +60 -22
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/insert_conflict.rb +72 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +57 -35
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +15 -3
- data/lib/sequel/plugins/pg_array_associations.rb +58 -41
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
- data/lib/sequel/plugins/prepared_statements.rb +15 -12
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +43 -35
- data/lib/sequel/plugins/serialization.rb +8 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +11 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/static_cache.rb +9 -4
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +2 -0
- data/lib/sequel/plugins/throw_failures.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/plugins/validation_helpers.rb +18 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +20 -5
- data/lib/sequel/timezones.rb +63 -17
- data/lib/sequel/version.rb +1 -1
- metadata +113 -381
- data/Rakefile +0 -151
- 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.37.0.txt +0 -50
- data/doc/release_notes/4.38.0.txt +0 -67
- data/doc/release_notes/4.39.0.txt +0 -127
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.40.0.txt +0 -179
- data/doc/release_notes/4.41.0.txt +0 -77
- data/doc/release_notes/4.42.0.txt +0 -221
- data/doc/release_notes/4.43.0.txt +0 -87
- data/doc/release_notes/4.44.0.txt +0 -125
- data/doc/release_notes/4.45.0.txt +0 -370
- data/doc/release_notes/4.46.0.txt +0 -404
- data/doc/release_notes/4.47.0.txt +0 -56
- data/doc/release_notes/4.48.0.txt +0 -293
- data/doc/release_notes/4.49.0.txt +0 -222
- 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/spec/adapter_spec.rb +0 -4
- data/spec/adapters/db2_spec.rb +0 -170
- data/spec/adapters/mssql_spec.rb +0 -804
- data/spec/adapters/mysql_spec.rb +0 -1065
- data/spec/adapters/oracle_spec.rb +0 -371
- data/spec/adapters/postgres_spec.rb +0 -4125
- data/spec/adapters/spec_helper.rb +0 -44
- data/spec/adapters/sqlanywhere_spec.rb +0 -97
- data/spec/adapters/sqlite_spec.rb +0 -652
- data/spec/bin_spec.rb +0 -278
- data/spec/core/connection_pool_spec.rb +0 -1250
- data/spec/core/database_spec.rb +0 -2865
- data/spec/core/dataset_spec.rb +0 -5515
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1455
- data/spec/core/mock_adapter_spec.rb +0 -722
- data/spec/core/object_graph_spec.rb +0 -336
- data/spec/core/placeholder_literalizer_spec.rb +0 -166
- data/spec/core/schema_generator_spec.rb +0 -214
- data/spec/core/schema_spec.rb +0 -1826
- data/spec/core/spec_helper.rb +0 -24
- data/spec/core/version_spec.rb +0 -14
- data/spec/core_extensions_spec.rb +0 -763
- data/spec/core_model_spec.rb +0 -2
- data/spec/core_spec.rb +0 -1
- data/spec/deprecation_helper.rb +0 -30
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -99
- data/spec/extensions/after_initialize_spec.rb +0 -28
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -125
- data/spec/extensions/association_pks_spec.rb +0 -423
- data/spec/extensions/association_proxies_spec.rb +0 -100
- data/spec/extensions/auto_literal_strings_spec.rb +0 -205
- data/spec/extensions/auto_validations_spec.rb +0 -229
- data/spec/extensions/blacklist_security_spec.rb +0 -95
- 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 -273
- data/spec/extensions/caller_logging_spec.rb +0 -52
- data/spec/extensions/class_table_inheritance_spec.rb +0 -750
- data/spec/extensions/column_conflicts_spec.rb +0 -75
- data/spec/extensions/column_select_spec.rb +0 -129
- data/spec/extensions/columns_introspection_spec.rb +0 -90
- data/spec/extensions/columns_updated_spec.rb +0 -35
- data/spec/extensions/composition_spec.rb +0 -248
- data/spec/extensions/connection_expiration_spec.rb +0 -151
- data/spec/extensions/connection_validator_spec.rb +0 -144
- data/spec/extensions/constant_sql_override_spec.rb +0 -24
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
- data/spec/extensions/constraint_validations_spec.rb +0 -439
- data/spec/extensions/core_refinements_spec.rb +0 -528
- data/spec/extensions/csv_serializer_spec.rb +0 -183
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -365
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -181
- data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
- data/spec/extensions/def_dataset_method_spec.rb +0 -100
- data/spec/extensions/defaults_setter_spec.rb +0 -150
- data/spec/extensions/delay_add_association_spec.rb +0 -73
- data/spec/extensions/dirty_spec.rb +0 -189
- data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
- data/spec/extensions/eager_each_spec.rb +0 -62
- data/spec/extensions/eager_graph_eager_spec.rb +0 -100
- 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/escaped_like_spec.rb +0 -40
- data/spec/extensions/eval_inspect_spec.rb +0 -81
- data/spec/extensions/finder_spec.rb +0 -260
- data/spec/extensions/force_encoding_spec.rb +0 -126
- data/spec/extensions/freeze_datasets_spec.rb +0 -31
- data/spec/extensions/graph_each_spec.rb +0 -113
- data/spec/extensions/hook_class_methods_spec.rb +0 -402
- data/spec/extensions/identifier_mangling_spec.rb +0 -201
- data/spec/extensions/implicit_subquery_spec.rb +0 -58
- data/spec/extensions/index_caching_spec.rb +0 -66
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -69
- data/spec/extensions/insert_returning_select_spec.rb +0 -72
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -246
- data/spec/extensions/integer64_spec.rb +0 -22
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -336
- data/spec/extensions/lazy_attributes_spec.rb +0 -183
- data/spec/extensions/list_spec.rb +0 -291
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2177
- data/spec/extensions/migration_spec.rb +0 -864
- data/spec/extensions/modification_detection_spec.rb +0 -93
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
- data/spec/extensions/named_timezones_spec.rb +0 -111
- data/spec/extensions/nested_attributes_spec.rb +0 -767
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -127
- data/spec/extensions/pagination_spec.rb +0 -116
- data/spec/extensions/pg_array_associations_spec.rb +0 -802
- data/spec/extensions/pg_array_ops_spec.rb +0 -144
- data/spec/extensions/pg_array_spec.rb +0 -398
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
- data/spec/extensions/pg_enum_spec.rb +0 -118
- data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
- data/spec/extensions/pg_hstore_spec.rb +0 -219
- data/spec/extensions/pg_inet_ops_spec.rb +0 -102
- data/spec/extensions/pg_inet_spec.rb +0 -72
- data/spec/extensions/pg_interval_spec.rb +0 -103
- data/spec/extensions/pg_json_ops_spec.rb +0 -289
- data/spec/extensions/pg_json_spec.rb +0 -262
- data/spec/extensions/pg_loose_count_spec.rb +0 -23
- data/spec/extensions/pg_range_ops_spec.rb +0 -60
- data/spec/extensions/pg_range_spec.rb +0 -519
- data/spec/extensions/pg_row_ops_spec.rb +0 -61
- data/spec/extensions/pg_row_plugin_spec.rb +0 -60
- data/spec/extensions/pg_row_spec.rb +0 -363
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
- data/spec/extensions/pg_timestamptz_spec.rb +0 -17
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
- data/spec/extensions/prepared_statements_spec.rb +0 -177
- data/spec/extensions/pretty_table_spec.rb +0 -123
- data/spec/extensions/query_spec.rb +0 -94
- data/spec/extensions/rcte_tree_spec.rb +0 -381
- data/spec/extensions/round_timestamps_spec.rb +0 -39
- data/spec/extensions/s_spec.rb +0 -60
- data/spec/extensions/schema_caching_spec.rb +0 -64
- data/spec/extensions/schema_dumper_spec.rb +0 -870
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -365
- data/spec/extensions/server_block_spec.rb +0 -97
- data/spec/extensions/server_logging_spec.rb +0 -45
- data/spec/extensions/sharding_spec.rb +0 -189
- data/spec/extensions/shared_caching_spec.rb +0 -151
- data/spec/extensions/single_table_inheritance_spec.rb +0 -347
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -18
- data/spec/extensions/spec_helper.rb +0 -63
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -57
- data/spec/extensions/sql_comments_spec.rb +0 -33
- data/spec/extensions/sql_expr_spec.rb +0 -59
- data/spec/extensions/static_cache_spec.rb +0 -471
- data/spec/extensions/string_agg_spec.rb +0 -90
- 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 -79
- data/spec/extensions/subset_conditions_spec.rb +0 -38
- data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
- data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
- data/spec/extensions/synchronize_sql_spec.rb +0 -124
- data/spec/extensions/table_select_spec.rb +0 -83
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/throw_failures_spec.rb +0 -74
- data/spec/extensions/timestamps_spec.rb +0 -209
- data/spec/extensions/to_dot_spec.rb +0 -153
- data/spec/extensions/touch_spec.rb +0 -226
- data/spec/extensions/tree_spec.rb +0 -334
- data/spec/extensions/typecast_on_load_spec.rb +0 -86
- data/spec/extensions/unlimited_update_spec.rb +0 -21
- data/spec/extensions/update_or_create_spec.rb +0 -83
- data/spec/extensions/update_primary_key_spec.rb +0 -105
- data/spec/extensions/update_refresh_spec.rb +0 -59
- data/spec/extensions/uuid_spec.rb +0 -101
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1040
- data/spec/extensions/validation_contexts_spec.rb +0 -31
- data/spec/extensions/validation_helpers_spec.rb +0 -525
- data/spec/extensions/whitelist_security_spec.rb +0 -157
- data/spec/extensions/xml_serializer_spec.rb +0 -213
- 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 -59
- data/spec/integration/associations_test.rb +0 -2597
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1981
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -262
- data/spec/integration/model_test.rb +0 -203
- data/spec/integration/plugin_test.rb +0 -2396
- data/spec/integration/prepared_statement_test.rb +0 -405
- data/spec/integration/schema_test.rb +0 -889
- data/spec/integration/spec_helper.rb +0 -65
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -603
- data/spec/integration/type_test.rb +0 -127
- data/spec/model/association_reflection_spec.rb +0 -803
- data/spec/model/associations_spec.rb +0 -4738
- data/spec/model/base_spec.rb +0 -875
- data/spec/model/class_dataset_methods_spec.rb +0 -146
- data/spec/model/dataset_methods_spec.rb +0 -198
- data/spec/model/eager_loading_spec.rb +0 -2377
- data/spec/model/hooks_spec.rb +0 -370
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -956
- data/spec/model/plugins_spec.rb +0 -429
- data/spec/model/record_spec.rb +0 -2118
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -220
- 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/sequel_warning.rb +0 -4
- data/spec/spec_config.rb +0 -12
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
# :nocov:
|
|
4
|
+
|
|
5
|
+
# This entire file is excluded from coverage testing. This is because it
|
|
6
|
+
# requires coverage testing to work, and if you've already loaded Sequel
|
|
7
|
+
# without enabling coverage, then coverage testing won't work correctly
|
|
8
|
+
# for methods defined by Sequel.
|
|
9
|
+
#
|
|
10
|
+
# While automated coverage testing is disabled, manual coverage testing
|
|
11
|
+
# was used during spec development to make sure this code is 100% covered.
|
|
12
|
+
|
|
13
|
+
if RUBY_VERSION < '2.5'
|
|
14
|
+
raise LoadError, "The Sequel unused_associations plugin depends on Ruby 2.5+ method coverage"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'coverage'
|
|
18
|
+
require 'json'
|
|
19
|
+
|
|
20
|
+
module Sequel
|
|
21
|
+
module Plugins
|
|
22
|
+
# The unused_associations plugin detects which model associations are not
|
|
23
|
+
# used and can be removed, and which model association methods are not used
|
|
24
|
+
# and can skip being defined. The advantage of removing unused associations
|
|
25
|
+
# and unused association methods is decreased memory usage, since each
|
|
26
|
+
# method defined takes memory and adds more work for the garbage collector.
|
|
27
|
+
#
|
|
28
|
+
# In order to detect which associations are used, this relies on the method
|
|
29
|
+
# coverage support added in Ruby 2.5. To allow flexibility to override
|
|
30
|
+
# association methods, the association methods that Sequel defines are
|
|
31
|
+
# defined in a module included in the class instead of directly in the
|
|
32
|
+
# class. Unfortunately, that makes it difficult to directly use the
|
|
33
|
+
# coverage data to find unused associations. The advantage of this plugin
|
|
34
|
+
# is that it is able to figure out from the coverage information whether
|
|
35
|
+
# the association methods Sequel defines are actually used.
|
|
36
|
+
#
|
|
37
|
+
# = Basic Usage
|
|
38
|
+
#
|
|
39
|
+
# The expected usage of the unused_associations plugin is to load it
|
|
40
|
+
# into the base class for models in your application, which will often
|
|
41
|
+
# be Sequel::Model:
|
|
42
|
+
#
|
|
43
|
+
# Sequel::Model.plugin :unused_associations
|
|
44
|
+
#
|
|
45
|
+
# Then you run your test suite with method coverage enabled, passing the
|
|
46
|
+
# coverage result to +update_associations_coverage+.
|
|
47
|
+
# +update_associations_coverage+ returns a data structure containing
|
|
48
|
+
# method coverage information for all subclasses of the base class.
|
|
49
|
+
# You can pass the coverage information to
|
|
50
|
+
# +update_unused_associations_data+, which will return a data structure
|
|
51
|
+
# with information on unused associations.
|
|
52
|
+
#
|
|
53
|
+
# require 'coverage'
|
|
54
|
+
# Coverage.start(methods: true)
|
|
55
|
+
# # load sequel after starting coverage, then run your tests
|
|
56
|
+
# cov_data = Sequel::Model.update_associations_coverage
|
|
57
|
+
# unused_associations_data = Sequel::Model.update_unused_associations_data(coverage_data: cov_data)
|
|
58
|
+
#
|
|
59
|
+
# You can take that unused association data and pass it to the
|
|
60
|
+
# +unused_associations+ method to get a array of information on
|
|
61
|
+
# associations which have not been used. Each entry in the array
|
|
62
|
+
# will contain a class name and association name for each unused
|
|
63
|
+
# association, both as a string:
|
|
64
|
+
#
|
|
65
|
+
# Sequel::Model.unused_associations(unused_associations_data: unused_associations_data)
|
|
66
|
+
# # => [["Class1", "assoc1"], ...]
|
|
67
|
+
#
|
|
68
|
+
# You can use the output of the +unused_associations+ method to determine
|
|
69
|
+
# which associations are not used at all in your application, and can
|
|
70
|
+
# be eliminiated.
|
|
71
|
+
#
|
|
72
|
+
# You can also take that unused association data and pass it to the
|
|
73
|
+
# +unused_association_options+ method, which will return an array of
|
|
74
|
+
# information on associations which are used, but have related methods
|
|
75
|
+
# defined that are not used. The first two entries in each array are
|
|
76
|
+
# the class name and association name as a string, and the third
|
|
77
|
+
# entry is a hash of association options:
|
|
78
|
+
#
|
|
79
|
+
# Sequel::Model.unused_association_options(unused_associations_data: unused_associations_data)
|
|
80
|
+
# # => [["Class2", "assoc2", {:read_only=>true}], ...]
|
|
81
|
+
#
|
|
82
|
+
# You can use the output of the +unused_association_options+ to
|
|
83
|
+
# find out which association options can be provided when defining
|
|
84
|
+
# the association so that the association method will not define
|
|
85
|
+
# methods that are not used.
|
|
86
|
+
#
|
|
87
|
+
# = Combining Coverage Results
|
|
88
|
+
#
|
|
89
|
+
# It is common to want to combine results from multiple separate
|
|
90
|
+
# coverage runs. For example, if you have multiple test suites
|
|
91
|
+
# for your application, one for model or unit tests and one for
|
|
92
|
+
# web or integration tests, you would want to combine the
|
|
93
|
+
# coverage information from all test suites before determining
|
|
94
|
+
# that the associations are not used.
|
|
95
|
+
#
|
|
96
|
+
# The unused_associations plugin supports combining multiple
|
|
97
|
+
# coverage results using the :coverage_file plugin option:
|
|
98
|
+
#
|
|
99
|
+
# Sequel::Model.plugin :unused_associations,
|
|
100
|
+
# coverage_file: 'unused_associations_coverage.json'
|
|
101
|
+
#
|
|
102
|
+
# With the coverage file option, +update_associations_coverage+
|
|
103
|
+
# will look in the given file for existing coverage information,
|
|
104
|
+
# if it exists. If the file exists, the data from it will be
|
|
105
|
+
# merged with the coverage result passed to the method.
|
|
106
|
+
# Before returning, the coverage file will be updated with the
|
|
107
|
+
# merged result. When using the :coverage_file plugin option,
|
|
108
|
+
# you can each of your test suites update the coverage
|
|
109
|
+
# information:
|
|
110
|
+
#
|
|
111
|
+
# require 'coverage'
|
|
112
|
+
# Coverage.start(methods: true)
|
|
113
|
+
# # run this test suite
|
|
114
|
+
# Sequel::Model.update_associations_coverage
|
|
115
|
+
#
|
|
116
|
+
# After all test suites have been run, you can run
|
|
117
|
+
# +update_unused_associations_data+, without an argument:
|
|
118
|
+
#
|
|
119
|
+
# unused_associations_data = Sequel::Model.update_unused_associations_data
|
|
120
|
+
#
|
|
121
|
+
# With no argument, +update_unused_associations_data+ will get
|
|
122
|
+
# the coverage data from the coverage file, and then use that
|
|
123
|
+
# to prepare the information. You can then use the returned
|
|
124
|
+
# value the same as before to get the data on unused associations.
|
|
125
|
+
# To prevent stale coverage information, calling
|
|
126
|
+
# +update_unused_associations_data+ when using the :coverage_file
|
|
127
|
+
# plugin option will remove the coverage file by default (you can
|
|
128
|
+
# use the :keep_coverage option to prevent the deletion of the
|
|
129
|
+
# coverage file).
|
|
130
|
+
#
|
|
131
|
+
# = Automatic Usage of Unused Association Data
|
|
132
|
+
#
|
|
133
|
+
# Since it can be a pain to manually update all of your code
|
|
134
|
+
# to remove unused assocations or add options to prevent the
|
|
135
|
+
# definition of unused associations, the unused_associations
|
|
136
|
+
# plugin comes with support to take previously saved unused
|
|
137
|
+
# association data, and use it to not create unused associations,
|
|
138
|
+
# and to automatically use the appropriate options so that unused
|
|
139
|
+
# association methods are not created.
|
|
140
|
+
#
|
|
141
|
+
# To use this option, you first need to save the unused association
|
|
142
|
+
# data previously prepared. You can do this by passing an
|
|
143
|
+
# :file option when loading the plugin.
|
|
144
|
+
#
|
|
145
|
+
# Sequel::Model.plugin :unused_associations,
|
|
146
|
+
# file: 'unused_associations.json'
|
|
147
|
+
#
|
|
148
|
+
# With the :file option provided, you no longer need to use
|
|
149
|
+
# the return value of +update_unused_associations_data+, as
|
|
150
|
+
# the file will be updated with the information:
|
|
151
|
+
#
|
|
152
|
+
# Sequel::Model.update_unused_associations_data(coverage_data: cov_data)
|
|
153
|
+
#
|
|
154
|
+
# Then, to use the saved unused associations data, add the
|
|
155
|
+
# :modify_associations plugin option:
|
|
156
|
+
#
|
|
157
|
+
# Sequel::Model.plugin :unused_associations,
|
|
158
|
+
# file: 'unused_associations.json',
|
|
159
|
+
# modify_associations: true
|
|
160
|
+
#
|
|
161
|
+
# With the :modify_associations used, and the unused association
|
|
162
|
+
# data file is available, when subclasses attempt to create an
|
|
163
|
+
# unused association, the attempt will be ignored. If the
|
|
164
|
+
# subclasses attempt to create an association where not
|
|
165
|
+
# all association methods are used, the plugin will automatically
|
|
166
|
+
# set the appropriate options so that the unused association
|
|
167
|
+
# methods are not defined.
|
|
168
|
+
#
|
|
169
|
+
# When you are testing which associations are used, make sure
|
|
170
|
+
# not to set the :modify_associations plugin option, or make sure
|
|
171
|
+
# that the unused associations data file does not exist.
|
|
172
|
+
#
|
|
173
|
+
# == Automatic Usage with Combined Coverage Results
|
|
174
|
+
#
|
|
175
|
+
# If you have multiple test suites and want to automatically
|
|
176
|
+
# use the unused association data, you should provide both
|
|
177
|
+
# :file and :coverage_file options when loading the plugin:
|
|
178
|
+
#
|
|
179
|
+
# Sequel::Model.plugin :unused_associations,
|
|
180
|
+
# file: 'unused_associations.json',
|
|
181
|
+
# coverage_file: 'unused_associations_coverage.json'
|
|
182
|
+
#
|
|
183
|
+
# Then each test suite just needs to run
|
|
184
|
+
# +update_associations_coverage+ to update the coverage information:
|
|
185
|
+
#
|
|
186
|
+
# Sequel::Model.update_associations_coverage
|
|
187
|
+
#
|
|
188
|
+
# After all test suites have been run, you can run
|
|
189
|
+
# +update_unused_associations_data+ to update the unused
|
|
190
|
+
# association data file (and remove the coverage file):
|
|
191
|
+
#
|
|
192
|
+
# Sequel::Model.update_unused_associations_data
|
|
193
|
+
#
|
|
194
|
+
# Then you can add the :modify_associations plugin option to
|
|
195
|
+
# automatically use the unused association data.
|
|
196
|
+
#
|
|
197
|
+
# = Caveats
|
|
198
|
+
#
|
|
199
|
+
# Since this plugin is based on coverage information, if you do
|
|
200
|
+
# not have tests that cover all usage of associations in your
|
|
201
|
+
# application, you can end up with coverage that shows the
|
|
202
|
+
# association is not used, when it is used in code that is not
|
|
203
|
+
# covered. The output of plugin can still be useful in such cases,
|
|
204
|
+
# as long as you are manually checking it. However, you should
|
|
205
|
+
# avoid using the :modify_associations unless you have
|
|
206
|
+
# confidence that your tests cover all usage of associations
|
|
207
|
+
# in your application. You can specify the :is_used association
|
|
208
|
+
# option for any association that you know is used. If an
|
|
209
|
+
# association uses the :is_used association option, this plugin
|
|
210
|
+
# will not modify it if the :modify_associations option is used.
|
|
211
|
+
#
|
|
212
|
+
# This plugin does not handle anonymous classes. Any unused
|
|
213
|
+
# associations defined in anonymous classes will not be
|
|
214
|
+
# reported by this plugin.
|
|
215
|
+
#
|
|
216
|
+
# This plugin only considers the public instance methods the
|
|
217
|
+
# association defines, and direct access to the related
|
|
218
|
+
# association reflection via Sequel::Model.association_reflection
|
|
219
|
+
# to determine if the association was used. If the association
|
|
220
|
+
# metadata was accessed another way, it's possible this plugin
|
|
221
|
+
# will show the association as unused.
|
|
222
|
+
#
|
|
223
|
+
# As this relies on the method coverage added in Ruby 2.5, it does
|
|
224
|
+
# not work on older versions of Ruby. It also does not work on
|
|
225
|
+
# JRuby, as JRuby does not implement method coverage.
|
|
226
|
+
module UnusedAssociations
|
|
227
|
+
# Load the subclasses plugin, as the unused associations plugin
|
|
228
|
+
# is designed to handle all subclasses of the class it is loaded
|
|
229
|
+
# into.
|
|
230
|
+
def self.apply(mod, opts=OPTS)
|
|
231
|
+
mod.plugin :subclasses
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Plugin options:
|
|
235
|
+
# :coverage_file :: The file to store the coverage information,
|
|
236
|
+
# when combining coverage information from
|
|
237
|
+
# multiple test suites.
|
|
238
|
+
# :file :: The file to store and/or load the unused associations data.
|
|
239
|
+
# :modify_associations :: Whether to use the unused associations data
|
|
240
|
+
# to skip defining associations or association
|
|
241
|
+
# methods.
|
|
242
|
+
# :unused_associations_data :: The unused associations data to use if the
|
|
243
|
+
# :modify_associations is used (by default, the
|
|
244
|
+
# :modify_associations option will use the data from
|
|
245
|
+
# the file specified by the :file option). This is
|
|
246
|
+
# same data returned by the
|
|
247
|
+
# +update_unused_associations_data+ method.
|
|
248
|
+
def self.configure(mod, opts=OPTS)
|
|
249
|
+
mod.instance_exec do
|
|
250
|
+
@unused_associations_coverage_file = opts[:coverage_file]
|
|
251
|
+
@unused_associations_file = opts[:file]
|
|
252
|
+
@unused_associations_data = if opts[:modify_associations]
|
|
253
|
+
if opts[:unused_associations_data]
|
|
254
|
+
opts[:unused_associations_data]
|
|
255
|
+
elsif File.file?(opts[:file])
|
|
256
|
+
Sequel.parse_json(File.binread(opts[:file]))
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
module ClassMethods
|
|
263
|
+
# Only the data is copied to subclasses, to allow the :modify_associations
|
|
264
|
+
# plugin option to affect them. The :file and :coverage_file are not copied
|
|
265
|
+
# to subclasses, as users are expected ot call methods such as
|
|
266
|
+
# unused_associations only on the class that is loading the plugin.
|
|
267
|
+
Plugins.inherited_instance_variables(self, :@unused_associations_data=>nil)
|
|
268
|
+
|
|
269
|
+
# Synchronize access to the used association reflections.
|
|
270
|
+
def used_association_reflections
|
|
271
|
+
Sequel.synchronize{@used_association_reflections ||= {}}
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Record access to association reflections to determine which associations are not used.
|
|
275
|
+
def association_reflection(association)
|
|
276
|
+
uar = used_association_reflections
|
|
277
|
+
Sequel.synchronize{uar[association] ||= true}
|
|
278
|
+
super
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# If modifying associations, and this association is marked as not used,
|
|
282
|
+
# and the association does not include the specific :is_used option,
|
|
283
|
+
# skip defining the association.
|
|
284
|
+
def associate(type, assoc_name, opts=OPTS)
|
|
285
|
+
if !opts[:is_used] && @unused_associations_data && (data = @unused_associations_data[name]) && data[assoc_name.to_s] == 'unused'
|
|
286
|
+
return
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
super
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Setup the used_association_reflections storage before freezing
|
|
293
|
+
def freeze
|
|
294
|
+
used_association_reflections
|
|
295
|
+
super
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Parse the coverage result, and return the coverage data for the
|
|
299
|
+
# associations for descendants of this class. If the plugin
|
|
300
|
+
# uses the :coverage_file option, the existing coverage file will be loaded
|
|
301
|
+
# if present, and before the method returns, the coverage file will be updated.
|
|
302
|
+
#
|
|
303
|
+
# Options:
|
|
304
|
+
# :coverage_result :: The coverage result to use. This defaults to +Coverage.result+.
|
|
305
|
+
def update_associations_coverage(opts=OPTS)
|
|
306
|
+
coverage_result = opts[:coverage_result] || Coverage.result
|
|
307
|
+
module_mapping = {}
|
|
308
|
+
file = @unused_associations_coverage_file
|
|
309
|
+
|
|
310
|
+
coverage_data = if file && File.file?(file)
|
|
311
|
+
Sequel.parse_json(File.binread(file))
|
|
312
|
+
else
|
|
313
|
+
{}
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
([self] + descendents).each do |sc|
|
|
317
|
+
next if sc.associations.empty? || !sc.name
|
|
318
|
+
module_mapping[sc.send(:overridable_methods_module)] = sc
|
|
319
|
+
cov_data = coverage_data[sc.name] ||= {''=>[]}
|
|
320
|
+
cov_data[''].concat(sc.used_association_reflections.keys.map(&:to_s).sort).uniq!
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
coverage_result.each do |file, coverage|
|
|
324
|
+
coverage[:methods].each do |(mod, meth), times|
|
|
325
|
+
next unless sc = module_mapping[mod]
|
|
326
|
+
coverage_data[sc.name][meth.to_s] ||= 0
|
|
327
|
+
coverage_data[sc.name][meth.to_s] += times
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
if file
|
|
332
|
+
File.binwrite(file, Sequel.object_to_json(coverage_data))
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
coverage_data
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Parse the coverage data returned by #update_associations_coverage,
|
|
339
|
+
# and return data on unused associations and unused association methods.
|
|
340
|
+
#
|
|
341
|
+
# Options:
|
|
342
|
+
# :coverage_data :: The coverage data to use. If not given, it is taken
|
|
343
|
+
# from the file specified by the :coverage_file plugin option.
|
|
344
|
+
# :keep_coverage :: Do not delete the file specified by the :coverage_file plugin
|
|
345
|
+
# option, even if it exists.
|
|
346
|
+
def update_unused_associations_data(options=OPTS)
|
|
347
|
+
coverage_data = options[:coverage_data] || Sequel.parse_json(File.binread(@unused_associations_coverage_file))
|
|
348
|
+
|
|
349
|
+
unused_associations_data = {}
|
|
350
|
+
|
|
351
|
+
([self] + descendents).each do |sc|
|
|
352
|
+
next unless cov_data = coverage_data[sc.name]
|
|
353
|
+
reflection_data = cov_data[''] || []
|
|
354
|
+
|
|
355
|
+
sc.association_reflections.each do |assoc, ref|
|
|
356
|
+
# Only report associations for the class they are defined in
|
|
357
|
+
next unless ref[:model] == sc
|
|
358
|
+
|
|
359
|
+
# Do not report associations using methods_module option, because this plugin only
|
|
360
|
+
# looks in the class's overridable_methods_module
|
|
361
|
+
next if ref[:methods_module]
|
|
362
|
+
|
|
363
|
+
info = {}
|
|
364
|
+
if reflection_data.include?(assoc.to_s)
|
|
365
|
+
info[:used] = [:reflection]
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
_update_association_coverage_info(info, cov_data, ref.dataset_method, :dataset_method)
|
|
369
|
+
_update_association_coverage_info(info, cov_data, ref.association_method, :association_method)
|
|
370
|
+
|
|
371
|
+
unless ref[:orig_opts][:read_only]
|
|
372
|
+
if ref.returns_array?
|
|
373
|
+
_update_association_coverage_info(info, cov_data, ref[:add_method], :adder)
|
|
374
|
+
_update_association_coverage_info(info, cov_data, ref[:remove_method], :remover)
|
|
375
|
+
_update_association_coverage_info(info, cov_data, ref[:remove_all_method], :clearer)
|
|
376
|
+
else
|
|
377
|
+
_update_association_coverage_info(info, cov_data, ref[:setter_method], :setter)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
next if info.keys == [:missing]
|
|
382
|
+
|
|
383
|
+
if !info[:used]
|
|
384
|
+
(unused_associations_data[sc.name] ||= {})[assoc.to_s] = 'unused'
|
|
385
|
+
elsif unused = info[:unused]
|
|
386
|
+
if unused.include?(:setter) || [:adder, :remover, :clearer].all?{|k| unused.include?(k)}
|
|
387
|
+
[:setter, :adder, :remover, :clearer].each do |k|
|
|
388
|
+
unused.delete(k)
|
|
389
|
+
end
|
|
390
|
+
unused << :read_only
|
|
391
|
+
end
|
|
392
|
+
(unused_associations_data[sc.name] ||= {})[assoc.to_s] = unused.map(&:to_s)
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
if @unused_associations_file
|
|
398
|
+
File.binwrite(@unused_associations_file, Sequel.object_to_json(unused_associations_data))
|
|
399
|
+
end
|
|
400
|
+
unless options[:keep_coverage]
|
|
401
|
+
_delete_unused_associations_file(@unused_associations_coverage_file)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
unused_associations_data
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
# Return an array of unused associations. These are associations where none of the
|
|
408
|
+
# association methods are used, according to the coverage information. Each entry
|
|
409
|
+
# in the array is an array of two strings, with the first string being the class name
|
|
410
|
+
# and the second string being the association name.
|
|
411
|
+
#
|
|
412
|
+
# Options:
|
|
413
|
+
# :unused_associations_data :: The data to use for determining which associations
|
|
414
|
+
# are unused, which is returned from
|
|
415
|
+
# +update_unused_associations_data+. If not given,
|
|
416
|
+
# loads the data from the file specified by the :file
|
|
417
|
+
# plugin option.
|
|
418
|
+
def unused_associations(opts=OPTS)
|
|
419
|
+
unused_associations_data = opts[:unused_associations_data] || Sequel.parse_json(File.binread(@unused_associations_file))
|
|
420
|
+
|
|
421
|
+
unused_associations = []
|
|
422
|
+
unused_associations_data.each do |sc, associations|
|
|
423
|
+
associations.each do |assoc, unused|
|
|
424
|
+
if unused == 'unused'
|
|
425
|
+
unused_associations << [sc, assoc]
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
unused_associations
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Return an array of unused association options. These are associations some but not all
|
|
433
|
+
# of the association methods are used, according to the coverage information. Each entry
|
|
434
|
+
# in the array is an array of three elements. The first element is the class name string,
|
|
435
|
+
# the second element is the association name string, and the third element is a hash of
|
|
436
|
+
# association options that can be used in the association so it does not define methods
|
|
437
|
+
# that are not used.
|
|
438
|
+
#
|
|
439
|
+
# Options:
|
|
440
|
+
# :unused_associations_data :: The data to use for determining which associations
|
|
441
|
+
# are unused, which is returned from
|
|
442
|
+
# +update_unused_associations_data+. If not given,
|
|
443
|
+
# loads the data from the file specified by the :file
|
|
444
|
+
# plugin option.
|
|
445
|
+
def unused_association_options(opts=OPTS)
|
|
446
|
+
unused_associations_data = opts[:unused_associations_data] || Sequel.parse_json(File.binread(@unused_associations_file))
|
|
447
|
+
|
|
448
|
+
unused_association_methods = []
|
|
449
|
+
unused_associations_data.each do |sc, associations|
|
|
450
|
+
associations.each do |assoc, unused|
|
|
451
|
+
unless unused == 'unused'
|
|
452
|
+
unused_association_methods << [sc, assoc, set_unused_options_for_association({}, unused)]
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
unused_association_methods
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# Delete the unused associations coverage file and unused associations data file,
|
|
460
|
+
# if either exist.
|
|
461
|
+
def delete_unused_associations_files
|
|
462
|
+
_delete_unused_associations_file(@unused_associations_coverage_file)
|
|
463
|
+
_delete_unused_associations_file(@unused_associations_file)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
private
|
|
467
|
+
|
|
468
|
+
# Delete the given file if it exists.
|
|
469
|
+
def _delete_unused_associations_file(file)
|
|
470
|
+
if file && File.file?(file)
|
|
471
|
+
File.unlink(file)
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# Update the info hash with information on whether the given method was
|
|
476
|
+
# called, according to the coverage information.
|
|
477
|
+
def _update_association_coverage_info(info, coverage_data, meth, key)
|
|
478
|
+
type = case coverage_data[meth.to_s]
|
|
479
|
+
when 0
|
|
480
|
+
:unused
|
|
481
|
+
when Integer
|
|
482
|
+
:used
|
|
483
|
+
else
|
|
484
|
+
# Missing here means there is no coverage information for the
|
|
485
|
+
# the method, which indicates the expected method was never
|
|
486
|
+
# defined. In that case, it can be ignored.
|
|
487
|
+
:missing
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
(info[type] ||= []) << key
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
# Based on the value of the unused, update the opts hash with association
|
|
494
|
+
# options that will prevent unused association methods from being
|
|
495
|
+
# defined.
|
|
496
|
+
def set_unused_options_for_association(opts, unused)
|
|
497
|
+
opts[:read_only] = true if unused.include?('read_only')
|
|
498
|
+
opts[:no_dataset_method] = true if unused.include?('dataset_method')
|
|
499
|
+
opts[:no_association_method] = true if unused.include?('association_method')
|
|
500
|
+
opts[:adder] = nil if unused.include?('adder')
|
|
501
|
+
opts[:remover] = nil if unused.include?('remover')
|
|
502
|
+
opts[:clearer] = nil if unused.include?('clearer')
|
|
503
|
+
opts
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
# If modifying associations, and this association has unused association
|
|
507
|
+
# methods, automatically set the appropriate options so the unused association
|
|
508
|
+
# methods are not defined, unless the association explicitly uses the :is_used
|
|
509
|
+
# options.
|
|
510
|
+
def def_association(opts)
|
|
511
|
+
if !opts[:is_used] && @unused_associations_data && (data = @unused_associations_data[name]) && (unused = data[opts[:name].to_s])
|
|
512
|
+
set_unused_options_for_association(opts, unused)
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
super
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
# :nocov:
|
|
@@ -194,7 +194,11 @@ module Sequel
|
|
|
194
194
|
def validates_each(*atts, &block)
|
|
195
195
|
opts = extract_options!(atts)
|
|
196
196
|
blank_meth = db.method(:blank_object?).to_proc
|
|
197
|
-
|
|
197
|
+
i = opts[:if]
|
|
198
|
+
am = opts[:allow_missing]
|
|
199
|
+
an = opts[:allow_nil]
|
|
200
|
+
ab = opts[:allow_blank]
|
|
201
|
+
blk = if i || am || an || ab
|
|
198
202
|
if i.is_a?(Proc)
|
|
199
203
|
i = Plugins.def_sequel_method(self, "validation_class_methods_if", 0, &i)
|
|
200
204
|
end
|
|
@@ -36,6 +36,7 @@ module Sequel
|
|
|
36
36
|
# :message :: The message to use. Can be a string which is used directly, or a
|
|
37
37
|
# proc which is called. If the validation method takes a argument before the array of attributes,
|
|
38
38
|
# that argument is passed as an argument to the proc.
|
|
39
|
+
# :skip_invalid :: Do not try to validate columns that are already invalid.
|
|
39
40
|
#
|
|
40
41
|
# The default validation options for all models can be modified by
|
|
41
42
|
# overridding the Model#default_validation_helpers_options private method.
|
|
@@ -65,16 +66,13 @@ module Sequel
|
|
|
65
66
|
# integer: "is not a number"
|
|
66
67
|
#
|
|
67
68
|
# Note that if you want to support internationalization of Errors#full_messages,
|
|
68
|
-
#
|
|
69
|
+
# it is easiest to override Errors#full_message (note singular form and not plural form).
|
|
70
|
+
# Here's an example:
|
|
69
71
|
#
|
|
70
72
|
# class Sequel::Model::Errors
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
# att.is_a?(Array) ? Array(att).map!{|v| I18n.t("attributes.#{v}")} : att = I18n.t("attributes.#{att}")
|
|
75
|
-
# errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(I18n.t('errors.joiner'))} #{e}")}
|
|
76
|
-
# m
|
|
77
|
-
# end
|
|
73
|
+
# private
|
|
74
|
+
# def full_message(attribute, error_msg)
|
|
75
|
+
# "#{Array(attribute).join(I18n.t('errors.joiner'))} #{error_msg}"
|
|
78
76
|
# end
|
|
79
77
|
# end
|
|
80
78
|
module ValidationHelpers
|
|
@@ -87,6 +85,7 @@ module Sequel
|
|
|
87
85
|
:max_length=>{:message=>lambda{|max| "is longer than #{max} characters"}, :nil_message=>lambda{"is not present"}},
|
|
88
86
|
:min_length=>{:message=>lambda{|min| "is shorter than #{min} characters"}},
|
|
89
87
|
:not_null=>{:message=>lambda{"is not present"}},
|
|
88
|
+
:no_null_byte=>{:message=>lambda{"contains a null byte"}},
|
|
90
89
|
:numeric=>{:message=>lambda{"is not a number"}},
|
|
91
90
|
:operator=>{:message=>lambda{|operator, rhs| "is not #{operator} #{rhs}"}},
|
|
92
91
|
:type=>{:message=>lambda{|klass| klass.is_a?(Array) ? "is not a valid #{klass.join(" or ").downcase}" : "is not a valid #{klass.to_s.downcase}"}},
|
|
@@ -151,6 +150,11 @@ module Sequel
|
|
|
151
150
|
def validates_not_null(atts, opts=OPTS)
|
|
152
151
|
validatable_attributes_for_type(:not_null, atts, opts){|a,v,m| validation_error_message(m) if v.nil?}
|
|
153
152
|
end
|
|
153
|
+
|
|
154
|
+
# Check attribute value(s) does not contain a null ("\0", ASCII NUL) byte.
|
|
155
|
+
def validates_no_null_byte(atts, opts=OPTS)
|
|
156
|
+
validatable_attributes_for_type(:no_null_byte, atts, opts){|a,v,m| validation_error_message(m) if String === v && v.include?("\0")}
|
|
157
|
+
end
|
|
154
158
|
|
|
155
159
|
# Check attribute value(s) string representation is a valid float.
|
|
156
160
|
def validates_numeric(atts, opts=OPTS)
|
|
@@ -262,7 +266,7 @@ module Sequel
|
|
|
262
266
|
next if vals.any?(&:nil?)
|
|
263
267
|
ds.where(arr.zip(vals))
|
|
264
268
|
end
|
|
265
|
-
ds = yield(ds) if
|
|
269
|
+
ds = yield(ds) if defined?(yield)
|
|
266
270
|
unless new?
|
|
267
271
|
h = ds.joined_dataset? ? qualified_pk_hash : pk_hash
|
|
268
272
|
ds = ds.exclude(h)
|
|
@@ -281,14 +285,17 @@ module Sequel
|
|
|
281
285
|
DEFAULT_OPTIONS[type]
|
|
282
286
|
end
|
|
283
287
|
|
|
284
|
-
# Skip validating any attribute that matches one of the allow_* options
|
|
288
|
+
# Skip validating any attribute that matches one of the allow_* options,
|
|
289
|
+
# or already has an error if the skip_invalid option is given.
|
|
290
|
+
#
|
|
285
291
|
# Otherwise, yield the attribute, value, and passed option :message to
|
|
286
292
|
# the block. If the block returns anything except nil or false, add it as
|
|
287
293
|
# an error message for that attributes.
|
|
288
294
|
def validatable_attributes(atts, opts)
|
|
289
|
-
am, an, ab, m = opts.values_at(:allow_missing, :allow_nil, :allow_blank, :message)
|
|
295
|
+
am, an, ab, m, si = opts.values_at(:allow_missing, :allow_nil, :allow_blank, :message, :skip_invalid)
|
|
290
296
|
from_values = opts[:from] == :values
|
|
291
297
|
Array(atts).each do |a|
|
|
298
|
+
next if si && errors.on(a)
|
|
292
299
|
next if am && !values.has_key?(a)
|
|
293
300
|
v = from_values ? values[a] : get_column_value(a)
|
|
294
301
|
next if an && v.nil?
|
data/lib/sequel/sql.rb
CHANGED
|
@@ -467,7 +467,7 @@ module Sequel
|
|
|
467
467
|
#
|
|
468
468
|
# Sequel[1] - :a # SQL: (1 - a)
|
|
469
469
|
def expr(arg=(no_arg=true), &block)
|
|
470
|
-
if
|
|
470
|
+
if defined?(yield)
|
|
471
471
|
if no_arg
|
|
472
472
|
return expr(block)
|
|
473
473
|
else
|
|
@@ -788,8 +788,10 @@ module Sequel
|
|
|
788
788
|
def coerce(other)
|
|
789
789
|
if other.is_a?(Numeric)
|
|
790
790
|
[SQL::NumericExpression.new(:NOOP, other), self]
|
|
791
|
-
|
|
791
|
+
elsif defined?(super)
|
|
792
792
|
super
|
|
793
|
+
else
|
|
794
|
+
[self, other]
|
|
793
795
|
end
|
|
794
796
|
end
|
|
795
797
|
|
|
@@ -1086,11 +1088,23 @@ module Sequel
|
|
|
1086
1088
|
def self.from_value_pair(l, r)
|
|
1087
1089
|
case r
|
|
1088
1090
|
when Range
|
|
1089
|
-
|
|
1091
|
+
unless r.begin.nil?
|
|
1092
|
+
begin_expr = new(:>=, l, r.begin)
|
|
1093
|
+
end
|
|
1090
1094
|
unless r.end.nil?
|
|
1091
|
-
|
|
1095
|
+
end_expr = new(r.exclude_end? ? :< : :<=, l, r.end)
|
|
1096
|
+
end
|
|
1097
|
+
if begin_expr
|
|
1098
|
+
if end_expr
|
|
1099
|
+
new(:AND, begin_expr, end_expr)
|
|
1100
|
+
else
|
|
1101
|
+
begin_expr
|
|
1102
|
+
end
|
|
1103
|
+
elsif end_expr
|
|
1104
|
+
end_expr
|
|
1105
|
+
else
|
|
1106
|
+
new(:'=', 1, 1)
|
|
1092
1107
|
end
|
|
1093
|
-
expr
|
|
1094
1108
|
when ::Array
|
|
1095
1109
|
r = r.dup.freeze unless r.frozen?
|
|
1096
1110
|
new(:IN, l, r)
|
|
@@ -1303,6 +1317,7 @@ module Sequel
|
|
|
1303
1317
|
CURRENT_DATE = Constant.new(:CURRENT_DATE)
|
|
1304
1318
|
CURRENT_TIME = Constant.new(:CURRENT_TIME)
|
|
1305
1319
|
CURRENT_TIMESTAMP = Constant.new(:CURRENT_TIMESTAMP)
|
|
1320
|
+
DEFAULT = Constant.new(:DEFAULT)
|
|
1306
1321
|
SQLTRUE = TRUE = BooleanConstant.new(true)
|
|
1307
1322
|
SQLFALSE = FALSE = BooleanConstant.new(false)
|
|
1308
1323
|
NULL = BooleanConstant.new(nil)
|