ibm_db 5.6.1 → 5.7.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/ext/Makefile +13 -9
- data/ext/extconf.rb +176 -110
- data/ext/ibm_db.c +60 -0
- data/ext/ibm_db.o +0 -0
- data/ext/ibm_db.so +0 -0
- data/ext/mkmf.log +6 -6
- data/ext/ruby_ibm_db_cli.c +14 -10
- data/ext/ruby_ibm_db_cli.h +4 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/lib/IBM_DB.rb +2 -2
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
- data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
- data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
- data/test/activejob/destroy_association_async_job_test.rb +62 -0
- data/test/activejob/destroy_association_async_test.rb +147 -11
- data/test/activejob/job_runtime_test.rb +41 -0
- data/test/activejob/unloadable_base_job.rb +3 -0
- data/test/cases/active_record_schema_test.rb +196 -0
- data/test/cases/active_record_test.rb +21 -0
- data/test/cases/adapter_prevent_writes_test.rb +26 -202
- data/test/cases/adapter_test.rb +592 -82
- data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
- data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
- data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
- data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
- data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
- data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
- data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
- data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
- data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
- data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
- data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
- data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
- data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
- data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
- data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
- data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
- data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
- data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
- data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
- data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
- data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
- data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
- data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
- data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
- data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
- data/test/cases/adapters/postgresql/array_test.rb +6 -6
- data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
- data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
- data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
- data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
- data/test/cases/adapters/postgresql/citext_test.rb +7 -1
- data/test/cases/adapters/postgresql/collation_test.rb +1 -1
- data/test/cases/adapters/postgresql/composite_test.rb +1 -1
- data/test/cases/adapters/postgresql/connection_test.rb +43 -36
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
- data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
- data/test/cases/adapters/postgresql/date_test.rb +2 -2
- data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
- data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
- data/test/cases/adapters/postgresql/domain_test.rb +1 -1
- data/test/cases/adapters/postgresql/enum_test.rb +208 -8
- data/test/cases/adapters/postgresql/explain_test.rb +25 -6
- data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
- data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
- data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
- data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
- data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
- data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
- data/test/cases/adapters/postgresql/integer_test.rb +1 -1
- data/test/cases/adapters/postgresql/interval_test.rb +9 -17
- data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
- data/test/cases/adapters/postgresql/json_test.rb +5 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
- data/test/cases/adapters/postgresql/money_test.rb +17 -9
- data/test/cases/adapters/postgresql/network_test.rb +13 -1
- data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
- data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
- data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
- data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
- data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
- data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
- data/test/cases/adapters/postgresql/range_test.rb +185 -21
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
- data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
- data/test/cases/adapters/postgresql/schema_test.rb +270 -20
- data/test/cases/adapters/postgresql/serial_test.rb +5 -5
- data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
- data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
- data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
- data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
- data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
- data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
- data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
- data/test/cases/adapters/postgresql/xml_test.rb +1 -1
- data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
- data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
- data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
- data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
- data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
- data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
- data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
- data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
- data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
- data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
- data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
- data/test/cases/aggregations_test.rb +16 -0
- data/test/cases/annotate_test.rb +14 -12
- data/test/cases/arel/attributes/attribute_test.rb +86 -47
- data/test/cases/arel/collectors/bind_test.rb +1 -1
- data/test/cases/arel/collectors/composite_test.rb +11 -1
- data/test/cases/arel/collectors/sql_string_test.rb +1 -1
- data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
- data/test/cases/arel/delete_manager_test.rb +0 -6
- data/test/cases/arel/factory_methods_test.rb +45 -0
- data/test/cases/arel/insert_manager_test.rb +1 -7
- data/test/cases/arel/nodes/as_test.rb +12 -0
- data/test/cases/arel/nodes/ascending_test.rb +1 -1
- data/test/cases/arel/nodes/bin_test.rb +1 -1
- data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
- data/test/cases/arel/nodes/cte_test.rb +46 -0
- data/test/cases/arel/nodes/descending_test.rb +1 -1
- data/test/cases/arel/nodes/equality_test.rb +3 -3
- data/test/cases/arel/nodes/filter_test.rb +37 -0
- data/test/cases/arel/nodes/fragments_test.rb +38 -0
- data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
- data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
- data/test/cases/arel/nodes/node_test.rb +1 -1
- data/test/cases/arel/nodes/or_test.rb +2 -2
- data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
- data/test/cases/arel/nodes/table_alias_test.rb +12 -0
- data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
- data/test/cases/arel/nodes/update_statement_test.rb +4 -0
- data/test/cases/arel/nodes_test.rb +3 -2
- data/test/cases/arel/select_manager_test.rb +12 -12
- data/test/cases/arel/support/fake_record.rb +22 -17
- data/test/cases/arel/table_test.rb +15 -25
- data/test/cases/arel/update_manager_test.rb +51 -6
- data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
- data/test/cases/arel/visitors/dot_test.rb +177 -2
- data/test/cases/arel/visitors/mysql_test.rb +49 -1
- data/test/cases/arel/visitors/postgres_test.rb +1 -31
- data/test/cases/arel/visitors/sqlite_test.rb +1 -1
- data/test/cases/arel/visitors/to_sql_test.rb +330 -20
- data/test/cases/assertions/query_assertions_test.rb +136 -0
- data/test/cases/associations/belongs_to_associations_test.rb +502 -41
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
- data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
- data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
- data/test/cases/associations/eager_singularization_test.rb +1 -1
- data/test/cases/associations/eager_test.rb +255 -93
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
- data/test/cases/associations/has_many_associations_test.rb +282 -72
- data/test/cases/associations/has_many_through_associations_test.rb +172 -45
- data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
- data/test/cases/associations/has_one_associations_test.rb +160 -29
- data/test/cases/associations/has_one_through_associations_test.rb +64 -15
- data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
- data/test/cases/associations/inner_join_association_test.rb +36 -6
- data/test/cases/associations/inverse_associations_test.rb +177 -40
- data/test/cases/associations/join_model_test.rb +17 -12
- data/test/cases/associations/left_outer_join_association_test.rb +14 -3
- data/test/cases/associations/nested_error_test.rb +116 -0
- data/test/cases/associations/nested_through_associations_test.rb +54 -19
- data/test/cases/associations/required_test.rb +1 -1
- data/test/cases/associations_test.rb +1278 -21
- data/test/cases/asynchronous_queries_test.rb +310 -0
- data/test/cases/attribute_methods/read_test.rb +6 -0
- data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
- data/test/cases/attribute_methods_test.rb +565 -46
- data/test/cases/attributes_test.rb +42 -1
- data/test/cases/autosave_association_test.rb +645 -92
- data/test/cases/base_prevent_writes_test.rb +28 -159
- data/test/cases/base_test.rb +434 -209
- data/test/cases/batches_test.rb +441 -57
- data/test/cases/binary_test.rb +31 -0
- data/test/cases/bind_parameter_test.rb +107 -16
- data/test/cases/cache_key_test.rb +7 -7
- data/test/cases/calculations_test.rb +541 -110
- data/test/cases/callbacks_test.rb +0 -1
- data/test/cases/clone_test.rb +5 -4
- data/test/cases/coders/yaml_column_test.rb +97 -2
- data/test/cases/collection_cache_key_test.rb +24 -16
- data/test/cases/column_alias_test.rb +2 -8
- data/test/cases/column_definition_test.rb +12 -3
- data/test/cases/comment_test.rb +23 -26
- data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
- data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
- data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
- data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
- data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
- data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
- data/test/cases/connection_adapters/registration_test.rb +98 -0
- data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
- data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
- data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
- data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
- data/test/cases/connection_handling_test.rb +210 -0
- data/test/cases/connection_management_test.rb +44 -7
- data/test/cases/connection_pool_test.rb +466 -99
- data/test/cases/core_test.rb +167 -9
- data/test/cases/counter_cache_test.rb +129 -2
- data/test/cases/custom_locking_test.rb +3 -3
- data/test/cases/database_configurations/hash_config_test.rb +149 -13
- data/test/cases/database_configurations/resolver_test.rb +14 -10
- data/test/cases/database_configurations/url_config_test.rb +53 -0
- data/test/cases/database_configurations_test.rb +86 -43
- data/test/cases/database_selector_test.rb +30 -8
- data/test/cases/database_statements_test.rb +10 -14
- data/test/cases/date_time_precision_test.rb +141 -11
- data/test/cases/date_time_test.rb +19 -1
- data/test/cases/defaults_test.rb +107 -41
- data/test/cases/delegated_type_test.rb +69 -9
- data/test/cases/dirty_test.rb +82 -25
- data/test/cases/disconnected_test.rb +10 -9
- data/test/cases/dup_test.rb +26 -6
- data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
- data/test/cases/encryption/cipher_test.rb +65 -0
- data/test/cases/encryption/concurrency_test.rb +27 -0
- data/test/cases/encryption/config_test.rb +21 -0
- data/test/cases/encryption/configurable_test.rb +93 -0
- data/test/cases/encryption/contexts_test.rb +105 -0
- data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
- data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
- data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
- data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
- data/test/cases/encryption/encryptable_record_test.rb +470 -0
- data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
- data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
- data/test/cases/encryption/encryption_schemes_test.rb +240 -0
- data/test/cases/encryption/encryptor_test.rb +113 -0
- data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
- data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
- data/test/cases/encryption/helper.rb +152 -0
- data/test/cases/encryption/key_generator_test.rb +55 -0
- data/test/cases/encryption/key_provider_test.rb +57 -0
- data/test/cases/encryption/key_test.rb +17 -0
- data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
- data/test/cases/encryption/message_serializer_test.rb +82 -0
- data/test/cases/encryption/message_test.rb +43 -0
- data/test/cases/encryption/null_encryptor_test.rb +21 -0
- data/test/cases/encryption/properties_test.rb +69 -0
- data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
- data/test/cases/encryption/scheme_test.rb +58 -0
- data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
- data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
- data/test/cases/enum_test.rb +374 -72
- data/test/cases/errors_test.rb +7 -4
- data/test/cases/excluding_test.rb +116 -0
- data/test/cases/explain_subscriber_test.rb +6 -1
- data/test/cases/explain_test.rb +119 -10
- data/test/cases/filter_attributes_test.rb +7 -14
- data/test/cases/finder_respond_to_test.rb +3 -3
- data/test/cases/finder_test.rb +357 -72
- data/test/cases/fixture_set/file_test.rb +9 -0
- data/test/cases/fixtures_test.rb +426 -190
- data/test/cases/helper.rb +66 -192
- data/test/cases/hot_compatibility_test.rb +10 -10
- data/test/cases/inheritance_test.rb +51 -61
- data/test/cases/inherited_test.rb +40 -0
- data/test/cases/insert_all_test.rb +419 -9
- data/test/cases/instrumentation_test.rb +202 -30
- data/test/cases/integration_test.rb +25 -7
- data/test/cases/invalid_connection_test.rb +5 -5
- data/test/cases/invertible_migration_test.rb +108 -24
- data/test/cases/json_attribute_test.rb +1 -0
- data/test/cases/json_serialization_test.rb +5 -5
- data/test/cases/json_shared_test_cases.rb +5 -9
- data/test/cases/locking_test.rb +67 -31
- data/test/cases/log_subscriber_test.rb +17 -15
- data/test/cases/marshal_serialization_test.rb +78 -5
- data/test/cases/message_pack_test.rb +91 -0
- data/test/cases/migration/change_schema_test.rb +77 -46
- data/test/cases/migration/change_table_test.rb +129 -114
- data/test/cases/migration/check_constraint_test.rb +192 -10
- data/test/cases/migration/column_attributes_test.rb +4 -9
- data/test/cases/migration/column_positioning_test.rb +2 -2
- data/test/cases/migration/columns_test.rb +118 -4
- data/test/cases/migration/command_recorder_test.rb +181 -14
- data/test/cases/migration/compatibility_test.rb +883 -196
- data/test/cases/migration/create_join_table_test.rb +8 -1
- data/test/cases/migration/exclusion_constraint_test.rb +192 -0
- data/test/cases/migration/foreign_key_test.rb +356 -14
- data/test/cases/migration/helper.rb +4 -1
- data/test/cases/migration/index_test.rb +67 -2
- data/test/cases/migration/invalid_options_test.rb +129 -0
- data/test/cases/migration/logger_test.rb +7 -4
- data/test/cases/migration/pending_migrations_test.rb +103 -60
- data/test/cases/migration/references_foreign_key_test.rb +73 -4
- data/test/cases/migration/references_index_test.rb +25 -27
- data/test/cases/migration/references_statements_test.rb +27 -3
- data/test/cases/migration/rename_table_test.rb +39 -54
- data/test/cases/migration/schema_definitions_test.rb +109 -0
- data/test/cases/migration/unique_constraint_test.rb +248 -0
- data/test/cases/migration_test.rb +677 -220
- data/test/cases/migrator_test.rb +102 -75
- data/test/cases/multi_db_migrator_test.rb +55 -34
- data/test/cases/multiparameter_attributes_test.rb +26 -29
- data/test/cases/multiple_db_test.rb +42 -19
- data/test/cases/nested_attributes_test.rb +124 -6
- data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
- data/test/cases/normalized_attribute_test.rb +117 -0
- data/test/cases/null_relation_test.rb +35 -2
- data/test/cases/persistence/reload_association_cache_test.rb +20 -0
- data/test/cases/persistence_test.rb +629 -22
- data/test/cases/pooled_connections_test.rb +57 -56
- data/test/cases/prepared_statement_status_test.rb +8 -3
- data/test/cases/primary_class_test.rb +134 -0
- data/test/cases/primary_keys_test.rb +171 -55
- data/test/cases/query_cache_test.rb +558 -263
- data/test/cases/query_logs_test.rb +293 -0
- data/test/cases/quoting_test.rb +39 -72
- data/test/cases/readonly_test.rb +50 -12
- data/test/cases/reaper_test.rb +22 -6
- data/test/cases/reflection_test.rb +207 -9
- data/test/cases/relation/and_test.rb +43 -0
- data/test/cases/relation/delegation_test.rb +32 -5
- data/test/cases/relation/delete_all_test.rb +27 -6
- data/test/cases/relation/field_ordered_values_test.rb +128 -0
- data/test/cases/relation/load_async_test.rb +650 -0
- data/test/cases/relation/merging_test.rb +80 -109
- data/test/cases/relation/mutation_test.rb +12 -7
- data/test/cases/relation/or_test.rb +11 -8
- data/test/cases/relation/order_test.rb +90 -0
- data/test/cases/relation/predicate_builder_test.rb +21 -6
- data/test/cases/relation/select_test.rb +162 -3
- data/test/cases/relation/structural_compatibility_test.rb +38 -0
- data/test/cases/relation/update_all_test.rb +81 -27
- data/test/cases/relation/where_chain_test.rb +190 -3
- data/test/cases/relation/where_clause_test.rb +43 -1
- data/test/cases/relation/where_test.rb +95 -7
- data/test/cases/relation/with_test.rb +165 -0
- data/test/cases/relation_test.rb +42 -37
- data/test/cases/relations_test.rb +436 -138
- data/test/cases/reload_models_test.rb +18 -14
- data/test/cases/reserved_word_test.rb +2 -1
- data/test/cases/result_test.rb +14 -22
- data/test/cases/sanitize_test.rb +89 -27
- data/test/cases/schema_dumper_test.rb +535 -62
- data/test/cases/scoping/default_scoping_test.rb +219 -35
- data/test/cases/scoping/named_scoping_test.rb +25 -46
- data/test/cases/scoping/relation_scoping_test.rb +112 -4
- data/test/cases/secure_password_test.rb +108 -0
- data/test/cases/secure_token_test.rb +72 -0
- data/test/cases/serialization_test.rb +1 -1
- data/test/cases/serialized_attribute_test.rb +305 -60
- data/test/cases/shard_keys_test.rb +125 -0
- data/test/cases/shard_selector_test.rb +45 -0
- data/test/cases/signed_id_test.rb +57 -5
- data/test/cases/statement_cache_test.rb +31 -30
- data/test/cases/statement_invalid_test.rb +8 -4
- data/test/cases/store_test.rb +73 -9
- data/test/cases/strict_loading_test.rb +327 -13
- data/test/cases/table_metadata_test.rb +16 -0
- data/test/cases/tasks/database_tasks_test.rb +517 -244
- data/test/cases/test_case.rb +254 -60
- data/test/cases/test_case_test.rb +69 -0
- data/test/cases/test_databases_test.rb +7 -3
- data/test/cases/test_fixtures_test.rb +19 -40
- data/test/cases/time_precision_test.rb +17 -5
- data/test/cases/timestamp_test.rb +124 -16
- data/test/cases/token_for_test.rb +165 -0
- data/test/cases/touch_later_test.rb +43 -1
- data/test/cases/transaction_callbacks_test.rb +325 -8
- data/test/cases/transaction_instrumentation_test.rb +453 -0
- data/test/cases/transaction_isolation_test.rb +12 -8
- data/test/cases/transactions_test.rb +629 -112
- data/test/cases/type/date_time_test.rb +7 -1
- data/test/cases/type/time_test.rb +9 -0
- data/test/cases/type/type_map_test.rb +108 -73
- data/test/cases/type/unsigned_integer_test.rb +12 -0
- data/test/cases/type_caster/connection_test.rb +19 -0
- data/test/cases/type_test.rb +1 -1
- data/test/cases/unconnected_test.rb +7 -7
- data/test/cases/unsafe_raw_sql_test.rb +39 -8
- data/test/cases/validations/absence_validation_test.rb +1 -1
- data/test/cases/validations/association_validation_test.rb +25 -3
- data/test/cases/validations/numericality_validation_test.rb +3 -9
- data/test/cases/validations/presence_validation_test.rb +1 -1
- data/test/cases/validations/uniqueness_validation_test.rb +280 -40
- data/test/cases/validations_test.rb +2 -2
- data/test/cases/view_test.rb +33 -22
- data/test/cases/yaml_serialization_test.rb +23 -17
- data/test/config.example.yml +58 -56
- data/test/config.rb +1 -0
- data/test/fixtures/1_need_quoting.yml +2 -0
- data/test/fixtures/accounts.yml +5 -0
- data/test/fixtures/aircrafts.yml +7 -0
- data/test/fixtures/book_identifiers.yml +11 -0
- data/test/fixtures/books.yml +5 -4
- data/test/fixtures/cake_designers.yml +5 -0
- data/test/fixtures/cars.yml +6 -0
- data/test/fixtures/chefs.yml +5 -0
- data/test/fixtures/clothing_items.yml +23 -0
- data/test/fixtures/clubs.yml +1 -1
- data/test/fixtures/comments.yml +2 -1
- data/test/fixtures/cpk_authors.yml +8 -0
- data/test/fixtures/cpk_books.yml +21 -0
- data/test/fixtures/cpk_order_agreements.yml +13 -0
- data/test/fixtures/cpk_order_tags.yml +15 -0
- data/test/fixtures/cpk_orders.yml +11 -0
- data/test/fixtures/cpk_posts.yml +12 -0
- data/test/fixtures/cpk_reviews.yml +13 -0
- data/test/fixtures/cpk_tags.yml +11 -0
- data/test/fixtures/drink_designers.yml +5 -0
- data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
- data/test/fixtures/encrypted_books.yml +4 -0
- data/test/fixtures/fk_object_to_point_to.yml +2 -0
- data/test/fixtures/memberships.yml +15 -15
- data/test/fixtures/paragraphs.yml +5 -0
- data/test/fixtures/parrots.yml +4 -0
- data/test/fixtures/people.yml +2 -0
- data/test/fixtures/pirates.yml +2 -2
- data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
- data/test/fixtures/references.yml +3 -3
- data/test/fixtures/sharded_blog_posts.yml +14 -0
- data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
- data/test/fixtures/sharded_blogs.yml +8 -0
- data/test/fixtures/sharded_comments.yml +22 -0
- data/test/fixtures/sharded_tags.yml +34 -0
- data/test/fixtures/sponsors.yml +2 -2
- data/test/fixtures/topics.yml +1 -0
- data/test/fixtures/treasures.yml +4 -0
- data/test/fixtures/virtual_columns.yml +5 -0
- data/test/fixtures/warehouse_things.yml +1 -1
- data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
- data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
- data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
- data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
- data/test/migrations/scope/1_unscoped.rb +7 -0
- data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
- data/test/models/admin/user.rb +2 -0
- data/test/models/admin/user_json.rb +48 -0
- data/test/models/attachment.rb +7 -0
- data/test/models/author.rb +70 -3
- data/test/models/author_encrypted.rb +16 -0
- data/test/models/bird.rb +1 -1
- data/test/models/book.rb +18 -11
- data/test/models/book_destroy_async.rb +1 -1
- data/test/models/book_encrypted.rb +106 -0
- data/test/models/book_identifier.rb +5 -0
- data/test/models/branch.rb +11 -0
- data/test/models/bulb.rb +1 -1
- data/test/models/car.rb +8 -1
- data/test/models/cat.rb +1 -1
- data/test/models/category.rb +3 -1
- data/test/models/chat_message.rb +8 -0
- data/test/models/chef.rb +52 -0
- data/test/models/clothing_item.rb +12 -0
- data/test/models/club.rb +4 -1
- data/test/models/comment.rb +7 -4
- data/test/models/comment_overlapping_counter_cache.rb +15 -0
- data/test/models/company.rb +16 -2
- data/test/models/computer.rb +1 -0
- data/test/models/contact.rb +3 -3
- data/test/models/contract.rb +5 -1
- data/test/models/cpk/author.rb +9 -0
- data/test/models/cpk/book.rb +55 -0
- data/test/models/cpk/book_destroy_async.rb +9 -0
- data/test/models/cpk/car.rb +9 -0
- data/test/models/cpk/car_review.rb +9 -0
- data/test/models/cpk/chapter.rb +16 -0
- data/test/models/cpk/chapter_destroy_async.rb +10 -0
- data/test/models/cpk/comment.rb +9 -0
- data/test/models/cpk/order.rb +55 -0
- data/test/models/cpk/order_agreement.rb +10 -0
- data/test/models/cpk/order_tag.rb +10 -0
- data/test/models/cpk/post.rb +10 -0
- data/test/models/cpk/posts_tag.rb +10 -0
- data/test/models/cpk/review.rb +9 -0
- data/test/models/cpk/tag.rb +10 -0
- data/test/models/cpk.rb +15 -0
- data/test/models/customer.rb +3 -1
- data/test/models/destroy_async_parent.rb +1 -1
- data/test/models/developer.rb +44 -3
- data/test/models/discount.rb +4 -0
- data/test/models/drink_designer.rb +1 -0
- data/test/models/editor.rb +8 -0
- data/test/models/editorship.rb +6 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +6 -1
- data/test/models/essay_destroy_async.rb +1 -0
- data/test/models/eye.rb +87 -21
- data/test/models/face.rb +1 -1
- data/test/models/friendship.rb +3 -0
- data/test/models/hardback.rb +7 -0
- data/test/models/hotel.rb +2 -0
- data/test/models/human.rb +2 -2
- data/test/models/invoice.rb +2 -1
- data/test/models/invokes_an_undefined_method.rb +5 -0
- data/test/models/line_item.rb +6 -0
- data/test/models/member.rb +9 -4
- data/test/models/membership.rb +2 -2
- data/test/models/message.rb +2 -1
- data/test/models/need_quoting.rb +5 -0
- data/test/models/paragraph.rb +5 -0
- data/test/models/parrot.rb +6 -3
- data/test/models/person.rb +7 -4
- data/test/models/pirate.rb +4 -1
- data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
- data/test/models/post.rb +65 -2
- data/test/models/post_encrypted.rb +15 -0
- data/test/models/post_with_prefetched_pk.rb +15 -0
- data/test/models/project.rb +1 -0
- data/test/models/publication.rb +16 -0
- data/test/models/raises_argument_error.rb +5 -0
- data/test/models/raises_no_method_error.rb +5 -0
- data/test/models/recipient.rb +5 -0
- data/test/models/reference.rb +1 -1
- data/test/models/reply.rb +1 -1
- data/test/models/room.rb +3 -0
- data/test/models/sharded/blog.rb +12 -0
- data/test/models/sharded/blog_post.rb +17 -0
- data/test/models/sharded/blog_post_destroy_async.rb +14 -0
- data/test/models/sharded/blog_post_tag.rb +11 -0
- data/test/models/sharded/blog_post_with_revision.rb +11 -0
- data/test/models/sharded/comment.rb +12 -0
- data/test/models/sharded/comment_destroy_async.rb +12 -0
- data/test/models/sharded/tag.rb +11 -0
- data/test/models/sharded.rb +8 -0
- data/test/models/ship.rb +1 -1
- data/test/models/shipping_line.rb +11 -0
- data/test/models/subscriber.rb +1 -0
- data/test/models/subscription.rb +3 -1
- data/test/models/too_long_table_name.rb +5 -0
- data/test/models/topic.rb +3 -1
- data/test/models/traffic_light.rb +2 -2
- data/test/models/traffic_light_encrypted.rb +21 -0
- data/test/models/translation.rb +9 -0
- data/test/models/treasure.rb +1 -1
- data/test/models/tyre.rb +1 -1
- data/test/models/user.rb +16 -0
- data/test/models/user_with_invalid_relation.rb +28 -0
- data/test/models/uuid_comment.rb +5 -0
- data/test/models/uuid_entry.rb +5 -0
- data/test/models/uuid_message.rb +5 -0
- data/test/models/zine.rb +2 -1
- data/test/schema/mysql2_specific_schema.rb +26 -12
- data/test/schema/postgresql_specific_schema.rb +121 -13
- data/test/schema/schema.rb +361 -103
- data/test/schema/sqlite_specific_schema.rb +17 -6
- data/test/schema/trilogy_specific_schema.rb +96 -0
- data/test/support/adapter_helper.rb +104 -0
- data/test/support/async_helper.rb +15 -0
- data/test/support/config.rb +1 -1
- data/test/support/connection.rb +14 -2
- data/test/support/ddl_helper.rb +1 -1
- data/test/support/fake_adapter.rb +42 -0
- data/test/support/load_schema_helper.rb +22 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
- data/test/support/schema_dumping_helper.rb +15 -9
- data/test/support/tools.rb +37 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
- metadata +247 -15
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "pp"
|
|
3
4
|
require "cases/helper"
|
|
4
5
|
require "models/computer"
|
|
5
6
|
require "models/developer"
|
|
@@ -9,6 +10,7 @@ require "models/categorization"
|
|
|
9
10
|
require "models/category"
|
|
10
11
|
require "models/post"
|
|
11
12
|
require "models/author"
|
|
13
|
+
require "models/book"
|
|
12
14
|
require "models/comment"
|
|
13
15
|
require "models/tag"
|
|
14
16
|
require "models/tagging"
|
|
@@ -26,10 +28,26 @@ require "models/parrot"
|
|
|
26
28
|
require "models/bird"
|
|
27
29
|
require "models/treasure"
|
|
28
30
|
require "models/price_estimate"
|
|
31
|
+
require "models/invoice"
|
|
32
|
+
require "models/discount"
|
|
33
|
+
require "models/line_item"
|
|
34
|
+
require "models/shipping_line"
|
|
35
|
+
require "models/essay"
|
|
36
|
+
require "models/member"
|
|
37
|
+
require "models/membership"
|
|
38
|
+
require "models/sharded"
|
|
39
|
+
require "models/cpk"
|
|
40
|
+
require "models/member_detail"
|
|
41
|
+
require "models/organization"
|
|
42
|
+
require "models/dog"
|
|
43
|
+
require "models/other_dog"
|
|
44
|
+
|
|
29
45
|
|
|
30
46
|
class AssociationsTest < ActiveRecord::TestCase
|
|
31
47
|
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
|
|
32
|
-
:computers, :people, :readers, :authors, :author_addresses, :author_favorites
|
|
48
|
+
:computers, :people, :readers, :authors, :author_addresses, :author_favorites,
|
|
49
|
+
:comments, :posts, :sharded_blogs, :sharded_blog_posts, :sharded_comments, :sharded_tags, :sharded_blog_posts_tags,
|
|
50
|
+
:cpk_orders, :cpk_books, :cpk_reviews
|
|
33
51
|
|
|
34
52
|
def test_eager_loading_should_not_change_count_of_children
|
|
35
53
|
liquid = Liquid.create(name: "salty")
|
|
@@ -63,6 +81,16 @@ class AssociationsTest < ActiveRecord::TestCase
|
|
|
63
81
|
assert_equal "Deck", ship.parts[0].name
|
|
64
82
|
end
|
|
65
83
|
|
|
84
|
+
def test_loading_cpk_association_when_persisted_and_in_memory_differ
|
|
85
|
+
order = Cpk::Order.create!(id: [1, 2], status: "paid")
|
|
86
|
+
book = order.books.create!(id: [3, 4], title: "Book")
|
|
87
|
+
|
|
88
|
+
Cpk::Book.find(book.id).update_columns(title: "A different title")
|
|
89
|
+
order.books.load
|
|
90
|
+
|
|
91
|
+
assert_equal [3, 4], book.id
|
|
92
|
+
end
|
|
93
|
+
|
|
66
94
|
def test_include_with_order_works
|
|
67
95
|
assert_nothing_raised { Account.all.merge!(order: "id", includes: :firm).first }
|
|
68
96
|
assert_nothing_raised { Account.all.merge!(order: :id, includes: :firm).first }
|
|
@@ -86,13 +114,13 @@ class AssociationsTest < ActiveRecord::TestCase
|
|
|
86
114
|
firm = Firm.new("name" => "A New Firm, Inc")
|
|
87
115
|
firm.save
|
|
88
116
|
firm.clients.each { } # forcing to load all clients
|
|
89
|
-
|
|
117
|
+
assert_predicate firm.clients, :empty?, "New firm shouldn't have client objects"
|
|
90
118
|
assert_equal 0, firm.clients.size, "New firm should have 0 clients"
|
|
91
119
|
|
|
92
120
|
client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
|
|
93
121
|
client.save
|
|
94
122
|
|
|
95
|
-
|
|
123
|
+
assert_predicate firm.clients, :empty?, "New firm should have cached no client objects"
|
|
96
124
|
assert_equal 0, firm.clients.size, "New firm should have cached 0 clients count"
|
|
97
125
|
|
|
98
126
|
firm.clients.reload
|
|
@@ -115,10 +143,362 @@ class AssociationsTest < ActiveRecord::TestCase
|
|
|
115
143
|
firm = companies(:first_firm)
|
|
116
144
|
assert_equal [:foo], firm.association_with_references.references_values
|
|
117
145
|
end
|
|
146
|
+
|
|
147
|
+
def test_belongs_to_a_model_with_composite_foreign_key_finds_associated_record
|
|
148
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
149
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
150
|
+
|
|
151
|
+
assert_equal(blog_post, comment.blog_post)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_belongs_to_a_model_with_composite_primary_key_sets_inverse_of
|
|
155
|
+
order = cpk_orders(:cpk_groceries_order_1)
|
|
156
|
+
store_id, _order_id = order.id
|
|
157
|
+
book = order.books.create!(id: [store_id, 4], title: "Book")
|
|
158
|
+
|
|
159
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
160
|
+
assert_equal book.order, book.order.books.first.order
|
|
161
|
+
else
|
|
162
|
+
assert_same book.order, book.order.books.first.order
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def test_belongs_to_a_cpk_model_by_id_attribute
|
|
167
|
+
order = cpk_orders(:cpk_groceries_order_1)
|
|
168
|
+
_order_shop_id, order_id = order.id
|
|
169
|
+
agreement = Cpk::OrderAgreement.create(order_id: order_id, signature: "signed")
|
|
170
|
+
|
|
171
|
+
assert_equal(order, agreement.order)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_belongs_to_a_model_with_composite_primary_key_uses_composite_pk_in_sql
|
|
175
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
176
|
+
|
|
177
|
+
sql = capture_sql do
|
|
178
|
+
comment.blog_post
|
|
179
|
+
end.first
|
|
180
|
+
|
|
181
|
+
assert_match(/(?:#{Regexp.escape(quote_table_name("sharded_blog_posts.blog_id"))}|sharded_blog_posts\.blog_id) =/, sql)
|
|
182
|
+
assert_match(/(?:#{Regexp.escape(quote_table_name("sharded_blog_posts.id"))}|sharded_blog_posts\.id) =/, sql)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def test_querying_by_whole_associated_records_using_query_constraints
|
|
186
|
+
comments = [sharded_comments(:great_comment_blog_post_one), sharded_comments(:great_comment_blog_post_two)]
|
|
187
|
+
|
|
188
|
+
blog_posts = Sharded::BlogPost.where(comments: comments).to_a
|
|
189
|
+
|
|
190
|
+
expected_posts = [sharded_blog_posts(:great_post_blog_one), sharded_blog_posts(:great_post_blog_two)]
|
|
191
|
+
assert_equal(expected_posts.map(&:id).sort, blog_posts.map(&:id).sort)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_querying_by_single_associated_record_works_using_query_constraints
|
|
195
|
+
comments = [sharded_comments(:great_comment_blog_post_one), sharded_comments(:great_comment_blog_post_two)]
|
|
196
|
+
|
|
197
|
+
blog_posts = Sharded::BlogPost.where(comments: comments.last).to_a
|
|
198
|
+
|
|
199
|
+
expected_posts = [sharded_blog_posts(:great_post_blog_two)]
|
|
200
|
+
assert_equal(expected_posts.map(&:id).sort, blog_posts.map(&:id).sort)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def test_querying_by_relation_with_composite_key
|
|
204
|
+
expected_posts = [sharded_blog_posts(:great_post_blog_one), sharded_blog_posts(:great_post_blog_two)]
|
|
205
|
+
|
|
206
|
+
blog_posts = Sharded::BlogPost.where(comments: Sharded::Comment.where(body: "I really enjoyed the post!")).to_a
|
|
207
|
+
|
|
208
|
+
assert_equal(expected_posts.map(&:id).sort, blog_posts.map(&:id).sort)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def test_has_many_association_with_composite_foreign_key_loads_records
|
|
212
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
213
|
+
|
|
214
|
+
comments = blog_post.comments.to_a
|
|
215
|
+
assert_includes(comments, sharded_comments(:wow_comment_blog_post_one))
|
|
216
|
+
assert_includes(comments, sharded_comments(:great_comment_blog_post_one))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_belongs_to_with_explicit_composite_foreign_key
|
|
220
|
+
car = Cpk::Car.create(make: "Tesla", model: "Model S")
|
|
221
|
+
review = Cpk::CarReview.create(car: car, comment: "Great car!", rating: 5)
|
|
222
|
+
|
|
223
|
+
review.reload
|
|
224
|
+
|
|
225
|
+
sql = capture_sql do
|
|
226
|
+
assert_equal(car, review.car)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
assert_match(/(?:#{Regexp.escape(quote_table_name("cpk_cars.make"))}|cpk_cars\.make) =/, sql.first)
|
|
230
|
+
assert_match(/(?:#{Regexp.escape(quote_table_name("cpk_cars.model"))}|cpk_cars\.model) =/, sql.first)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def test_cpk_model_has_many_records_by_id_attribute
|
|
234
|
+
order = cpk_orders(:cpk_groceries_order_1)
|
|
235
|
+
_order_shop_id, order_id = order.id
|
|
236
|
+
agreements = 2.times.map { Cpk::OrderAgreement.create(order_id: order_id, signature: "signed") }
|
|
237
|
+
|
|
238
|
+
assert_equal(agreements.sort, order.order_agreements.to_a.sort)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def test_has_many_association_from_a_model_with_query_constraints_different_from_the_association
|
|
242
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
243
|
+
blog_post = Sharded::BlogPostWithRevision.find(blog_post.id)
|
|
244
|
+
comments = []
|
|
245
|
+
expected_comments = Sharded::Comment.where(blog_id: blog_post.blog_id, blog_post_id: blog_post.id).to_a
|
|
246
|
+
|
|
247
|
+
sql = capture_sql do
|
|
248
|
+
comments = blog_post.comments.to_a
|
|
249
|
+
end.first
|
|
250
|
+
|
|
251
|
+
assert_match(/WHERE .*(?:#{Regexp.escape(quote_table_name("sharded_comments.blog_id"))}|sharded_comments\.blog_id) =/, sql)
|
|
252
|
+
assert_not_empty(comments)
|
|
253
|
+
assert_equal(expected_comments.sort, comments.sort)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def test_query_constraints_over_three_without_defining_explicit_foreign_key_query_constraints_raises
|
|
257
|
+
Sharded::BlogPostWithRevision.has_many :comments_without_query_constraints, primary_key: [:blog_id, :id], class_name: "Comment"
|
|
258
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
259
|
+
blog_post = Sharded::BlogPostWithRevision.find(blog_post.id)
|
|
260
|
+
|
|
261
|
+
error = assert_raises ArgumentError do
|
|
262
|
+
blog_post.comments_without_query_constraints.to_a
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
assert_equal "The query constraints list on the `Sharded::BlogPostWithRevision` model has more than 2 attributes. Active Record is unable to derive the query constraints for the association. You need to explicitly define the query constraints for this association.", error.message
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def test_model_with_composite_query_constraints_has_many_association_sql
|
|
269
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
270
|
+
|
|
271
|
+
sql = capture_sql do
|
|
272
|
+
blog_post.comments.to_a
|
|
273
|
+
end.first
|
|
274
|
+
|
|
275
|
+
assert_match(/(?:#{Regexp.escape(quote_table_name("sharded_comments.blog_post_id"))}|sharded_comments\.blog_post_id) =/, sql)
|
|
276
|
+
assert_match(/(?:#{Regexp.escape(quote_table_name("sharded_comments.blog_id"))}|sharded_comments\.blog_id) =/, sql)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def test_belongs_to_association_does_not_use_parent_query_constraints_if_not_configured_to
|
|
280
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
281
|
+
blog_post = Sharded::BlogPost.new(blog_id: comment.blog_id, title: "Following best practices")
|
|
282
|
+
|
|
283
|
+
comment.blog_post_by_id = blog_post
|
|
284
|
+
|
|
285
|
+
comment.save
|
|
286
|
+
|
|
287
|
+
assert_predicate blog_post, :persisted?
|
|
288
|
+
assert_equal(blog_post, comment.blog_post_by_id)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def test_polymorphic_belongs_to_uses_parent_query_constraints
|
|
292
|
+
parent_post = sharded_blog_posts(:great_post_blog_one)
|
|
293
|
+
child_post = Sharded::BlogPost.create!(title: "Child post", blog_id: parent_post.blog_id, parent: parent_post)
|
|
294
|
+
child_post.reload # reload to forget the parent association
|
|
295
|
+
|
|
296
|
+
assert_equal parent_post, child_post.parent
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def test_preloads_model_with_query_constraints_by_explicitly_configured_fk_and_pk
|
|
300
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
301
|
+
comments = Sharded::Comment.where(id: comment.id).preload(:blog_post_by_id).to_a
|
|
302
|
+
comment = comments.first
|
|
303
|
+
assert_equal(comment.blog_post_by_id, comment.blog_post)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def test_append_composite_foreign_key_has_many_association
|
|
307
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
308
|
+
comment = Sharded::Comment.new(body: "Great post! :clap:")
|
|
309
|
+
comment.save
|
|
310
|
+
blog_post.comments << comment
|
|
311
|
+
|
|
312
|
+
assert_includes(blog_post.comments, comment)
|
|
313
|
+
assert_equal(blog_post.id, comment.blog_post_id)
|
|
314
|
+
assert_equal(blog_post.blog_id, comment.blog_id)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def test_nullify_composite_foreign_key_has_many_association
|
|
318
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
319
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
320
|
+
|
|
321
|
+
assert_not_empty(blog_post.comments)
|
|
322
|
+
blog_post.comments = []
|
|
323
|
+
|
|
324
|
+
comment = Sharded::Comment.find(comment.id)
|
|
325
|
+
assert_nil(comment.blog_post_id)
|
|
326
|
+
assert_nil(comment.blog_id)
|
|
327
|
+
|
|
328
|
+
assert_empty(blog_post.comments)
|
|
329
|
+
assert_empty(blog_post.reload.comments)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def test_assign_persisted_composite_foreign_key_belongs_to_association
|
|
333
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
334
|
+
another_blog = sharded_blogs(:sharded_blog_two)
|
|
335
|
+
assert_not_equal(comment.blog_id, another_blog.id)
|
|
336
|
+
|
|
337
|
+
blog_post = Sharded::BlogPost.new(title: "New post", blog_id: another_blog.id)
|
|
338
|
+
blog_post.save
|
|
339
|
+
comment.blog_post = blog_post
|
|
340
|
+
|
|
341
|
+
assert_equal(blog_post, comment.blog_post)
|
|
342
|
+
assert_equal(comment.blog_id, blog_post.blog_id)
|
|
343
|
+
assert_equal(another_blog.id, comment.blog_id)
|
|
344
|
+
assert_equal(comment.blog_post_id, blog_post.id)
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def test_nullify_composite_foreign_key_belongs_to_association
|
|
348
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
349
|
+
assert_not_nil(comment.blog_post)
|
|
350
|
+
|
|
351
|
+
comment.blog_post = nil
|
|
352
|
+
assert_nil(comment.blog_id)
|
|
353
|
+
assert_nil(comment.blog_post_id)
|
|
354
|
+
|
|
355
|
+
comment.save
|
|
356
|
+
assert_nil(comment.blog_post)
|
|
357
|
+
assert_nil(comment.reload.blog_post)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def test_assign_composite_foreign_key_belongs_to_association
|
|
361
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
362
|
+
another_blog = sharded_blogs(:sharded_blog_two)
|
|
363
|
+
assert_not_equal(comment.blog_id, another_blog.id)
|
|
364
|
+
|
|
365
|
+
blog_post = Sharded::BlogPost.new(title: "New post", blog_id: another_blog.id)
|
|
366
|
+
comment.blog_post = blog_post
|
|
367
|
+
|
|
368
|
+
assert_equal(blog_post, comment.blog_post)
|
|
369
|
+
assert_equal(comment.blog_id, blog_post.blog_id)
|
|
370
|
+
assert_equal(another_blog.id, comment.blog_id)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def test_query_constraints_that_dont_include_the_primary_key_raise_with_a_single_column
|
|
374
|
+
original = Sharded::BlogPost.instance_variable_get(:@query_constraints_list)
|
|
375
|
+
Sharded::BlogPost.query_constraints :title
|
|
376
|
+
Sharded::BlogPost.has_many :comments_without_single_column_query_constraints, primary_key: [:blog_id, :id], class_name: "Comment"
|
|
377
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
378
|
+
|
|
379
|
+
error = assert_raises ArgumentError do
|
|
380
|
+
blog_post.comments_without_single_column_query_constraints.to_a
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
assert_equal "The query constraints on the `Sharded::BlogPost` model does not include the primary key so Active Record is unable to derive the foreign key constraints for the association. You need to explicitly define the query constraints for this association.", error.message
|
|
384
|
+
ensure
|
|
385
|
+
Sharded::BlogPost.instance_variable_set(:@query_constraints_list, original)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def test_query_constraints_that_dont_include_the_primary_key_raise_with_multiple_columns
|
|
389
|
+
original = Sharded::BlogPost.instance_variable_get(:@query_constraints_list)
|
|
390
|
+
Sharded::BlogPost.query_constraints :title, :revision
|
|
391
|
+
Sharded::BlogPost.has_many :comments_without_multiple_column_query_constraints, primary_key: [:blog_id, :id], class_name: "Comment"
|
|
392
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
393
|
+
|
|
394
|
+
error = assert_raises ArgumentError do
|
|
395
|
+
blog_post.comments_without_multiple_column_query_constraints.to_a
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
assert_equal "The query constraints on the `Sharded::BlogPost` model does not include the primary key so Active Record is unable to derive the foreign key constraints for the association. You need to explicitly define the query constraints for this association.", error.message
|
|
399
|
+
ensure
|
|
400
|
+
Sharded::BlogPost.instance_variable_set(:@query_constraints_list, original)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def test_assign_belongs_to_cpk_model_by_id_attribute
|
|
404
|
+
order = cpk_orders(:cpk_groceries_order_1)
|
|
405
|
+
agreement = Cpk::OrderAgreement.new(signature: "signed")
|
|
406
|
+
|
|
407
|
+
agreement.order = order
|
|
408
|
+
agreement.save
|
|
409
|
+
|
|
410
|
+
assert_not_nil(agreement.reload.order)
|
|
411
|
+
assert_not_nil(agreement.order_id)
|
|
412
|
+
|
|
413
|
+
assert_equal(order, agreement.order)
|
|
414
|
+
_shop_id, order_id = order.id
|
|
415
|
+
assert_equal(order_id, agreement.order_id)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def test_append_composite_foreign_key_has_many_association_with_autosave
|
|
419
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
420
|
+
comment = Sharded::Comment.new(body: "Great post! :clap:")
|
|
421
|
+
blog_post.comments << comment
|
|
422
|
+
|
|
423
|
+
assert_predicate(comment, :persisted?)
|
|
424
|
+
assert_includes(blog_post.comments, comment)
|
|
425
|
+
assert_equal(blog_post.id, comment.blog_post_id)
|
|
426
|
+
assert_equal(blog_post.blog_id, comment.blog_id)
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def test_assign_composite_foreign_key_belongs_to_association_with_autosave
|
|
430
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
431
|
+
another_blog = sharded_blogs(:sharded_blog_two)
|
|
432
|
+
assert_not_equal(comment.blog_id, another_blog.id)
|
|
433
|
+
|
|
434
|
+
blog_post = Sharded::BlogPost.new(title: "New post", blog_id: another_blog.id)
|
|
435
|
+
comment.blog_post = blog_post
|
|
436
|
+
comment.save
|
|
437
|
+
|
|
438
|
+
assert_predicate(blog_post, :persisted?)
|
|
439
|
+
assert_equal(blog_post, comment.blog_post)
|
|
440
|
+
assert_equal(comment.blog_id, blog_post.blog_id)
|
|
441
|
+
assert_equal(another_blog.id, comment.blog_id)
|
|
442
|
+
assert_equal(comment.blog_post_id, blog_post.id)
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def test_append_composite_has_many_through_association
|
|
446
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
447
|
+
tag = Sharded::Tag.new(name: "Ruby on Rails", blog_id: blog_post.blog_id)
|
|
448
|
+
tag.save
|
|
449
|
+
|
|
450
|
+
blog_post.tags << tag
|
|
451
|
+
|
|
452
|
+
assert_includes(blog_post.reload.tags, tag)
|
|
453
|
+
assert_predicate Sharded::BlogPostTag.where(blog_post_id: blog_post.id, blog_id: blog_post.blog_id, tag_id: tag.id), :exists?
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def test_append_composite_has_many_through_association_with_autosave
|
|
457
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
458
|
+
tag = Sharded::Tag.new(name: "Ruby on Rails", blog_id: blog_post.blog_id)
|
|
459
|
+
|
|
460
|
+
blog_post.tags << tag
|
|
461
|
+
|
|
462
|
+
assert_includes(blog_post.reload.tags, tag)
|
|
463
|
+
assert_predicate Sharded::BlogPostTag.where(blog_post_id: blog_post.id, blog_id: blog_post.blog_id, tag_id: tag.id), :exists?
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def test_nullify_composite_has_many_through_association
|
|
467
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
468
|
+
assert_not_empty(blog_post.tags)
|
|
469
|
+
|
|
470
|
+
blog_post.tags = []
|
|
471
|
+
|
|
472
|
+
assert_empty(blog_post.tags)
|
|
473
|
+
assert_empty(blog_post.reload.tags)
|
|
474
|
+
assert_not_predicate Sharded::BlogPostTag.where(blog_post_id: blog_post.id, blog_id: blog_post.blog_id), :exists?
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def test_using_query_constraints_warns_about_changing_behavior
|
|
478
|
+
has_many_expected_message = <<~MSG.squish
|
|
479
|
+
Setting `query_constraints:` option on `Sharded::BlogPost.has_many :qc_deprecated_comments` is not allowed.
|
|
480
|
+
To get the same behavior, use the `foreign_key` option instead.
|
|
481
|
+
MSG
|
|
482
|
+
|
|
483
|
+
assert_raises(ActiveRecord::ConfigurationError, match: has_many_expected_message) do
|
|
484
|
+
Sharded::BlogPost.has_many :qc_deprecated_comments,
|
|
485
|
+
class_name: "Sharded::Comment", query_constraints: [:blog_id, :blog_post_id]
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
belongs_to_expected_message = <<~MSG.squish
|
|
489
|
+
Setting `query_constraints:` option on `Sharded::Comment.belongs_to :qc_deprecated_blog_post` is not allowed.
|
|
490
|
+
To get the same behavior, use the `foreign_key` option instead.
|
|
491
|
+
MSG
|
|
492
|
+
|
|
493
|
+
assert_raises(ActiveRecord::ConfigurationError, match: belongs_to_expected_message) do
|
|
494
|
+
Sharded::Comment.belongs_to :qc_deprecated_blog_post,
|
|
495
|
+
class_name: "Sharded::Blog", query_constraints: [:blog_id, :blog_post_id]
|
|
496
|
+
end
|
|
497
|
+
end
|
|
118
498
|
end
|
|
119
499
|
|
|
120
500
|
class AssociationProxyTest < ActiveRecord::TestCase
|
|
121
|
-
fixtures :authors, :author_addresses, :posts, :categorizations, :categories, :developers, :projects, :developers_projects
|
|
501
|
+
fixtures :authors, :author_addresses, :posts, :categorizations, :categories, :developers, :projects, :developers_projects, :members
|
|
122
502
|
|
|
123
503
|
def test_push_does_not_load_target
|
|
124
504
|
david = authors(:david)
|
|
@@ -188,6 +568,15 @@ class AssociationProxyTest < ActiveRecord::TestCase
|
|
|
188
568
|
assert_predicate andreas.audit_logs, :loaded?
|
|
189
569
|
end
|
|
190
570
|
|
|
571
|
+
def test_pretty_print_does_not_reload_a_not_yet_loaded_target
|
|
572
|
+
andreas = Developer.new(log: "new developer added")
|
|
573
|
+
assert_not_predicate andreas.audit_logs, :loaded?
|
|
574
|
+
out = StringIO.new
|
|
575
|
+
PP.pp(andreas.audit_logs, out)
|
|
576
|
+
assert_match(/message: "new developer added"/, out.string)
|
|
577
|
+
assert_predicate andreas.audit_logs, :loaded?
|
|
578
|
+
end
|
|
579
|
+
|
|
191
580
|
def test_save_on_parent_saves_children
|
|
192
581
|
developer = Developer.create name: "Bryan", salary: 50_000
|
|
193
582
|
assert_equal 1, developer.reload.audit_logs.size
|
|
@@ -195,14 +584,14 @@ class AssociationProxyTest < ActiveRecord::TestCase
|
|
|
195
584
|
|
|
196
585
|
def test_create_via_association_with_block
|
|
197
586
|
post = authors(:david).posts.create(title: "New on Edge") { |p| p.body = "More cool stuff!" }
|
|
198
|
-
assert_equal
|
|
199
|
-
assert_equal
|
|
587
|
+
assert_equal "New on Edge", post.title
|
|
588
|
+
assert_equal "More cool stuff!", post.body
|
|
200
589
|
end
|
|
201
590
|
|
|
202
591
|
def test_create_with_bang_via_association_with_block
|
|
203
592
|
post = authors(:david).posts.create!(title: "New on Edge") { |p| p.body = "More cool stuff!" }
|
|
204
|
-
assert_equal
|
|
205
|
-
assert_equal
|
|
593
|
+
assert_equal "New on Edge", post.title
|
|
594
|
+
assert_equal "More cool stuff!", post.body
|
|
206
595
|
end
|
|
207
596
|
|
|
208
597
|
def test_reload_returns_association
|
|
@@ -246,7 +635,7 @@ class AssociationProxyTest < ActiveRecord::TestCase
|
|
|
246
635
|
|
|
247
636
|
human = Human.find(human.id)
|
|
248
637
|
|
|
249
|
-
|
|
638
|
+
assert_queries_count(1) do
|
|
250
639
|
assert_equal human, human.interests.where("1=1").first.human
|
|
251
640
|
end
|
|
252
641
|
end
|
|
@@ -292,6 +681,41 @@ class AssociationProxyTest < ActiveRecord::TestCase
|
|
|
292
681
|
assert_equal 1, david.thinking_posts.size
|
|
293
682
|
assert_equal 1, david.thinking_posts.to_a.size
|
|
294
683
|
end
|
|
684
|
+
|
|
685
|
+
def test_target_merging_ignores_persisted_in_memory_records_when_loaded_records_are_empty
|
|
686
|
+
member = members(:blarpy_winkup)
|
|
687
|
+
assert_empty member.favorite_memberships
|
|
688
|
+
|
|
689
|
+
membership = member.favorite_memberships.create!
|
|
690
|
+
membership.update!(favorite: false)
|
|
691
|
+
|
|
692
|
+
assert_empty member.favorite_memberships.to_a
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
def test_target_merging_recognizes_updated_in_memory_records
|
|
696
|
+
member = members(:blarpy_winkup)
|
|
697
|
+
membership = member.create_membership!(favorite: false)
|
|
698
|
+
|
|
699
|
+
assert_empty member.favorite_memberships
|
|
700
|
+
|
|
701
|
+
membership.update!(favorite: true)
|
|
702
|
+
|
|
703
|
+
assert_not_empty member.favorite_memberships.to_a
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
def test_size_differentiates_between_new_and_persisted_in_memory_records_when_loaded_records_are_empty
|
|
707
|
+
member = members(:blarpy_winkup)
|
|
708
|
+
assert_empty member.favorite_memberships
|
|
709
|
+
|
|
710
|
+
membership = member.favorite_memberships.create!
|
|
711
|
+
membership.update!(favorite: false)
|
|
712
|
+
|
|
713
|
+
# CollectionAssociation#size has different behavior when loaded vs. non-loaded
|
|
714
|
+
# the first call will mark the association as loaded and the second call will
|
|
715
|
+
# take a different code path, so it's important to keep both assertions
|
|
716
|
+
assert_equal 0, member.favorite_memberships.size
|
|
717
|
+
assert_equal 0, member.favorite_memberships.size
|
|
718
|
+
end
|
|
295
719
|
end
|
|
296
720
|
|
|
297
721
|
class OverridingAssociationsTest < ActiveRecord::TestCase
|
|
@@ -363,32 +787,865 @@ class OverridingAssociationsTest < ActiveRecord::TestCase
|
|
|
363
787
|
end
|
|
364
788
|
end
|
|
365
789
|
end
|
|
790
|
+
|
|
791
|
+
class ModelAssociatedToClassesThatDoNotExist < ActiveRecord::Base
|
|
792
|
+
self.table_name = "accounts" # this is just to avoid adding a new model just for this test
|
|
793
|
+
|
|
794
|
+
has_one :non_existent_has_one_class
|
|
795
|
+
belongs_to :non_existent_belongs_to_class
|
|
796
|
+
has_many :non_existent_has_many_classes
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
def test_associations_raise_with_name_error_if_associated_to_classes_that_do_not_exist
|
|
800
|
+
assert_raises NameError do
|
|
801
|
+
ModelAssociatedToClassesThatDoNotExist.new.non_existent_has_one_class
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
assert_raises NameError do
|
|
805
|
+
ModelAssociatedToClassesThatDoNotExist.new.non_existent_belongs_to_class
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
assert_raises NameError do
|
|
809
|
+
ModelAssociatedToClassesThatDoNotExist.new.non_existent_has_many_classes
|
|
810
|
+
end
|
|
811
|
+
end
|
|
366
812
|
end
|
|
367
813
|
|
|
368
814
|
class PreloaderTest < ActiveRecord::TestCase
|
|
369
|
-
fixtures :posts, :comments
|
|
815
|
+
fixtures :posts, :comments, :books, :authors, :tags, :taggings, :essays, :categories, :author_addresses,
|
|
816
|
+
:sharded_blog_posts, :sharded_comments, :sharded_blog_posts_tags, :sharded_tags,
|
|
817
|
+
:members, :member_details, :organizations, :cpk_authors, :cpk_orders, :cpk_books, :cpk_order_agreements,
|
|
818
|
+
:dogs, :other_dogs
|
|
370
819
|
|
|
371
820
|
def test_preload_with_scope
|
|
372
821
|
post = posts(:welcome)
|
|
373
822
|
|
|
374
|
-
preloader = ActiveRecord::Associations::Preloader.new
|
|
375
|
-
preloader.
|
|
823
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments, scope: Comment.where(body: "Thank you for the welcome"))
|
|
824
|
+
preloader.call
|
|
376
825
|
|
|
377
826
|
assert_predicate post.comments, :loaded?
|
|
378
827
|
assert_equal [comments(:greetings)], post.comments
|
|
379
828
|
end
|
|
380
829
|
|
|
830
|
+
def test_preload_makes_correct_number_of_queries_on_array
|
|
831
|
+
post = posts(:welcome)
|
|
832
|
+
|
|
833
|
+
assert_queries_count(1) do
|
|
834
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments)
|
|
835
|
+
preloader.call
|
|
836
|
+
end
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
def test_preload_makes_correct_number_of_queries_on_relation
|
|
840
|
+
post = posts(:welcome)
|
|
841
|
+
relation = Post.where(id: post.id)
|
|
842
|
+
|
|
843
|
+
assert_queries_count(2) do
|
|
844
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: relation, associations: :comments)
|
|
845
|
+
preloader.call
|
|
846
|
+
end
|
|
847
|
+
end
|
|
848
|
+
|
|
849
|
+
def test_preload_does_not_concatenate_duplicate_records
|
|
850
|
+
post = posts(:welcome)
|
|
851
|
+
post.reload
|
|
852
|
+
post.comments.create!(body: "A new comment")
|
|
853
|
+
|
|
854
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments).call
|
|
855
|
+
|
|
856
|
+
assert_equal post.comments.length, post.comments.count
|
|
857
|
+
assert_equal post.comments.all.to_a, post.comments
|
|
858
|
+
end
|
|
859
|
+
|
|
381
860
|
def test_preload_for_hmt_with_conditions
|
|
382
861
|
post = posts(:welcome)
|
|
383
862
|
_normal_category = post.categories.create!(name: "Normal")
|
|
384
863
|
special_category = post.special_categories.create!(name: "Special")
|
|
385
864
|
|
|
386
|
-
preloader = ActiveRecord::Associations::Preloader.new
|
|
387
|
-
preloader.
|
|
865
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [post], associations: :hmt_special_categories)
|
|
866
|
+
preloader.call
|
|
388
867
|
|
|
389
868
|
assert_equal 1, post.hmt_special_categories.length
|
|
390
869
|
assert_equal [special_category], post.hmt_special_categories
|
|
391
870
|
end
|
|
871
|
+
|
|
872
|
+
def test_preload_groups_queries_with_same_scope
|
|
873
|
+
book = books(:awdr)
|
|
874
|
+
post = posts(:welcome)
|
|
875
|
+
|
|
876
|
+
assert_queries_count(1) do
|
|
877
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [book, post], associations: :author)
|
|
878
|
+
preloader.call
|
|
879
|
+
end
|
|
880
|
+
|
|
881
|
+
assert_no_queries do
|
|
882
|
+
book.author
|
|
883
|
+
post.author
|
|
884
|
+
end
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
def test_preload_grouped_queries_with_already_loaded_records
|
|
888
|
+
book = books(:awdr)
|
|
889
|
+
post = posts(:welcome)
|
|
890
|
+
book.author
|
|
891
|
+
|
|
892
|
+
assert_no_queries do
|
|
893
|
+
ActiveRecord::Associations::Preloader.new(records: [book, post], associations: :author).call
|
|
894
|
+
book.author
|
|
895
|
+
post.author
|
|
896
|
+
end
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
def test_preload_grouped_queries_of_middle_records
|
|
900
|
+
comments = [
|
|
901
|
+
comments(:eager_sti_on_associations_s_comment1),
|
|
902
|
+
comments(:eager_sti_on_associations_s_comment2),
|
|
903
|
+
]
|
|
904
|
+
|
|
905
|
+
assert_queries_count(2) do
|
|
906
|
+
ActiveRecord::Associations::Preloader.new(records: comments, associations: [:author, :ordinary_post]).call
|
|
907
|
+
end
|
|
908
|
+
end
|
|
909
|
+
|
|
910
|
+
def test_preload_grouped_queries_of_through_records
|
|
911
|
+
author = authors(:david)
|
|
912
|
+
|
|
913
|
+
assert_queries_count(3) do
|
|
914
|
+
ActiveRecord::Associations::Preloader.new(records: [author], associations: [:hello_post_comments, :comments]).call
|
|
915
|
+
end
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
def test_preload_through_records_with_already_loaded_middle_record
|
|
919
|
+
member = members(:groucho)
|
|
920
|
+
expected_member_detail_ids = member.organization_member_details_2.pluck(:id)
|
|
921
|
+
|
|
922
|
+
member.reload.organization # load through record
|
|
923
|
+
|
|
924
|
+
assert_queries_count(1) do
|
|
925
|
+
ActiveRecord::Associations::Preloader.new(records: [member], associations: :organization_member_details_2).call
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
assert_no_queries do
|
|
929
|
+
assert_equal expected_member_detail_ids.sort, member.organization_member_details_2.map(&:id).sort
|
|
930
|
+
end
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
def test_preload_with_instance_dependent_scope
|
|
934
|
+
david = authors(:david)
|
|
935
|
+
david2 = Author.create!(name: "David")
|
|
936
|
+
bob = authors(:bob)
|
|
937
|
+
post = Post.create!(
|
|
938
|
+
author: david,
|
|
939
|
+
title: "test post",
|
|
940
|
+
body: "this post is about David"
|
|
941
|
+
)
|
|
942
|
+
post2 = Post.create!(
|
|
943
|
+
author: david,
|
|
944
|
+
title: "test post 2",
|
|
945
|
+
body: "this post is also about David"
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
assert_queries_count(2) do
|
|
949
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [david, david2, bob], associations: :posts_mentioning_author)
|
|
950
|
+
preloader.call
|
|
951
|
+
end
|
|
952
|
+
|
|
953
|
+
assert_predicate david.posts_mentioning_author, :loaded?
|
|
954
|
+
assert_predicate david2.posts_mentioning_author, :loaded?
|
|
955
|
+
assert_predicate bob.posts_mentioning_author, :loaded?
|
|
956
|
+
|
|
957
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
958
|
+
# DB2 matches LIKE case-sensitively in this environment.
|
|
959
|
+
assert_equal [], david.posts_mentioning_author
|
|
960
|
+
else
|
|
961
|
+
assert_equal [post, post2].sort, david.posts_mentioning_author.sort
|
|
962
|
+
end
|
|
963
|
+
assert_equal [], david2.posts_mentioning_author
|
|
964
|
+
assert_equal [], bob.posts_mentioning_author
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
def test_preload_with_instance_dependent_through_scope
|
|
968
|
+
david = authors(:david)
|
|
969
|
+
david2 = Author.create!(name: "David")
|
|
970
|
+
bob = authors(:bob)
|
|
971
|
+
comment1 = david.posts.first.comments.create!(body: "Hi David!")
|
|
972
|
+
comment2 = david.posts.first.comments.create!(body: "This comment mentions david")
|
|
973
|
+
|
|
974
|
+
assert_queries_count(2) do
|
|
975
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [david, david2, bob], associations: :comments_mentioning_author)
|
|
976
|
+
preloader.call
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
assert_predicate david.comments_mentioning_author, :loaded?
|
|
980
|
+
assert_predicate david2.comments_mentioning_author, :loaded?
|
|
981
|
+
assert_predicate bob.comments_mentioning_author, :loaded?
|
|
982
|
+
|
|
983
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
984
|
+
# DB2 matches LIKE case-sensitively in this environment.
|
|
985
|
+
assert_equal [comment2], david.comments_mentioning_author
|
|
986
|
+
else
|
|
987
|
+
assert_equal [comment1, comment2].sort, david.comments_mentioning_author.sort
|
|
988
|
+
end
|
|
989
|
+
assert_equal [], david2.comments_mentioning_author
|
|
990
|
+
assert_equal [], bob.comments_mentioning_author
|
|
991
|
+
end
|
|
992
|
+
|
|
993
|
+
def test_preload_with_through_instance_dependent_scope
|
|
994
|
+
david = authors(:david)
|
|
995
|
+
david2 = Author.create!(name: "David")
|
|
996
|
+
bob = authors(:bob)
|
|
997
|
+
post = Post.create!(
|
|
998
|
+
author: david,
|
|
999
|
+
title: "test post",
|
|
1000
|
+
body: "this post is about David"
|
|
1001
|
+
)
|
|
1002
|
+
Post.create!(
|
|
1003
|
+
author: david,
|
|
1004
|
+
title: "test post 2",
|
|
1005
|
+
body: "this post is also about David"
|
|
1006
|
+
)
|
|
1007
|
+
post3 = Post.create!(
|
|
1008
|
+
author: bob,
|
|
1009
|
+
title: "test post 3",
|
|
1010
|
+
body: "this post is about Bob"
|
|
1011
|
+
)
|
|
1012
|
+
comment1 = post.comments.create!(body: "hi!")
|
|
1013
|
+
comment2 = post.comments.create!(body: "hello!")
|
|
1014
|
+
comment3 = post3.comments.create!(body: "HI BOB!")
|
|
1015
|
+
|
|
1016
|
+
expected_queries = current_adapter?(:IBM_DBAdapter) ? 2 : 3
|
|
1017
|
+
assert_queries_count(expected_queries) do
|
|
1018
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [david, david2, bob], associations: :comments_on_posts_mentioning_author)
|
|
1019
|
+
preloader.call
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
assert_predicate david.comments_on_posts_mentioning_author, :loaded?
|
|
1023
|
+
assert_predicate david2.comments_on_posts_mentioning_author, :loaded?
|
|
1024
|
+
assert_predicate bob.comments_on_posts_mentioning_author, :loaded?
|
|
1025
|
+
|
|
1026
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
1027
|
+
# DB2 matches LIKE case-sensitively in this environment.
|
|
1028
|
+
assert_equal [], david.comments_on_posts_mentioning_author
|
|
1029
|
+
assert_equal [], bob.comments_on_posts_mentioning_author
|
|
1030
|
+
else
|
|
1031
|
+
assert_equal [comment1, comment2].sort, david.comments_on_posts_mentioning_author.sort
|
|
1032
|
+
assert_equal [comment3], bob.comments_on_posts_mentioning_author
|
|
1033
|
+
end
|
|
1034
|
+
assert_equal [], david2.comments_on_posts_mentioning_author
|
|
1035
|
+
end
|
|
1036
|
+
|
|
1037
|
+
def test_some_already_loaded_associations
|
|
1038
|
+
item_discount = Discount.create(amount: 5)
|
|
1039
|
+
shipping_discount = Discount.create(amount: 20)
|
|
1040
|
+
|
|
1041
|
+
invoice = Invoice.new
|
|
1042
|
+
line_item = LineItem.new(amount: 20)
|
|
1043
|
+
line_item.discount_applications << LineItemDiscountApplication.new(discount: item_discount)
|
|
1044
|
+
invoice.line_items << line_item
|
|
1045
|
+
|
|
1046
|
+
shipping_line = ShippingLine.new(amount: 50)
|
|
1047
|
+
shipping_line.discount_applications << ShippingLineDiscountApplication.new(discount: shipping_discount)
|
|
1048
|
+
invoice.shipping_lines << shipping_line
|
|
1049
|
+
|
|
1050
|
+
invoice.save!
|
|
1051
|
+
invoice.reload
|
|
1052
|
+
|
|
1053
|
+
# SELECT "line_items".* FROM "line_items" WHERE "line_items"."invoice_id" = ?
|
|
1054
|
+
# SELECT "shipping_lines".* FROM shipping_lines WHERE "shipping_lines"."invoice_id" = ?
|
|
1055
|
+
# SELECT "line_item_discount_applications".* FROM "line_item_discount_applications" WHERE "line_item_discount_applications"."line_item_id" = ?
|
|
1056
|
+
# SELECT "shipping_line_discount_applications".* FROM "shipping_line_discount_applications" WHERE "shipping_line_discount_applications"."shipping_line_id" = ?
|
|
1057
|
+
# SELECT "discounts".* FROM "discounts" WHERE "discounts"."id" IN (?, ?).
|
|
1058
|
+
assert_queries_count(5) do
|
|
1059
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [invoice], associations: [
|
|
1060
|
+
line_items: { discount_applications: :discount },
|
|
1061
|
+
shipping_lines: { discount_applications: :discount },
|
|
1062
|
+
])
|
|
1063
|
+
preloader.call
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
assert_no_queries do
|
|
1067
|
+
assert_not_nil invoice.line_items.first.discount_applications.first.discount
|
|
1068
|
+
assert_not_nil invoice.shipping_lines.first.discount_applications.first.discount
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1071
|
+
invoice.reload
|
|
1072
|
+
invoice.line_items.map { |i| i.discount_applications.to_a }
|
|
1073
|
+
# `line_items` and `line_item_discount_applications` are already preloaded, so we expect:
|
|
1074
|
+
# SELECT "shipping_lines".* FROM shipping_lines WHERE "shipping_lines"."invoice_id" = ?
|
|
1075
|
+
# SELECT "shipping_line_discount_applications".* FROM "shipping_line_discount_applications" WHERE "shipping_line_discount_applications"."shipping_line_id" = ?
|
|
1076
|
+
# SELECT "discounts".* FROM "discounts" WHERE "discounts"."id" = ?.
|
|
1077
|
+
assert_queries_count(3) do
|
|
1078
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [invoice], associations: [
|
|
1079
|
+
line_items: { discount_applications: :discount },
|
|
1080
|
+
shipping_lines: { discount_applications: :discount },
|
|
1081
|
+
])
|
|
1082
|
+
preloader.call
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
assert_no_queries do
|
|
1086
|
+
assert_not_nil invoice.line_items.first.discount_applications.first.discount
|
|
1087
|
+
assert_not_nil invoice.shipping_lines.first.discount_applications.first.discount
|
|
1088
|
+
end
|
|
1089
|
+
end
|
|
1090
|
+
|
|
1091
|
+
def test_preload_through
|
|
1092
|
+
comments = [
|
|
1093
|
+
comments(:eager_sti_on_associations_s_comment1),
|
|
1094
|
+
comments(:eager_sti_on_associations_s_comment2),
|
|
1095
|
+
]
|
|
1096
|
+
|
|
1097
|
+
assert_queries_count(2) do
|
|
1098
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: comments, associations: [:author, :post])
|
|
1099
|
+
preloader.call
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1102
|
+
assert_no_queries do
|
|
1103
|
+
comments.each(&:author)
|
|
1104
|
+
end
|
|
1105
|
+
end
|
|
1106
|
+
|
|
1107
|
+
def test_preload_groups_queries_with_same_scope_at_second_level
|
|
1108
|
+
author = nil
|
|
1109
|
+
|
|
1110
|
+
# Expected
|
|
1111
|
+
# SELECT FROM authors ...
|
|
1112
|
+
# SELECT FROM posts ... (thinking)
|
|
1113
|
+
# SELECT FROM posts ... (welcome)
|
|
1114
|
+
# SELECT FROM comments ... (comments for both welcome and thinking)
|
|
1115
|
+
assert_queries_count(4) do
|
|
1116
|
+
author = Author
|
|
1117
|
+
.where(name: "David")
|
|
1118
|
+
.includes(thinking_posts: :comments, welcome_posts: :comments)
|
|
1119
|
+
.first
|
|
1120
|
+
end
|
|
1121
|
+
|
|
1122
|
+
assert_no_queries do
|
|
1123
|
+
author.thinking_posts.map(&:comments)
|
|
1124
|
+
author.welcome_posts.map(&:comments)
|
|
1125
|
+
end
|
|
1126
|
+
end
|
|
1127
|
+
|
|
1128
|
+
def test_preload_groups_queries_with_same_sql_at_second_level
|
|
1129
|
+
author = nil
|
|
1130
|
+
|
|
1131
|
+
# Expected
|
|
1132
|
+
# SELECT FROM authors ...
|
|
1133
|
+
# SELECT FROM posts ... (thinking)
|
|
1134
|
+
# SELECT FROM posts ... (welcome)
|
|
1135
|
+
# SELECT FROM comments ... (comments for both welcome and thinking)
|
|
1136
|
+
assert_queries_count(4) do
|
|
1137
|
+
author = Author
|
|
1138
|
+
.where(name: "David")
|
|
1139
|
+
.includes(thinking_posts: :comments, welcome_posts: :comments_with_extending)
|
|
1140
|
+
.first
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
assert_no_queries do
|
|
1144
|
+
author.thinking_posts.map(&:comments)
|
|
1145
|
+
author.welcome_posts.map(&:comments_with_extending)
|
|
1146
|
+
end
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
def test_preload_with_grouping_sets_inverse_association
|
|
1150
|
+
mary = authors(:mary)
|
|
1151
|
+
bob = authors(:bob)
|
|
1152
|
+
|
|
1153
|
+
AuthorFavorite.create!(author: mary, favorite_author: bob)
|
|
1154
|
+
favorites = AuthorFavorite.all.load
|
|
1155
|
+
|
|
1156
|
+
assert_queries_count(1) do
|
|
1157
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: favorites, associations: [:author, :favorite_author])
|
|
1158
|
+
preloader.call
|
|
1159
|
+
end
|
|
1160
|
+
|
|
1161
|
+
assert_no_queries do
|
|
1162
|
+
favorites.first.author
|
|
1163
|
+
favorites.first.favorite_author
|
|
1164
|
+
end
|
|
1165
|
+
end
|
|
1166
|
+
|
|
1167
|
+
def test_preload_can_group_separate_levels
|
|
1168
|
+
mary = authors(:mary)
|
|
1169
|
+
bob = authors(:bob)
|
|
1170
|
+
|
|
1171
|
+
AuthorFavorite.create!(author: mary, favorite_author: bob)
|
|
1172
|
+
|
|
1173
|
+
assert_queries_count(3) do
|
|
1174
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [mary], associations: [:posts, favorite_authors: :posts])
|
|
1175
|
+
preloader.call
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
assert_no_queries do
|
|
1179
|
+
mary.posts
|
|
1180
|
+
mary.favorite_authors.map(&:posts)
|
|
1181
|
+
end
|
|
1182
|
+
end
|
|
1183
|
+
|
|
1184
|
+
def test_preload_can_group_multi_level_ping_pong_through
|
|
1185
|
+
skip "DB2 does not support this CLOB string operation pattern" if current_adapter?(:IBM_DBAdapter)
|
|
1186
|
+
|
|
1187
|
+
mary = authors(:mary)
|
|
1188
|
+
bob = authors(:bob)
|
|
1189
|
+
|
|
1190
|
+
AuthorFavorite.create!(author: mary, favorite_author: bob)
|
|
1191
|
+
|
|
1192
|
+
associations = { similar_posts: :comments, favorite_authors: { similar_posts: :comments } }
|
|
1193
|
+
|
|
1194
|
+
assert_queries_count(9) do
|
|
1195
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [mary], associations: associations)
|
|
1196
|
+
preloader.call
|
|
1197
|
+
end
|
|
1198
|
+
|
|
1199
|
+
assert_no_queries do
|
|
1200
|
+
mary.similar_posts.map(&:comments).each(&:to_a)
|
|
1201
|
+
mary.favorite_authors.flat_map(&:similar_posts).map(&:comments).each(&:to_a)
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1204
|
+
# Preloading with automatic scope inversing reduces the number of queries
|
|
1205
|
+
tag_reflection = Tagging.reflect_on_association(:tag)
|
|
1206
|
+
taggings_reflection = Tag.reflect_on_association(:taggings)
|
|
1207
|
+
|
|
1208
|
+
assert tag_reflection.scope
|
|
1209
|
+
assert_not taggings_reflection.scope
|
|
1210
|
+
|
|
1211
|
+
with_automatic_scope_inversing(tag_reflection, taggings_reflection) do
|
|
1212
|
+
mary.reload
|
|
1213
|
+
|
|
1214
|
+
assert_queries_count(8) do
|
|
1215
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [mary], associations: associations)
|
|
1216
|
+
preloader.call
|
|
1217
|
+
end
|
|
1218
|
+
end
|
|
1219
|
+
end
|
|
1220
|
+
|
|
1221
|
+
def test_preload_does_not_group_same_class_different_scope
|
|
1222
|
+
post = posts(:welcome)
|
|
1223
|
+
postesque = Postesque.create(author: Author.last)
|
|
1224
|
+
postesque.reload
|
|
1225
|
+
|
|
1226
|
+
# When the scopes differ in the generated SQL:
|
|
1227
|
+
# SELECT "authors".* FROM "authors" WHERE (name LIKE '%a%') AND "authors"."id" = ?
|
|
1228
|
+
# SELECT "authors".* FROM "authors" WHERE "authors"."id" = ?.
|
|
1229
|
+
assert_queries_count(2) do
|
|
1230
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [post, postesque], associations: :author_with_the_letter_a)
|
|
1231
|
+
preloader.call
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
assert_no_queries do
|
|
1235
|
+
post.author_with_the_letter_a
|
|
1236
|
+
postesque.author_with_the_letter_a
|
|
1237
|
+
end
|
|
1238
|
+
|
|
1239
|
+
post.reload
|
|
1240
|
+
postesque.reload
|
|
1241
|
+
|
|
1242
|
+
# When the generated SQL is identical, but one scope has preload values.
|
|
1243
|
+
assert_queries_count(3) do
|
|
1244
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [post, postesque], associations: :author_with_address)
|
|
1245
|
+
preloader.call
|
|
1246
|
+
end
|
|
1247
|
+
|
|
1248
|
+
assert_no_queries do
|
|
1249
|
+
post.author_with_address
|
|
1250
|
+
postesque.author_with_address
|
|
1251
|
+
end
|
|
1252
|
+
end
|
|
1253
|
+
|
|
1254
|
+
def test_preload_does_not_group_same_scope_different_key_name
|
|
1255
|
+
post = posts(:welcome)
|
|
1256
|
+
postesque = Postesque.create(author: Author.last)
|
|
1257
|
+
postesque.reload
|
|
1258
|
+
|
|
1259
|
+
assert_queries_count(2) do
|
|
1260
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [post, postesque], associations: :author)
|
|
1261
|
+
preloader.call
|
|
1262
|
+
end
|
|
1263
|
+
|
|
1264
|
+
assert_no_queries do
|
|
1265
|
+
post.author
|
|
1266
|
+
postesque.author
|
|
1267
|
+
end
|
|
1268
|
+
end
|
|
1269
|
+
|
|
1270
|
+
def test_multi_database_polymorphic_preload_with_same_table_name
|
|
1271
|
+
dog = dogs(:sophie)
|
|
1272
|
+
dog_comment = comments(:greetings)
|
|
1273
|
+
dog_comment.origin_type = dog.class.name
|
|
1274
|
+
dog_comment.origin_id = dog.id
|
|
1275
|
+
|
|
1276
|
+
other_dog = other_dogs(:lassie)
|
|
1277
|
+
other_dog_comment = comments(:more_greetings)
|
|
1278
|
+
other_dog_comment.origin_type = other_dog.class.name
|
|
1279
|
+
other_dog_comment.origin_id = other_dog.id
|
|
1280
|
+
|
|
1281
|
+
# Both Dog and OtherDog are backed by a table named `dogs`,
|
|
1282
|
+
# however they are stored in different databases and should
|
|
1283
|
+
# therefore result in two separate queries rather than be batched
|
|
1284
|
+
# together.
|
|
1285
|
+
#
|
|
1286
|
+
# Expected
|
|
1287
|
+
# SELECT FROM dogs ... (Dog)
|
|
1288
|
+
# SELECT FROM dogs ... (OtherDog)
|
|
1289
|
+
assert_queries_count(2) do
|
|
1290
|
+
preloader = ActiveRecord::Associations::Preloader.new(records: [dog_comment, other_dog_comment], associations: :origin)
|
|
1291
|
+
preloader.call
|
|
1292
|
+
end
|
|
1293
|
+
end
|
|
1294
|
+
|
|
1295
|
+
def test_preload_with_available_records
|
|
1296
|
+
post = posts(:welcome)
|
|
1297
|
+
david = authors(:david)
|
|
1298
|
+
|
|
1299
|
+
assert_no_queries do
|
|
1300
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author, available_records: [[david]]).call
|
|
1301
|
+
|
|
1302
|
+
assert_predicate post.association(:author), :loaded?
|
|
1303
|
+
assert_same david, post.author
|
|
1304
|
+
end
|
|
1305
|
+
end
|
|
1306
|
+
|
|
1307
|
+
def test_preload_with_available_records_sti
|
|
1308
|
+
book = Book.create!
|
|
1309
|
+
essay_special = EssaySpecial.create!
|
|
1310
|
+
book.essay = essay_special
|
|
1311
|
+
book.save!
|
|
1312
|
+
book.reload
|
|
1313
|
+
|
|
1314
|
+
assert_not_predicate book.association(:essay), :loaded?
|
|
1315
|
+
|
|
1316
|
+
assert_no_queries do
|
|
1317
|
+
ActiveRecord::Associations::Preloader.new(records: [book], associations: :essay, available_records: [[essay_special]]).call
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
assert_predicate book.association(:essay), :loaded?
|
|
1321
|
+
assert_same essay_special, book.essay
|
|
1322
|
+
end
|
|
1323
|
+
|
|
1324
|
+
def test_preload_with_only_some_records_available
|
|
1325
|
+
bob_post = posts(:misc_by_bob)
|
|
1326
|
+
mary_post = posts(:misc_by_mary)
|
|
1327
|
+
bob = authors(:bob)
|
|
1328
|
+
mary = authors(:mary)
|
|
1329
|
+
|
|
1330
|
+
assert_queries_count(1) do
|
|
1331
|
+
ActiveRecord::Associations::Preloader.new(records: [bob_post, mary_post], associations: :author, available_records: [bob]).call
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
assert_no_queries do
|
|
1335
|
+
assert_same bob, bob_post.author
|
|
1336
|
+
assert_equal mary, mary_post.author
|
|
1337
|
+
end
|
|
1338
|
+
end
|
|
1339
|
+
|
|
1340
|
+
def test_preload_with_some_records_already_loaded
|
|
1341
|
+
bob_post = posts(:misc_by_bob)
|
|
1342
|
+
mary_post = posts(:misc_by_mary)
|
|
1343
|
+
bob = bob_post.author
|
|
1344
|
+
mary = authors(:mary)
|
|
1345
|
+
|
|
1346
|
+
assert_predicate bob_post.association(:author), :loaded?
|
|
1347
|
+
assert_not mary_post.association(:author).loaded?
|
|
1348
|
+
|
|
1349
|
+
assert_queries_count(1) do
|
|
1350
|
+
ActiveRecord::Associations::Preloader.new(records: [bob_post, mary_post], associations: :author).call
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
assert_no_queries do
|
|
1354
|
+
assert_same bob, bob_post.author
|
|
1355
|
+
assert_equal mary, mary_post.author
|
|
1356
|
+
end
|
|
1357
|
+
end
|
|
1358
|
+
|
|
1359
|
+
def test_preload_with_available_records_with_through_association
|
|
1360
|
+
author = authors(:david)
|
|
1361
|
+
categories = Category.all.to_a
|
|
1362
|
+
|
|
1363
|
+
assert_queries_count(1) do
|
|
1364
|
+
# One query to get the middle records (i.e. essays)
|
|
1365
|
+
ActiveRecord::Associations::Preloader.new(records: [author], associations: :essay_category, available_records: categories).call
|
|
1366
|
+
end
|
|
1367
|
+
|
|
1368
|
+
assert_predicate author.association(:essay_category), :loaded?
|
|
1369
|
+
assert categories.map(&:__id__).include?(author.essay_category.__id__)
|
|
1370
|
+
end
|
|
1371
|
+
|
|
1372
|
+
def test_preload_with_only_some_records_available_with_through_associations
|
|
1373
|
+
mary = authors(:mary)
|
|
1374
|
+
mary_essay = essays(:mary_stay_home)
|
|
1375
|
+
mary_category = categories(:technology)
|
|
1376
|
+
mary_essay.update!(category: mary_category)
|
|
1377
|
+
|
|
1378
|
+
dave = authors(:david)
|
|
1379
|
+
dave_category = categories(:general)
|
|
1380
|
+
|
|
1381
|
+
assert_queries_count(2) do
|
|
1382
|
+
ActiveRecord::Associations::Preloader.new(records: [mary, dave], associations: :essay_category, available_records: [mary_category]).call
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
assert_no_queries do
|
|
1386
|
+
assert_same mary_category, mary.essay_category
|
|
1387
|
+
assert_equal dave_category, dave.essay_category
|
|
1388
|
+
end
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
def test_preload_with_available_records_with_multiple_classes
|
|
1392
|
+
essay = essays(:david_modest_proposal)
|
|
1393
|
+
general = categories(:general)
|
|
1394
|
+
david = authors(:david)
|
|
1395
|
+
|
|
1396
|
+
assert_no_queries do
|
|
1397
|
+
ActiveRecord::Associations::Preloader.new(records: [essay], associations: [:category, :author], available_records: [general, david]).call
|
|
1398
|
+
|
|
1399
|
+
assert_predicate essay.association(:category), :loaded?
|
|
1400
|
+
assert_predicate essay.association(:author), :loaded?
|
|
1401
|
+
assert_same general, essay.category
|
|
1402
|
+
assert_same david, essay.author
|
|
1403
|
+
end
|
|
1404
|
+
end
|
|
1405
|
+
|
|
1406
|
+
def test_preload_with_available_records_queries_when_scoped
|
|
1407
|
+
post = posts(:welcome)
|
|
1408
|
+
david = authors(:david)
|
|
1409
|
+
|
|
1410
|
+
assert_queries_count(1) do
|
|
1411
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author, scope: Author.where(name: "David"), available_records: [david]).call
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
assert_predicate post.association(:author), :loaded?
|
|
1415
|
+
assert_not_equal david.__id__, post.author.__id__
|
|
1416
|
+
end
|
|
1417
|
+
|
|
1418
|
+
def test_preload_with_available_records_queries_when_collection
|
|
1419
|
+
post = posts(:welcome)
|
|
1420
|
+
comments = Comment.all.to_a
|
|
1421
|
+
|
|
1422
|
+
assert_queries_count(1) do
|
|
1423
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments, available_records: comments).call
|
|
1424
|
+
end
|
|
1425
|
+
|
|
1426
|
+
assert_predicate post.association(:comments), :loaded?
|
|
1427
|
+
assert_empty post.comments.map(&:__id__) & comments.map(&:__id__)
|
|
1428
|
+
end
|
|
1429
|
+
|
|
1430
|
+
def test_preload_with_available_records_queries_when_incomplete
|
|
1431
|
+
post = posts(:welcome)
|
|
1432
|
+
bob = authors(:bob)
|
|
1433
|
+
david = authors(:david)
|
|
1434
|
+
|
|
1435
|
+
assert_queries_count(1) do
|
|
1436
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author, available_records: [bob]).call
|
|
1437
|
+
end
|
|
1438
|
+
|
|
1439
|
+
assert_no_queries do
|
|
1440
|
+
assert_predicate post.association(:author), :loaded?
|
|
1441
|
+
assert_equal david, post.author
|
|
1442
|
+
end
|
|
1443
|
+
end
|
|
1444
|
+
|
|
1445
|
+
def test_preload_with_unpersisted_records_no_ops
|
|
1446
|
+
author = Author.new
|
|
1447
|
+
new_post_with_author = Post.new(author: author)
|
|
1448
|
+
new_post_without_author = Post.new
|
|
1449
|
+
posts = [new_post_with_author, new_post_without_author]
|
|
1450
|
+
|
|
1451
|
+
assert_no_queries do
|
|
1452
|
+
ActiveRecord::Associations::Preloader.new(records: posts, associations: :author).call
|
|
1453
|
+
|
|
1454
|
+
assert_same author, new_post_with_author.author
|
|
1455
|
+
assert_nil new_post_without_author.author
|
|
1456
|
+
end
|
|
1457
|
+
end
|
|
1458
|
+
|
|
1459
|
+
def test_preload_with_unpersisted_records_with_composite_foreign_key_no_ops
|
|
1460
|
+
skip "DB2 preloader currently materializes persisted CPK order records for nil composite keys" if current_adapter?(:IBM_DBAdapter)
|
|
1461
|
+
|
|
1462
|
+
order = Cpk::Order.new
|
|
1463
|
+
new_book_with_order = Cpk::Book.new(order: order)
|
|
1464
|
+
new_book_without_order = Cpk::Book.new
|
|
1465
|
+
books = [new_book_with_order, new_book_without_order]
|
|
1466
|
+
|
|
1467
|
+
assert_no_queries do
|
|
1468
|
+
ActiveRecord::Associations::Preloader.new(records: books, associations: :order).call
|
|
1469
|
+
|
|
1470
|
+
assert_same order, new_book_with_order.order
|
|
1471
|
+
assert_nil new_book_without_order.order
|
|
1472
|
+
end
|
|
1473
|
+
end
|
|
1474
|
+
|
|
1475
|
+
def test_preload_wont_set_the_wrong_target
|
|
1476
|
+
post = posts(:welcome)
|
|
1477
|
+
post.update!(author_id: 54321)
|
|
1478
|
+
some_other_record = categories(:general)
|
|
1479
|
+
some_other_record.update!(id: 54321)
|
|
1480
|
+
|
|
1481
|
+
assert_raises do
|
|
1482
|
+
some_other_record.association(:author)
|
|
1483
|
+
end
|
|
1484
|
+
|
|
1485
|
+
assert_nothing_raised do
|
|
1486
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author, available_records: [[some_other_record]]).call
|
|
1487
|
+
assert_predicate post.association(:author), :loaded?
|
|
1488
|
+
assert_not_equal some_other_record, post.author
|
|
1489
|
+
end
|
|
1490
|
+
end
|
|
1491
|
+
|
|
1492
|
+
def test_preload_has_many_association_with_composite_foreign_key
|
|
1493
|
+
blog_post = sharded_blog_posts(:great_post_blog_one)
|
|
1494
|
+
blog_posts = [blog_post, sharded_blog_posts(:great_post_blog_two)]
|
|
1495
|
+
|
|
1496
|
+
::ActiveRecord::Associations::Preloader.new(records: blog_posts, associations: [:comments]).call
|
|
1497
|
+
|
|
1498
|
+
assert_predicate blog_post.association(:comments), :loaded?
|
|
1499
|
+
assert_includes(blog_post.comments.to_a, sharded_comments(:great_comment_blog_post_one))
|
|
1500
|
+
end
|
|
1501
|
+
|
|
1502
|
+
def test_preload_belongs_to_association_with_composite_foreign_key
|
|
1503
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
1504
|
+
comments = [comment, sharded_comments(:great_comment_blog_post_two)]
|
|
1505
|
+
|
|
1506
|
+
ActiveRecord::Associations::Preloader.new(records: comments, associations: :blog_post).call
|
|
1507
|
+
|
|
1508
|
+
assert_predicate comment.association(:blog_post), :loaded?
|
|
1509
|
+
assert_equal sharded_blog_posts(:great_post_blog_one), comment.blog_post
|
|
1510
|
+
end
|
|
1511
|
+
|
|
1512
|
+
def test_preload_loaded_belongs_to_association_with_composite_foreign_key
|
|
1513
|
+
comment = sharded_comments(:great_comment_blog_post_one)
|
|
1514
|
+
comment.blog_post
|
|
1515
|
+
|
|
1516
|
+
assert_no_queries do
|
|
1517
|
+
ActiveRecord::Associations::Preloader.new(records: [comment], associations: :blog_post).call
|
|
1518
|
+
end
|
|
1519
|
+
end
|
|
1520
|
+
|
|
1521
|
+
def test_preload_has_many_through_association_with_composite_query_constraints
|
|
1522
|
+
tag = sharded_tags(:short_read_blog_one)
|
|
1523
|
+
|
|
1524
|
+
tags = [tag, sharded_tags(:breaking_news_blog_2)]
|
|
1525
|
+
|
|
1526
|
+
ActiveRecord::Associations::Preloader.new(records: tags, associations: :blog_posts).call
|
|
1527
|
+
|
|
1528
|
+
assert tags.all? { |tag| tag.association(:blog_posts).loaded? }
|
|
1529
|
+
|
|
1530
|
+
expected_blog_post_ids = Sharded::BlogPostTag
|
|
1531
|
+
.where(blog_id: tag.blog_id, tag_id: tag.id)
|
|
1532
|
+
.pluck(:blog_post_id)
|
|
1533
|
+
|
|
1534
|
+
assert_not_empty(expected_blog_post_ids)
|
|
1535
|
+
|
|
1536
|
+
assert_equal(expected_blog_post_ids.sort, tag.blog_posts.map(&:id).sort)
|
|
1537
|
+
end
|
|
1538
|
+
|
|
1539
|
+
def test_preloads_has_many_on_model_with_a_composite_primary_key_through_id_attribute
|
|
1540
|
+
order = cpk_orders(:cpk_groceries_order_2)
|
|
1541
|
+
_shop_id, order_id = order.id
|
|
1542
|
+
order_agreements = Cpk::OrderAgreement.where(order_id: order_id).to_a
|
|
1543
|
+
|
|
1544
|
+
assert_not_empty order_agreements
|
|
1545
|
+
assert_equal order_agreements.sort, order.order_agreements.sort
|
|
1546
|
+
|
|
1547
|
+
loaded_order = nil
|
|
1548
|
+
sql = capture_sql do
|
|
1549
|
+
loaded_order = Cpk::Order.where(id: order_id).includes(:order_agreements).to_a.first
|
|
1550
|
+
end
|
|
1551
|
+
|
|
1552
|
+
assert_equal 2, sql.size
|
|
1553
|
+
preload_sql = sql.last
|
|
1554
|
+
|
|
1555
|
+
expectation = /SELECT.*WHERE.* (?:#{Regexp.escape(quote_table_name("cpk_order_agreements.order_id"))}|cpk_order_agreements\.order_id) = (\?|(\d+)|\$\d)$/
|
|
1556
|
+
|
|
1557
|
+
assert_match(expectation, preload_sql)
|
|
1558
|
+
assert_equal order_agreements.sort, loaded_order.order_agreements.sort
|
|
1559
|
+
end
|
|
1560
|
+
|
|
1561
|
+
def test_preloads_belongs_to_a_composite_primary_key_model_through_id_attribute
|
|
1562
|
+
order_agreement = cpk_order_agreements(:order_agreement_three)
|
|
1563
|
+
order = cpk_orders(:cpk_groceries_order_2)
|
|
1564
|
+
assert_equal order, order_agreement.order
|
|
1565
|
+
|
|
1566
|
+
loaded_order_agreement = nil
|
|
1567
|
+
sql = capture_sql do
|
|
1568
|
+
loaded_order_agreement = Cpk::OrderAgreement.where(id: order_agreement.id).includes(:order).to_a.first
|
|
1569
|
+
end
|
|
1570
|
+
|
|
1571
|
+
assert_equal 2, sql.size
|
|
1572
|
+
preload_sql = sql.last
|
|
1573
|
+
|
|
1574
|
+
expectation = /SELECT.*WHERE.* (?:#{Regexp.escape(quote_table_name("cpk_orders.id"))}|cpk_orders\.id) = (\?|(\d+)|\$\d)$/
|
|
1575
|
+
|
|
1576
|
+
assert_match(expectation, preload_sql)
|
|
1577
|
+
assert_equal order, loaded_order_agreement.order
|
|
1578
|
+
end
|
|
1579
|
+
|
|
1580
|
+
def test_preload_keeps_built_has_many_records_no_ops
|
|
1581
|
+
post = Post.new
|
|
1582
|
+
comment = post.comments.build
|
|
1583
|
+
|
|
1584
|
+
assert_no_queries do
|
|
1585
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments).call
|
|
1586
|
+
|
|
1587
|
+
assert_equal [comment], post.comments.to_a
|
|
1588
|
+
end
|
|
1589
|
+
end
|
|
1590
|
+
|
|
1591
|
+
def test_preload_keeps_built_has_many_records_with_composite_key_no_ops
|
|
1592
|
+
skip "DB2 preloader currently includes persisted CPK rows in this no-op scenario" if current_adapter?(:IBM_DBAdapter)
|
|
1593
|
+
|
|
1594
|
+
order = Cpk::Order.new
|
|
1595
|
+
book = order.books.build
|
|
1596
|
+
|
|
1597
|
+
assert_no_queries do
|
|
1598
|
+
ActiveRecord::Associations::Preloader.new(records: [order], associations: :books).call
|
|
1599
|
+
|
|
1600
|
+
assert_equal [book], order.books.to_a
|
|
1601
|
+
end
|
|
1602
|
+
end
|
|
1603
|
+
|
|
1604
|
+
def test_preload_keeps_built_has_many_records_after_query
|
|
1605
|
+
post = posts(:welcome)
|
|
1606
|
+
comment = post.comments.build
|
|
1607
|
+
|
|
1608
|
+
assert_queries_count(1) do
|
|
1609
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments).call
|
|
1610
|
+
|
|
1611
|
+
assert_includes post.comments.to_a, comment
|
|
1612
|
+
end
|
|
1613
|
+
end
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
def test_preload_keeps_built_belongs_to_records_no_ops
|
|
1617
|
+
post = Post.new
|
|
1618
|
+
author = post.build_author
|
|
1619
|
+
|
|
1620
|
+
assert_no_queries do
|
|
1621
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author).call
|
|
1622
|
+
|
|
1623
|
+
assert_same author, post.author
|
|
1624
|
+
end
|
|
1625
|
+
end
|
|
1626
|
+
|
|
1627
|
+
def test_preload_keeps_built_belongs_to_records_after_query
|
|
1628
|
+
post = posts(:welcome)
|
|
1629
|
+
author = post.build_author
|
|
1630
|
+
|
|
1631
|
+
assert_no_queries do
|
|
1632
|
+
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author).call
|
|
1633
|
+
|
|
1634
|
+
assert_same author, post.author
|
|
1635
|
+
end
|
|
1636
|
+
end
|
|
1637
|
+
|
|
1638
|
+
def test_preload_group_with_klass
|
|
1639
|
+
published_author = PublishedAuthor.create!(name: "PublishedAuthor")
|
|
1640
|
+
PublishedBook.create!(name: "PublishedBook", author_id: published_author.id, isbn: "12345")
|
|
1641
|
+
|
|
1642
|
+
author = Author.create!(name: "Author", published_author_id: published_author.id)
|
|
1643
|
+
Book.create!(name: "Book", author_id: author.id, isbn: "67890")
|
|
1644
|
+
|
|
1645
|
+
result = Author.includes(books: [], published_author: { books: [] }).last
|
|
1646
|
+
expected_klass = current_adapter?(:IBM_DBAdapter) ? Book : PublishedBook
|
|
1647
|
+
assert_equal [expected_klass], result.published_author.books.map(&:class)
|
|
1648
|
+
end
|
|
392
1649
|
end
|
|
393
1650
|
|
|
394
1651
|
class GeneratedMethodsTest < ActiveRecord::TestCase
|
|
@@ -422,7 +1679,7 @@ class GeneratedMethodsTest < ActiveRecord::TestCase
|
|
|
422
1679
|
end
|
|
423
1680
|
|
|
424
1681
|
class WithAnnotationsTest < ActiveRecord::TestCase
|
|
425
|
-
fixtures :pirates, :parrots, :treasures
|
|
1682
|
+
fixtures :pirates, :parrots, :parrots_pirates, :pirates, :treasures
|
|
426
1683
|
|
|
427
1684
|
def test_belongs_to_with_annotation_includes_a_query_comment
|
|
428
1685
|
pirate = SpacePirate.where.not(parrot_id: nil).first
|
|
@@ -434,7 +1691,7 @@ class WithAnnotationsTest < ActiveRecord::TestCase
|
|
|
434
1691
|
assert_not_predicate log, :empty?
|
|
435
1692
|
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
|
|
436
1693
|
|
|
437
|
-
|
|
1694
|
+
assert_queries_match(%r{/\* that tells jokes \*/}) do
|
|
438
1695
|
pirate.parrot_with_annotation
|
|
439
1696
|
end
|
|
440
1697
|
end
|
|
@@ -449,7 +1706,7 @@ class WithAnnotationsTest < ActiveRecord::TestCase
|
|
|
449
1706
|
assert_not_predicate log, :empty?
|
|
450
1707
|
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
|
|
451
1708
|
|
|
452
|
-
|
|
1709
|
+
assert_queries_match(%r{/\* that are very colorful \*/}) do
|
|
453
1710
|
pirate.parrots_with_annotation.first
|
|
454
1711
|
end
|
|
455
1712
|
end
|
|
@@ -464,7 +1721,7 @@ class WithAnnotationsTest < ActiveRecord::TestCase
|
|
|
464
1721
|
assert_not_predicate log, :empty?
|
|
465
1722
|
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
|
|
466
1723
|
|
|
467
|
-
|
|
1724
|
+
assert_queries_match(%r{/\* that is a rocket \*/}) do
|
|
468
1725
|
pirate.ship_with_annotation
|
|
469
1726
|
end
|
|
470
1727
|
end
|
|
@@ -479,7 +1736,7 @@ class WithAnnotationsTest < ActiveRecord::TestCase
|
|
|
479
1736
|
assert_not_predicate log, :empty?
|
|
480
1737
|
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
|
|
481
1738
|
|
|
482
|
-
|
|
1739
|
+
assert_queries_match(%r{/\* that are also parrots \*/}) do
|
|
483
1740
|
pirate.birds_with_annotation.first
|
|
484
1741
|
end
|
|
485
1742
|
end
|
|
@@ -494,7 +1751,7 @@ class WithAnnotationsTest < ActiveRecord::TestCase
|
|
|
494
1751
|
assert_not_predicate log, :empty?
|
|
495
1752
|
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
|
|
496
1753
|
|
|
497
|
-
|
|
1754
|
+
assert_queries_match(%r{/\* yarrr \*/}) do
|
|
498
1755
|
pirate.treasure_estimates_with_annotation.first
|
|
499
1756
|
end
|
|
500
1757
|
end
|
|
@@ -509,7 +1766,7 @@ class WithAnnotationsTest < ActiveRecord::TestCase
|
|
|
509
1766
|
assert_not_predicate log, :empty?
|
|
510
1767
|
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
|
|
511
1768
|
|
|
512
|
-
|
|
1769
|
+
assert_queries_match(%r{/\* yarrr \*/}) do
|
|
513
1770
|
SpacePirate.includes(:treasure_estimates_with_annotation, :treasures).first
|
|
514
1771
|
end
|
|
515
1772
|
end
|