ibm_db 5.1.0-x86-mingw32 → 5.3.2-x86-mingw32
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/CHANGES +9 -0
- data/LICENSE +55 -18
- data/ext/Makefile +14 -14
- data/ext/extconf.rb +4 -4
- data/ext/ibm_db.c +62 -57
- data/ext/ibm_db.o +0 -0
- data/ext/ibm_db.so +0 -0
- data/ext/mkmf.log +11 -11
- data/ext/ruby_ibm_db_cli.c +1 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
- data/lib/ibm_db.so +1 -0
- data/lib/mswin32/ibm_db.rb +7 -3
- data/lib/mswin32/rb2x/i386/ruby25/ibm_db.so +0 -0
- data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
- data/test/activejob/destroy_association_async_test.rb +305 -0
- data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
- data/test/activejob/helper.rb +15 -0
- data/test/assets/schema_dump_5_1.yml +345 -0
- data/test/cases/adapter_prevent_writes_test.rb +334 -0
- data/test/cases/adapter_test.rb +432 -218
- data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
- data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
- data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
- data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
- data/test/cases/adapters/mysql2/connection_test.rb +48 -50
- data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
- data/test/cases/adapters/mysql2/enum_test.rb +32 -11
- data/test/cases/adapters/mysql2/explain_test.rb +13 -11
- data/test/cases/adapters/mysql2/json_test.rb +17 -188
- data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
- data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
- data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
- data/test/cases/adapters/mysql2/schema_test.rb +24 -22
- data/test/cases/adapters/mysql2/set_test.rb +32 -0
- data/test/cases/adapters/mysql2/sp_test.rb +10 -8
- data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
- data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
- data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
- data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
- data/test/cases/adapters/postgresql/array_test.rb +118 -63
- data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
- data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
- data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
- data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
- data/test/cases/adapters/postgresql/citext_test.rb +58 -58
- data/test/cases/adapters/postgresql/collation_test.rb +17 -15
- data/test/cases/adapters/postgresql/composite_test.rb +25 -23
- data/test/cases/adapters/postgresql/connection_test.rb +73 -85
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
- data/test/cases/adapters/postgresql/date_test.rb +42 -0
- data/test/cases/adapters/postgresql/domain_test.rb +9 -7
- data/test/cases/adapters/postgresql/enum_test.rb +12 -10
- data/test/cases/adapters/postgresql/explain_test.rb +10 -8
- data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
- data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
- data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
- data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
- data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
- data/test/cases/adapters/postgresql/integer_test.rb +2 -0
- data/test/cases/adapters/postgresql/interval_test.rb +99 -0
- data/test/cases/adapters/postgresql/json_test.rb +16 -201
- data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
- data/test/cases/adapters/postgresql/money_test.rb +47 -16
- data/test/cases/adapters/postgresql/network_test.rb +36 -28
- data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
- data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
- data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
- data/test/cases/adapters/postgresql/range_test.rb +406 -292
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
- data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
- data/test/cases/adapters/postgresql/schema_test.rb +207 -91
- data/test/cases/adapters/postgresql/serial_test.rb +9 -7
- data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
- data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
- data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
- data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
- data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
- data/test/cases/adapters/postgresql/utils_test.rb +11 -9
- data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
- data/test/cases/adapters/postgresql/xml_test.rb +10 -14
- data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
- data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
- data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
- data/test/cases/adapters/sqlite3/json_test.rb +29 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
- data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
- data/test/cases/aggregations_test.rb +14 -12
- data/test/cases/annotate_test.rb +46 -0
- data/test/cases/ar_schema_test.rb +153 -86
- data/test/cases/arel/attributes/attribute_test.rb +1145 -0
- data/test/cases/arel/attributes/math_test.rb +83 -0
- data/test/cases/arel/attributes_test.rb +27 -0
- data/test/cases/arel/collectors/bind_test.rb +40 -0
- data/test/cases/arel/collectors/composite_test.rb +47 -0
- data/test/cases/arel/collectors/sql_string_test.rb +41 -0
- data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
- data/test/cases/arel/crud_test.rb +65 -0
- data/test/cases/arel/delete_manager_test.rb +53 -0
- data/test/cases/arel/factory_methods_test.rb +46 -0
- data/test/cases/arel/helper.rb +45 -0
- data/test/cases/arel/insert_manager_test.rb +241 -0
- data/test/cases/arel/nodes/and_test.rb +30 -0
- data/test/cases/arel/nodes/as_test.rb +36 -0
- data/test/cases/arel/nodes/ascending_test.rb +46 -0
- data/test/cases/arel/nodes/bin_test.rb +35 -0
- data/test/cases/arel/nodes/binary_test.rb +29 -0
- data/test/cases/arel/nodes/bind_param_test.rb +22 -0
- data/test/cases/arel/nodes/case_test.rb +96 -0
- data/test/cases/arel/nodes/casted_test.rb +18 -0
- data/test/cases/arel/nodes/comment_test.rb +22 -0
- data/test/cases/arel/nodes/count_test.rb +35 -0
- data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
- data/test/cases/arel/nodes/descending_test.rb +46 -0
- data/test/cases/arel/nodes/distinct_test.rb +21 -0
- data/test/cases/arel/nodes/equality_test.rb +62 -0
- data/test/cases/arel/nodes/extract_test.rb +43 -0
- data/test/cases/arel/nodes/false_test.rb +21 -0
- data/test/cases/arel/nodes/grouping_test.rb +26 -0
- data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
- data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
- data/test/cases/arel/nodes/named_function_test.rb +48 -0
- data/test/cases/arel/nodes/node_test.rb +22 -0
- data/test/cases/arel/nodes/not_test.rb +31 -0
- data/test/cases/arel/nodes/or_test.rb +36 -0
- data/test/cases/arel/nodes/over_test.rb +69 -0
- data/test/cases/arel/nodes/select_core_test.rb +79 -0
- data/test/cases/arel/nodes/select_statement_test.rb +51 -0
- data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
- data/test/cases/arel/nodes/sum_test.rb +35 -0
- data/test/cases/arel/nodes/table_alias_test.rb +29 -0
- data/test/cases/arel/nodes/true_test.rb +21 -0
- data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
- data/test/cases/arel/nodes/update_statement_test.rb +60 -0
- data/test/cases/arel/nodes/window_test.rb +81 -0
- data/test/cases/arel/nodes_test.rb +34 -0
- data/test/cases/arel/select_manager_test.rb +1238 -0
- data/test/cases/arel/support/fake_record.rb +135 -0
- data/test/cases/arel/table_test.rb +216 -0
- data/test/cases/arel/update_manager_test.rb +126 -0
- data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
- data/test/cases/arel/visitors/dot_test.rb +90 -0
- data/test/cases/arel/visitors/mysql_test.rb +157 -0
- data/test/cases/arel/visitors/postgres_test.rb +366 -0
- data/test/cases/arel/visitors/sqlite_test.rb +75 -0
- data/test/cases/arel/visitors/to_sql_test.rb +750 -0
- data/test/cases/associations/belongs_to_associations_test.rb +510 -158
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
- data/test/cases/associations/callbacks_test.rb +56 -38
- data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
- data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
- data/test/cases/associations/eager_singularization_test.rb +21 -21
- data/test/cases/associations/eager_test.rb +559 -415
- data/test/cases/associations/extension_test.rb +18 -12
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
- data/test/cases/associations/has_many_associations_test.rb +1038 -465
- data/test/cases/associations/has_many_through_associations_test.rb +558 -249
- data/test/cases/associations/has_one_associations_test.rb +294 -129
- data/test/cases/associations/has_one_through_associations_test.rb +121 -75
- data/test/cases/associations/inner_join_association_test.rb +114 -38
- data/test/cases/associations/inverse_associations_test.rb +606 -398
- data/test/cases/associations/join_model_test.rb +158 -148
- data/test/cases/associations/left_outer_join_association_test.rb +59 -24
- data/test/cases/associations/nested_through_associations_test.rb +166 -109
- data/test/cases/associations/required_test.rb +35 -10
- data/test/cases/associations_test.rb +241 -110
- data/test/cases/attribute_methods/read_test.rb +11 -11
- data/test/cases/attribute_methods_test.rb +413 -298
- data/test/cases/attributes_test.rb +145 -27
- data/test/cases/autosave_association_test.rb +681 -436
- data/test/cases/base_prevent_writes_test.rb +229 -0
- data/test/cases/base_test.rb +599 -542
- data/test/cases/batches_test.rb +288 -82
- data/test/cases/binary_test.rb +26 -31
- data/test/cases/bind_parameter_test.rb +194 -21
- data/test/cases/boolean_test.rb +52 -0
- data/test/cases/cache_key_test.rb +110 -5
- data/test/cases/calculations_test.rb +740 -177
- data/test/cases/callbacks_test.rb +74 -207
- data/test/cases/clone_test.rb +15 -10
- data/test/cases/coders/json_test.rb +2 -0
- data/test/cases/coders/yaml_column_test.rb +16 -13
- data/test/cases/collection_cache_key_test.rb +177 -20
- data/test/cases/column_alias_test.rb +9 -7
- data/test/cases/column_definition_test.rb +10 -68
- data/test/cases/comment_test.rb +166 -107
- data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
- data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
- data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
- data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
- data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
- data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
- data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
- data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
- data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
- data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
- data/test/cases/connection_management_test.rb +13 -11
- data/test/cases/connection_pool_test.rb +316 -83
- data/test/cases/core_test.rb +82 -58
- data/test/cases/counter_cache_test.rb +204 -50
- data/test/cases/custom_locking_test.rb +5 -3
- data/test/cases/database_configurations/hash_config_test.rb +74 -0
- data/test/cases/database_configurations/resolver_test.rb +150 -0
- data/test/cases/database_configurations_test.rb +145 -0
- data/test/cases/database_selector_test.rb +296 -0
- data/test/cases/database_statements_test.rb +18 -16
- data/test/cases/date_test.rb +8 -16
- data/test/cases/date_time_precision_test.rb +100 -78
- data/test/cases/date_time_test.rb +23 -8
- data/test/cases/defaults_test.rb +106 -71
- data/test/cases/delegated_type_test.rb +57 -0
- data/test/cases/dirty_test.rb +419 -223
- data/test/cases/disconnected_test.rb +6 -6
- data/test/cases/dup_test.rb +54 -27
- data/test/cases/enum_test.rb +461 -82
- data/test/cases/errors_test.rb +7 -7
- data/test/cases/explain_subscriber_test.rb +17 -15
- data/test/cases/explain_test.rb +11 -19
- data/test/cases/filter_attributes_test.rb +153 -0
- data/test/cases/finder_respond_to_test.rb +14 -14
- data/test/cases/finder_test.rb +669 -287
- data/test/cases/fixture_set/file_test.rb +34 -38
- data/test/cases/fixtures_test.rb +833 -176
- data/test/cases/forbidden_attributes_protection_test.rb +32 -67
- data/test/cases/habtm_destroy_order_test.rb +25 -25
- data/test/cases/helper.rb +78 -49
- data/test/cases/hot_compatibility_test.rb +33 -32
- data/test/cases/i18n_test.rb +18 -17
- data/test/cases/inheritance_test.rb +180 -115
- data/test/cases/insert_all_test.rb +489 -0
- data/test/cases/instrumentation_test.rb +101 -0
- data/test/cases/integration_test.rb +119 -31
- data/test/cases/invalid_connection_test.rb +18 -16
- data/test/cases/invertible_migration_test.rb +183 -43
- data/test/cases/json_attribute_test.rb +35 -0
- data/test/cases/json_serialization_test.rb +57 -58
- data/test/cases/json_shared_test_cases.rb +290 -0
- data/test/cases/locking_test.rb +413 -119
- data/test/cases/log_subscriber_test.rb +68 -26
- data/test/cases/marshal_serialization_test.rb +39 -0
- data/test/cases/migration/change_schema_test.rb +118 -72
- data/test/cases/migration/change_table_test.rb +138 -30
- data/test/cases/migration/check_constraint_test.rb +162 -0
- data/test/cases/migration/column_attributes_test.rb +45 -35
- data/test/cases/migration/column_positioning_test.rb +18 -6
- data/test/cases/migration/columns_test.rb +93 -77
- data/test/cases/migration/command_recorder_test.rb +121 -34
- data/test/cases/migration/compatibility_test.rb +578 -23
- data/test/cases/migration/create_join_table_test.rb +35 -25
- data/test/cases/migration/foreign_key_test.rb +503 -284
- data/test/cases/migration/helper.rb +4 -3
- data/test/cases/migration/index_test.rb +119 -70
- data/test/cases/migration/logger_test.rb +9 -6
- data/test/cases/migration/pending_migrations_test.rb +88 -34
- data/test/cases/migration/references_foreign_key_test.rb +164 -150
- data/test/cases/migration/references_index_test.rb +38 -19
- data/test/cases/migration/references_statements_test.rb +15 -14
- data/test/cases/migration/rename_table_test.rb +53 -30
- data/test/cases/migration_test.rb +637 -269
- data/test/cases/migrator_test.rb +191 -135
- data/test/cases/mixin_test.rb +7 -11
- data/test/cases/modules_test.rb +36 -34
- data/test/cases/multi_db_migrator_test.rb +223 -0
- data/test/cases/multiparameter_attributes_test.rb +60 -33
- data/test/cases/multiple_db_test.rb +16 -22
- data/test/cases/nested_attributes_test.rb +341 -320
- data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
- data/test/cases/null_relation_test.rb +84 -0
- data/test/cases/numeric_data_test.rb +93 -0
- data/test/cases/persistence_test.rb +361 -269
- data/test/cases/pooled_connections_test.rb +18 -26
- data/test/cases/prepared_statement_status_test.rb +48 -0
- data/test/cases/primary_keys_test.rb +210 -104
- data/test/cases/query_cache_test.rb +610 -141
- data/test/cases/quoting_test.rb +132 -31
- data/test/cases/readonly_test.rb +49 -48
- data/test/cases/reaper_test.rb +146 -32
- data/test/cases/reflection_test.rb +167 -156
- data/test/cases/relation/delegation_test.rb +49 -36
- data/test/cases/relation/delete_all_test.rb +117 -0
- data/test/cases/relation/merging_test.rb +319 -42
- data/test/cases/relation/mutation_test.rb +55 -93
- data/test/cases/relation/or_test.rb +129 -29
- data/test/cases/relation/predicate_builder_test.rb +21 -6
- data/test/cases/relation/record_fetch_warning_test.rb +5 -3
- data/test/cases/relation/select_test.rb +67 -0
- data/test/cases/relation/update_all_test.rb +317 -0
- data/test/cases/relation/where_chain_test.rb +68 -32
- data/test/cases/relation/where_clause_test.rb +136 -61
- data/test/cases/relation/where_test.rb +155 -48
- data/test/cases/relation_test.rb +266 -112
- data/test/cases/relations_test.rb +969 -744
- data/test/cases/reload_models_test.rb +13 -9
- data/test/cases/reserved_word_test.rb +141 -0
- data/test/cases/result_test.rb +68 -17
- data/test/cases/sanitize_test.rb +87 -71
- data/test/cases/schema_dumper_test.rb +221 -128
- data/test/cases/schema_loading_test.rb +3 -2
- data/test/cases/scoping/default_scoping_test.rb +185 -144
- data/test/cases/scoping/named_scoping_test.rb +177 -89
- data/test/cases/scoping/relation_scoping_test.rb +197 -75
- data/test/cases/secure_token_test.rb +18 -3
- data/test/cases/serialization_test.rb +30 -28
- data/test/cases/serialized_attribute_test.rb +133 -42
- data/test/cases/signed_id_test.rb +168 -0
- data/test/cases/statement_cache_test.rb +41 -24
- data/test/cases/statement_invalid_test.rb +42 -0
- data/test/cases/store_test.rb +180 -55
- data/test/cases/strict_loading_test.rb +473 -0
- data/test/cases/suppressor_test.rb +26 -12
- data/test/cases/tasks/database_tasks_test.rb +1258 -194
- data/test/cases/tasks/mysql_rake_test.rb +370 -298
- data/test/cases/tasks/postgresql_rake_test.rb +481 -251
- data/test/cases/tasks/sqlite_rake_test.rb +225 -178
- data/test/cases/test_case.rb +51 -40
- data/test/cases/test_databases_test.rb +79 -0
- data/test/cases/test_fixtures_test.rb +79 -19
- data/test/cases/time_precision_test.rb +98 -76
- data/test/cases/timestamp_test.rb +102 -99
- data/test/cases/touch_later_test.rb +12 -10
- data/test/cases/transaction_callbacks_test.rb +344 -90
- data/test/cases/transaction_isolation_test.rb +12 -12
- data/test/cases/transactions_test.rb +612 -162
- data/test/cases/type/adapter_specific_registry_test.rb +14 -2
- data/test/cases/type/date_time_test.rb +4 -2
- data/test/cases/type/integer_test.rb +4 -2
- data/test/cases/type/string_test.rb +10 -8
- data/test/cases/type/time_test.rb +28 -0
- data/test/cases/type/type_map_test.rb +29 -28
- data/test/cases/type/unsigned_integer_test.rb +19 -0
- data/test/cases/type_test.rb +2 -0
- data/test/cases/types_test.rb +3 -1
- data/test/cases/unconnected_test.rb +14 -1
- data/test/cases/unsafe_raw_sql_test.rb +274 -0
- data/test/cases/validations/absence_validation_test.rb +19 -17
- data/test/cases/validations/association_validation_test.rb +30 -28
- data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
- data/test/cases/validations/i18n_validation_test.rb +22 -21
- data/test/cases/validations/length_validation_test.rb +34 -33
- data/test/cases/validations/numericality_validation_test.rb +181 -0
- data/test/cases/validations/presence_validation_test.rb +21 -19
- data/test/cases/validations/uniqueness_validation_test.rb +156 -86
- data/test/cases/validations_repair_helper.rb +2 -0
- data/test/cases/validations_test.rb +61 -26
- data/test/cases/view_test.rb +122 -116
- data/test/cases/yaml_serialization_test.rb +79 -34
- data/test/config.example.yml +19 -19
- data/test/config.rb +3 -1
- data/test/config.yml +16 -6
- data/test/fixtures/all/namespaced/accounts.yml +2 -0
- data/test/fixtures/author_addresses.yml +1 -8
- data/test/fixtures/authors.yml +1 -7
- data/test/fixtures/binaries.yml +4 -0
- data/test/fixtures/books.yml +9 -2
- data/test/fixtures/categories_posts.yml +3 -0
- data/test/fixtures/citations.yml +5 -0
- data/test/fixtures/comments.yml +7 -0
- data/test/fixtures/companies.yml +5 -0
- data/test/fixtures/computers.yml +2 -0
- data/test/fixtures/customers.yml +10 -1
- data/test/fixtures/developers.yml +1 -1
- data/test/fixtures/essays.yml +10 -0
- data/test/fixtures/faces.yml +3 -3
- data/test/fixtures/humans.yml +5 -0
- data/test/fixtures/interests.yml +7 -7
- data/test/fixtures/memberships.yml +7 -0
- data/test/fixtures/minimalistics.yml +3 -0
- data/test/fixtures/mixed_case_monkeys.yml +2 -2
- data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
- data/test/fixtures/naked/yml/parrots.yml +1 -0
- data/test/fixtures/other_books.yml +26 -0
- data/test/fixtures/other_posts.yml +1 -0
- data/test/fixtures/parrots.yml +7 -1
- data/test/fixtures/pirates.yml +3 -0
- data/test/fixtures/posts.yml +11 -3
- data/test/fixtures/readers.yml +6 -0
- data/test/fixtures/reserved_words/values.yml +2 -2
- data/test/fixtures/sponsors.yml +3 -0
- data/test/fixtures/strict_zines.yml +2 -0
- data/test/fixtures/subscribers.yml +1 -1
- data/test/fixtures/tasks.yml +1 -1
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/migrations/10_urban/9_add_expressions.rb +2 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
- data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
- data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
- data/test/migrations/missing/1_people_have_last_names.rb +2 -0
- data/test/migrations/missing/3_we_need_reminders.rb +2 -0
- data/test/migrations/missing/4_innocent_jointable.rb +3 -1
- data/test/migrations/rename/1_we_need_things.rb +2 -0
- data/test/migrations/rename/2_rename_things.rb +2 -0
- data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
- data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
- data/test/migrations/to_copy2/1_create_articles.rb +2 -0
- data/test/migrations/to_copy2/2_create_comments.rb +3 -1
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
- data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
- data/test/migrations/valid/2_we_need_reminders.rb +2 -0
- data/test/migrations/valid/3_innocent_jointable.rb +3 -1
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
- data/test/models/account.rb +46 -0
- data/test/models/admin/account.rb +3 -1
- data/test/models/admin/randomly_named_c1.rb +2 -0
- data/test/models/admin/user.rb +16 -8
- data/test/models/admin.rb +4 -2
- data/test/models/aircraft.rb +3 -1
- data/test/models/arunit2_model.rb +2 -0
- data/test/models/author.rb +153 -102
- data/test/models/auto_id.rb +2 -0
- data/test/models/autoloadable/extra_firm.rb +2 -0
- data/test/models/binary.rb +3 -1
- data/test/models/binary_field.rb +6 -0
- data/test/models/bird.rb +13 -1
- data/test/models/book.rb +14 -4
- data/test/models/book_destroy_async.rb +24 -0
- data/test/models/boolean.rb +5 -0
- data/test/models/bulb.rb +13 -4
- data/test/models/cake_designer.rb +2 -0
- data/test/models/car.rb +17 -10
- data/test/models/carrier.rb +2 -0
- data/test/models/cart.rb +5 -0
- data/test/models/cat.rb +2 -0
- data/test/models/categorization.rb +8 -6
- data/test/models/category.rb +28 -16
- data/test/models/chef.rb +2 -0
- data/test/models/citation.rb +5 -1
- data/test/models/club.rb +13 -10
- data/test/models/college.rb +4 -2
- data/test/models/column.rb +2 -0
- data/test/models/column_name.rb +2 -0
- data/test/models/comment.rb +32 -10
- data/test/models/company.rb +102 -106
- data/test/models/company_in_module.rb +27 -26
- data/test/models/computer.rb +3 -1
- data/test/models/contact.rb +15 -13
- data/test/models/content.rb +5 -3
- data/test/models/contract.rb +21 -3
- data/test/models/country.rb +2 -4
- data/test/models/course.rb +3 -1
- data/test/models/customer.rb +10 -8
- data/test/models/customer_carrier.rb +2 -0
- data/test/models/dashboard.rb +2 -0
- data/test/models/default.rb +2 -0
- data/test/models/department.rb +2 -0
- data/test/models/destroy_async_parent.rb +15 -0
- data/test/models/destroy_async_parent_soft_delete.rb +20 -0
- data/test/models/developer.rb +152 -85
- data/test/models/dl_keyed_belongs_to.rb +13 -0
- data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
- data/test/models/dl_keyed_has_many.rb +5 -0
- data/test/models/dl_keyed_has_many_through.rb +5 -0
- data/test/models/dl_keyed_has_one.rb +5 -0
- data/test/models/dl_keyed_join.rb +10 -0
- data/test/models/dog.rb +2 -0
- data/test/models/dog_lover.rb +2 -0
- data/test/models/doubloon.rb +3 -1
- data/test/models/drink_designer.rb +17 -0
- data/test/models/edge.rb +4 -2
- data/test/models/electron.rb +2 -0
- data/test/models/engine.rb +3 -2
- data/test/models/entrant.rb +2 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +6 -3
- data/test/models/essay_destroy_async.rb +12 -0
- data/test/models/event.rb +3 -1
- data/test/models/eye.rb +5 -3
- data/test/models/face.rb +14 -6
- data/test/models/family.rb +6 -0
- data/test/models/family_tree.rb +6 -0
- data/test/models/friendship.rb +5 -3
- data/test/models/frog.rb +8 -0
- data/test/models/guid.rb +3 -1
- data/test/models/guitar.rb +2 -0
- data/test/models/hotel.rb +5 -3
- data/test/models/human.rb +39 -0
- data/test/models/image.rb +3 -1
- data/test/models/interest.rb +14 -3
- data/test/models/invoice.rb +4 -2
- data/test/models/item.rb +3 -1
- data/test/models/job.rb +5 -3
- data/test/models/joke.rb +4 -2
- data/test/models/keyboard.rb +3 -1
- data/test/models/legacy_thing.rb +2 -0
- data/test/models/lesson.rb +2 -0
- data/test/models/line_item.rb +3 -1
- data/test/models/liquid.rb +2 -0
- data/test/models/matey.rb +3 -1
- data/test/models/measurement.rb +4 -0
- data/test/models/member.rb +23 -20
- data/test/models/member_detail.rb +3 -0
- data/test/models/member_type.rb +2 -0
- data/test/models/membership.rb +4 -1
- data/test/models/mentor.rb +3 -1
- data/test/models/message.rb +5 -0
- data/test/models/minimalistic.rb +2 -0
- data/test/models/minivan.rb +3 -2
- data/test/models/mixed_case_monkey.rb +3 -1
- data/test/models/molecule.rb +2 -0
- data/test/models/mouse.rb +6 -0
- data/test/models/movie.rb +2 -0
- data/test/models/node.rb +4 -2
- data/test/models/non_primary_key.rb +2 -0
- data/test/models/notification.rb +2 -0
- data/test/models/numeric_data.rb +12 -0
- data/test/models/order.rb +4 -2
- data/test/models/organization.rb +9 -7
- data/test/models/other_dog.rb +3 -1
- data/test/models/owner.rb +6 -4
- data/test/models/parrot.rb +12 -4
- data/test/models/person.rb +59 -54
- data/test/models/personal_legacy_thing.rb +3 -1
- data/test/models/pet.rb +4 -2
- data/test/models/pet_treasure.rb +2 -0
- data/test/models/pirate.rb +67 -43
- data/test/models/possession.rb +3 -1
- data/test/models/post.rb +184 -86
- data/test/models/price_estimate.rb +11 -1
- data/test/models/professor.rb +3 -1
- data/test/models/project.rb +14 -12
- data/test/models/publisher/article.rb +2 -0
- data/test/models/publisher/magazine.rb +2 -0
- data/test/models/publisher.rb +2 -0
- data/test/models/randomly_named_c1.rb +2 -0
- data/test/models/rating.rb +5 -1
- data/test/models/reader.rb +7 -5
- data/test/models/recipe.rb +2 -0
- data/test/models/record.rb +2 -0
- data/test/models/reference.rb +6 -3
- data/test/models/reply.rb +39 -21
- data/test/models/room.rb +6 -0
- data/test/models/section.rb +6 -0
- data/test/models/seminar.rb +6 -0
- data/test/models/session.rb +6 -0
- data/test/models/ship.rb +12 -9
- data/test/models/ship_part.rb +5 -3
- data/test/models/shop.rb +4 -2
- data/test/models/shop_account.rb +2 -0
- data/test/models/speedometer.rb +2 -0
- data/test/models/sponsor.rb +8 -5
- data/test/models/squeak.rb +6 -0
- data/test/models/strict_zine.rb +7 -0
- data/test/models/string_key_object.rb +2 -0
- data/test/models/student.rb +2 -0
- data/test/models/subscriber.rb +4 -2
- data/test/models/subscription.rb +5 -1
- data/test/models/tag.rb +6 -3
- data/test/models/tagging.rb +13 -6
- data/test/models/task.rb +2 -0
- data/test/models/topic.rb +54 -19
- data/test/models/toy.rb +4 -0
- data/test/models/traffic_light.rb +2 -0
- data/test/models/treasure.rb +5 -3
- data/test/models/treaty.rb +2 -4
- data/test/models/tree.rb +2 -0
- data/test/models/tuning_peg.rb +2 -0
- data/test/models/tyre.rb +2 -0
- data/test/models/user.rb +12 -4
- data/test/models/uuid_child.rb +2 -0
- data/test/models/uuid_item.rb +2 -0
- data/test/models/uuid_parent.rb +2 -0
- data/test/models/vegetables.rb +12 -3
- data/test/models/vertex.rb +6 -4
- data/test/models/warehouse_thing.rb +2 -0
- data/test/models/wheel.rb +3 -1
- data/test/models/without_table.rb +3 -1
- data/test/models/zine.rb +3 -1
- data/test/schema/mysql2_specific_schema.rb +49 -35
- data/test/schema/oracle_specific_schema.rb +13 -15
- data/test/schema/postgresql_specific_schema.rb +51 -40
- data/test/schema/schema.rb +334 -154
- data/test/schema/sqlite_specific_schema.rb +9 -16
- data/test/support/config.rb +26 -26
- data/test/support/connection.rb +14 -8
- data/test/support/connection_helper.rb +3 -1
- data/test/support/ddl_helper.rb +2 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
- data/test/support/schema_dumping_helper.rb +2 -0
- data/test/support/stubs/strong_parameters.rb +40 -0
- data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
- data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
- metadata +196 -11
@@ -1,56 +1,90 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
27
|
-
require
|
28
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cases/helper"
|
4
|
+
require "models/author"
|
5
|
+
require "models/book"
|
6
|
+
require "models/bird"
|
7
|
+
require "models/post"
|
8
|
+
require "models/comment"
|
9
|
+
require "models/category"
|
10
|
+
require "models/company"
|
11
|
+
require "models/contract"
|
12
|
+
require "models/customer"
|
13
|
+
require "models/developer"
|
14
|
+
require "models/computer"
|
15
|
+
require "models/invoice"
|
16
|
+
require "models/line_item"
|
17
|
+
require "models/mouse"
|
18
|
+
require "models/order"
|
19
|
+
require "models/parrot"
|
20
|
+
require "models/pirate"
|
21
|
+
require "models/project"
|
22
|
+
require "models/ship"
|
23
|
+
require "models/ship_part"
|
24
|
+
require "models/squeak"
|
25
|
+
require "models/tag"
|
26
|
+
require "models/tagging"
|
27
|
+
require "models/treasure"
|
28
|
+
require "models/eye"
|
29
|
+
require "models/electron"
|
30
|
+
require "models/molecule"
|
31
|
+
require "models/member"
|
32
|
+
require "models/member_detail"
|
33
|
+
require "models/organization"
|
34
|
+
require "models/guitar"
|
35
|
+
require "models/tuning_peg"
|
36
|
+
require "models/reply"
|
29
37
|
|
30
38
|
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
|
31
|
-
def
|
39
|
+
def test_autosave_works_even_when_other_callbacks_update_the_parent_model
|
40
|
+
reference = Class.new(ActiveRecord::Base) do
|
41
|
+
self.table_name = "references"
|
42
|
+
def self.name; "Reference"; end
|
43
|
+
end
|
44
|
+
|
45
|
+
person = Class.new(ActiveRecord::Base) do
|
46
|
+
self.table_name = "people"
|
47
|
+
def self.name; "Person"; end
|
48
|
+
|
49
|
+
# It is necessary that the after_create is before the has_many _and_ that it updates the model.
|
50
|
+
# This replicates a bug found in https://github.com/rails/rails/issues/38120
|
51
|
+
after_create { update(first_name: "first name") }
|
52
|
+
has_many :references, autosave: true, anonymous_class: reference
|
53
|
+
end
|
54
|
+
|
55
|
+
reference_instance = reference.create!
|
56
|
+
person_instance = person.create!(first_name: "foo", references: [reference_instance])
|
57
|
+
|
58
|
+
reference_instance.reload
|
59
|
+
assert_equal person_instance.id, reference_instance.person_id
|
60
|
+
assert_equal "first name", person_instance.first_name # Make sure the after_create is actually called
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_autosave_does_not_pass_through_non_custom_validation_contexts
|
32
64
|
person = Class.new(ActiveRecord::Base) {
|
33
|
-
self.table_name =
|
34
|
-
validate :should_be_cool, :
|
35
|
-
def self.name;
|
65
|
+
self.table_name = "people"
|
66
|
+
validate :should_be_cool, on: :create
|
67
|
+
def self.name; "Person"; end
|
36
68
|
|
37
69
|
private
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
70
|
+
def should_be_cool
|
71
|
+
unless first_name == "cool"
|
72
|
+
errors.add :first_name, "not cool"
|
73
|
+
end
|
42
74
|
end
|
43
|
-
end
|
44
75
|
}
|
45
76
|
reference = Class.new(ActiveRecord::Base) {
|
46
77
|
self.table_name = "references"
|
47
|
-
def self.name;
|
78
|
+
def self.name; "Reference"; end
|
48
79
|
belongs_to :person, autosave: true, anonymous_class: person
|
49
80
|
}
|
50
81
|
|
51
|
-
u = person.create!(first_name:
|
52
|
-
u.
|
53
|
-
|
82
|
+
u = person.create!(first_name: "cool")
|
83
|
+
u.first_name = "nah"
|
84
|
+
|
85
|
+
assert_predicate u, :valid?
|
86
|
+
r = reference.new(person: u)
|
87
|
+
assert_predicate r, :valid?
|
54
88
|
end
|
55
89
|
|
56
90
|
def test_should_not_add_the_same_callbacks_multiple_times_for_has_one
|
@@ -73,60 +107,59 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
|
|
73
107
|
ship = ShipWithoutNestedAttributes.new
|
74
108
|
ship.prisoners.build
|
75
109
|
|
76
|
-
|
110
|
+
assert_not_predicate ship, :valid?
|
77
111
|
assert_equal 1, ship.errors[:name].length
|
78
112
|
end
|
79
113
|
|
80
114
|
private
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
115
|
+
def assert_no_difference_when_adding_callbacks_twice_for(model, association_name)
|
116
|
+
reflection = model.reflect_on_association(association_name)
|
117
|
+
assert_no_difference "callbacks_for_model(#{model.name}).length" do
|
118
|
+
model.send(:add_autosave_association_callbacks, reflection)
|
119
|
+
end
|
86
120
|
end
|
87
|
-
end
|
88
121
|
|
89
|
-
|
90
|
-
|
91
|
-
|
122
|
+
def callbacks_for_model(model)
|
123
|
+
model.instance_variables.grep(/_callbacks$/).flat_map do |ivar|
|
124
|
+
model.instance_variable_get(ivar)
|
125
|
+
end
|
92
126
|
end
|
93
|
-
end
|
94
127
|
end
|
95
128
|
|
96
129
|
class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
97
130
|
fixtures :companies, :accounts
|
98
131
|
|
99
132
|
def test_should_save_parent_but_not_invalid_child
|
100
|
-
firm = Firm.new(:
|
101
|
-
|
133
|
+
firm = Firm.new(name: "GlobalMegaCorp")
|
134
|
+
assert_predicate firm, :valid?
|
102
135
|
|
103
136
|
firm.build_account_using_primary_key
|
104
|
-
|
137
|
+
assert_not_predicate firm.build_account_using_primary_key, :valid?
|
105
138
|
|
106
139
|
assert firm.save
|
107
|
-
|
140
|
+
assert_not_predicate firm.account_using_primary_key, :persisted?
|
108
141
|
end
|
109
142
|
|
110
143
|
def test_save_fails_for_invalid_has_one
|
111
144
|
firm = Firm.first
|
112
|
-
|
145
|
+
assert_predicate firm, :valid?
|
113
146
|
|
114
147
|
firm.build_account
|
115
148
|
|
116
|
-
|
117
|
-
|
118
|
-
|
149
|
+
assert_not_predicate firm.account, :valid?
|
150
|
+
assert_not_predicate firm, :valid?
|
151
|
+
assert_not firm.save
|
119
152
|
assert_equal ["is invalid"], firm.errors["account"]
|
120
153
|
end
|
121
154
|
|
122
155
|
def test_save_succeeds_for_invalid_has_one_with_validate_false
|
123
156
|
firm = Firm.first
|
124
|
-
|
157
|
+
assert_predicate firm, :valid?
|
125
158
|
|
126
159
|
firm.build_unvalidated_account
|
127
160
|
|
128
|
-
|
129
|
-
|
161
|
+
assert_not_predicate firm.unvalidated_account, :valid?
|
162
|
+
assert_predicate firm, :valid?
|
130
163
|
assert firm.save
|
131
164
|
end
|
132
165
|
|
@@ -135,10 +168,10 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
|
|
135
168
|
|
136
169
|
account = firm.build_account("credit_limit" => 1000)
|
137
170
|
assert_equal account, firm.account
|
138
|
-
|
171
|
+
assert_not_predicate account, :persisted?
|
139
172
|
assert firm.save
|
140
173
|
assert_equal account, firm.account
|
141
|
-
|
174
|
+
assert_predicate account, :persisted?
|
142
175
|
end
|
143
176
|
|
144
177
|
def test_build_before_either_saved
|
@@ -146,16 +179,16 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
|
|
146
179
|
|
147
180
|
firm.account = account = Account.new("credit_limit" => 1000)
|
148
181
|
assert_equal account, firm.account
|
149
|
-
|
182
|
+
assert_not_predicate account, :persisted?
|
150
183
|
assert firm.save
|
151
184
|
assert_equal account, firm.account
|
152
|
-
|
185
|
+
assert_predicate account, :persisted?
|
153
186
|
end
|
154
187
|
|
155
188
|
def test_assignment_before_parent_saved
|
156
189
|
firm = Firm.new("name" => "GlobalMegaCorp")
|
157
190
|
firm.account = a = Account.find(1)
|
158
|
-
|
191
|
+
assert_not_predicate firm, :persisted?
|
159
192
|
assert_equal a, firm.account
|
160
193
|
assert firm.save
|
161
194
|
assert_equal a, firm.account
|
@@ -166,20 +199,20 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
|
|
166
199
|
def test_assignment_before_either_saved
|
167
200
|
firm = Firm.new("name" => "GlobalMegaCorp")
|
168
201
|
firm.account = a = Account.new("credit_limit" => 1000)
|
169
|
-
|
170
|
-
|
202
|
+
assert_not_predicate firm, :persisted?
|
203
|
+
assert_not_predicate a, :persisted?
|
171
204
|
assert_equal a, firm.account
|
172
205
|
assert firm.save
|
173
|
-
|
174
|
-
|
206
|
+
assert_predicate firm, :persisted?
|
207
|
+
assert_predicate a, :persisted?
|
175
208
|
assert_equal a, firm.account
|
176
209
|
firm.association(:account).reload
|
177
210
|
assert_equal a, firm.account
|
178
211
|
end
|
179
212
|
|
180
213
|
def test_not_resaved_when_unchanged
|
181
|
-
firm = Firm.all.merge!(:
|
182
|
-
firm.name +=
|
214
|
+
firm = Firm.all.merge!(includes: :account).first
|
215
|
+
firm.name += "-changed"
|
183
216
|
assert_queries(1) { firm.save! }
|
184
217
|
|
185
218
|
firm = Firm.first
|
@@ -196,21 +229,21 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
|
|
196
229
|
end
|
197
230
|
|
198
231
|
def test_callbacks_firing_order_on_create
|
199
|
-
eye = Eye.create(:
|
232
|
+
eye = Eye.create(iris_attributes: { color: "honey" })
|
200
233
|
assert_equal [true, false], eye.after_create_callbacks_stack
|
201
234
|
end
|
202
235
|
|
203
236
|
def test_callbacks_firing_order_on_update
|
204
|
-
eye = Eye.create(iris_attributes: {color:
|
205
|
-
eye.update(iris_attributes: {color:
|
237
|
+
eye = Eye.create(iris_attributes: { color: "honey" })
|
238
|
+
eye.update(iris_attributes: { color: "green" })
|
206
239
|
assert_equal [true, false], eye.after_update_callbacks_stack
|
207
240
|
end
|
208
241
|
|
209
242
|
def test_callbacks_firing_order_on_save
|
210
|
-
eye = Eye.create(iris_attributes: {color:
|
243
|
+
eye = Eye.create(iris_attributes: { color: "honey" })
|
211
244
|
assert_equal [false, false], eye.after_save_callbacks_stack
|
212
245
|
|
213
|
-
eye.update(iris_attributes: {color:
|
246
|
+
eye.update(iris_attributes: { color: "blue" })
|
214
247
|
assert_equal [false, false, false, false], eye.after_save_callbacks_stack
|
215
248
|
end
|
216
249
|
end
|
@@ -219,34 +252,34 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
|
|
219
252
|
fixtures :companies, :posts, :tags, :taggings
|
220
253
|
|
221
254
|
def test_should_save_parent_but_not_invalid_child
|
222
|
-
client = Client.new(:
|
223
|
-
|
255
|
+
client = Client.new(name: "Joe (the Plumber)")
|
256
|
+
assert_predicate client, :valid?
|
224
257
|
|
225
258
|
client.build_firm
|
226
|
-
|
259
|
+
assert_not_predicate client.firm, :valid?
|
227
260
|
|
228
261
|
assert client.save
|
229
|
-
|
262
|
+
assert_not_predicate client.firm, :persisted?
|
230
263
|
end
|
231
264
|
|
232
265
|
def test_save_fails_for_invalid_belongs_to
|
233
266
|
# Oracle saves empty string as NULL therefore :message changed to one space
|
234
|
-
assert log = AuditLog.create(:
|
267
|
+
assert log = AuditLog.create(developer_id: 0, message: " ")
|
235
268
|
|
236
269
|
log.developer = Developer.new
|
237
|
-
|
238
|
-
|
239
|
-
|
270
|
+
assert_not_predicate log.developer, :valid?
|
271
|
+
assert_not_predicate log, :valid?
|
272
|
+
assert_not log.save
|
240
273
|
assert_equal ["is invalid"], log.errors["developer"]
|
241
274
|
end
|
242
275
|
|
243
276
|
def test_save_succeeds_for_invalid_belongs_to_with_validate_false
|
244
277
|
# Oracle saves empty string as NULL therefore :message changed to one space
|
245
|
-
assert log = AuditLog.create(:
|
278
|
+
assert log = AuditLog.create(developer_id: 0, message: " ")
|
246
279
|
|
247
280
|
log.unvalidated_developer = Developer.new
|
248
|
-
|
249
|
-
|
281
|
+
assert_not_predicate log.unvalidated_developer, :valid?
|
282
|
+
assert_predicate log, :valid?
|
250
283
|
assert log.save
|
251
284
|
end
|
252
285
|
|
@@ -255,10 +288,10 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
|
|
255
288
|
apple = Firm.new("name" => "Apple")
|
256
289
|
client.firm = apple
|
257
290
|
assert_equal apple, client.firm
|
258
|
-
|
291
|
+
assert_not_predicate apple, :persisted?
|
259
292
|
assert client.save
|
260
293
|
assert apple.save
|
261
|
-
|
294
|
+
assert_predicate apple, :persisted?
|
262
295
|
assert_equal apple, client.firm
|
263
296
|
client.association(:firm).reload
|
264
297
|
assert_equal apple, client.firm
|
@@ -268,11 +301,11 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
|
|
268
301
|
final_cut = Client.new("name" => "Final Cut")
|
269
302
|
apple = Firm.new("name" => "Apple")
|
270
303
|
final_cut.firm = apple
|
271
|
-
|
272
|
-
|
304
|
+
assert_not_predicate final_cut, :persisted?
|
305
|
+
assert_not_predicate apple, :persisted?
|
273
306
|
assert final_cut.save
|
274
|
-
|
275
|
-
|
307
|
+
assert_predicate final_cut, :persisted?
|
308
|
+
assert_predicate apple, :persisted?
|
276
309
|
assert_equal apple, final_cut.firm
|
277
310
|
final_cut.association(:firm).reload
|
278
311
|
assert_equal apple, final_cut.firm
|
@@ -362,41 +395,55 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
|
|
362
395
|
|
363
396
|
def test_store_association_with_a_polymorphic_relationship
|
364
397
|
num_tagging = Tagging.count
|
365
|
-
tags(:misc).create_tagging(:
|
398
|
+
tags(:misc).create_tagging(taggable: posts(:thinking))
|
366
399
|
assert_equal num_tagging + 1, Tagging.count
|
367
400
|
end
|
368
401
|
|
369
402
|
def test_build_and_then_save_parent_should_not_reload_target
|
370
403
|
client = Client.first
|
371
|
-
apple = client.build_firm(:
|
404
|
+
apple = client.build_firm(name: "Apple")
|
372
405
|
client.save!
|
373
406
|
assert_no_queries { assert_equal apple, client.firm }
|
374
407
|
end
|
375
408
|
|
376
409
|
def test_validation_does_not_validate_stale_association_target
|
377
|
-
valid_developer = Developer.create!(:
|
410
|
+
valid_developer = Developer.create!(name: "Dude", salary: 50_000)
|
378
411
|
invalid_developer = Developer.new()
|
379
412
|
|
380
|
-
auditlog = AuditLog.new(:
|
413
|
+
auditlog = AuditLog.new(message: "foo")
|
381
414
|
auditlog.developer = invalid_developer
|
382
415
|
auditlog.developer_id = valid_developer.id
|
383
416
|
|
384
|
-
|
417
|
+
assert_predicate auditlog, :valid?
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_validation_does_not_validate_non_dirty_association_target
|
421
|
+
mouse = Mouse.create!(name: "Will")
|
422
|
+
Squeak.create!(mouse: mouse)
|
423
|
+
|
424
|
+
mouse.name = nil
|
425
|
+
mouse.save! validate: false
|
426
|
+
|
427
|
+
squeak = Squeak.last
|
428
|
+
|
429
|
+
assert_equal true, squeak.valid?
|
430
|
+
assert_equal true, squeak.mouse.present?
|
431
|
+
assert_equal true, squeak.valid?
|
385
432
|
end
|
386
433
|
end
|
387
434
|
|
388
435
|
class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttributes < ActiveRecord::TestCase
|
389
436
|
def test_invalid_adding_with_nested_attributes
|
390
437
|
molecule = Molecule.new
|
391
|
-
valid_electron = Electron.new(name:
|
438
|
+
valid_electron = Electron.new(name: "electron")
|
392
439
|
invalid_electron = Electron.new
|
393
440
|
|
394
441
|
molecule.electrons = [valid_electron, invalid_electron]
|
395
442
|
molecule.save
|
396
443
|
|
397
|
-
|
398
|
-
|
399
|
-
assert_not molecule.persisted?,
|
444
|
+
assert_not_predicate invalid_electron, :valid?
|
445
|
+
assert_predicate valid_electron, :valid?
|
446
|
+
assert_not molecule.persisted?, "Molecule should not be persisted when its electrons are invalid"
|
400
447
|
end
|
401
448
|
|
402
449
|
def test_errors_should_be_indexed_when_passed_as_array
|
@@ -407,9 +454,9 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
|
|
407
454
|
|
408
455
|
guitar.tuning_pegs = [tuning_peg_valid, tuning_peg_invalid]
|
409
456
|
|
410
|
-
|
411
|
-
|
412
|
-
|
457
|
+
assert_not_predicate tuning_peg_invalid, :valid?
|
458
|
+
assert_predicate tuning_peg_valid, :valid?
|
459
|
+
assert_not_predicate guitar, :valid?
|
413
460
|
assert_equal ["is not a number"], guitar.errors["tuning_pegs[1].pitch"]
|
414
461
|
assert_not_equal ["is not a number"], guitar.errors["tuning_pegs.pitch"]
|
415
462
|
end
|
@@ -419,14 +466,14 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
|
|
419
466
|
ActiveRecord::Base.index_nested_attribute_errors = true
|
420
467
|
|
421
468
|
molecule = Molecule.new
|
422
|
-
valid_electron = Electron.new(name:
|
469
|
+
valid_electron = Electron.new(name: "electron")
|
423
470
|
invalid_electron = Electron.new
|
424
471
|
|
425
472
|
molecule.electrons = [valid_electron, invalid_electron]
|
426
473
|
|
427
|
-
|
428
|
-
|
429
|
-
|
474
|
+
assert_not_predicate invalid_electron, :valid?
|
475
|
+
assert_predicate valid_electron, :valid?
|
476
|
+
assert_not_predicate molecule, :valid?
|
430
477
|
assert_equal ["can't be blank"], molecule.errors["electrons[1].name"]
|
431
478
|
assert_not_equal ["can't be blank"], molecule.errors["electrons.name"]
|
432
479
|
ensure
|
@@ -435,14 +482,14 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
|
|
435
482
|
|
436
483
|
def test_errors_details_should_be_set
|
437
484
|
molecule = Molecule.new
|
438
|
-
valid_electron = Electron.new(name:
|
485
|
+
valid_electron = Electron.new(name: "electron")
|
439
486
|
invalid_electron = Electron.new
|
440
487
|
|
441
488
|
molecule.electrons = [valid_electron, invalid_electron]
|
442
489
|
|
443
|
-
|
444
|
-
|
445
|
-
|
490
|
+
assert_not_predicate invalid_electron, :valid?
|
491
|
+
assert_predicate valid_electron, :valid?
|
492
|
+
assert_not_predicate molecule, :valid?
|
446
493
|
assert_equal [{ error: :blank }], molecule.errors.details[:"electrons.name"]
|
447
494
|
end
|
448
495
|
|
@@ -454,9 +501,9 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
|
|
454
501
|
|
455
502
|
guitar.tuning_pegs = [tuning_peg_valid, tuning_peg_invalid]
|
456
503
|
|
457
|
-
|
458
|
-
|
459
|
-
|
504
|
+
assert_not_predicate tuning_peg_invalid, :valid?
|
505
|
+
assert_predicate tuning_peg_valid, :valid?
|
506
|
+
assert_not_predicate guitar, :valid?
|
460
507
|
assert_equal [{ error: :not_a_number, value: nil }], guitar.errors.details[:"tuning_pegs[1].pitch"]
|
461
508
|
assert_equal [], guitar.errors.details[:"tuning_pegs.pitch"]
|
462
509
|
end
|
@@ -466,14 +513,14 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
|
|
466
513
|
ActiveRecord::Base.index_nested_attribute_errors = true
|
467
514
|
|
468
515
|
molecule = Molecule.new
|
469
|
-
valid_electron = Electron.new(name:
|
516
|
+
valid_electron = Electron.new(name: "electron")
|
470
517
|
invalid_electron = Electron.new
|
471
518
|
|
472
519
|
molecule.electrons = [valid_electron, invalid_electron]
|
473
520
|
|
474
|
-
|
475
|
-
|
476
|
-
|
521
|
+
assert_not_predicate invalid_electron, :valid?
|
522
|
+
assert_predicate valid_electron, :valid?
|
523
|
+
assert_not_predicate molecule, :valid?
|
477
524
|
assert_equal [{ error: :blank }], molecule.errors.details[:"electrons[1].name"]
|
478
525
|
assert_equal [], molecule.errors.details[:"electrons.name"]
|
479
526
|
ensure
|
@@ -482,38 +529,50 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
|
|
482
529
|
|
483
530
|
def test_valid_adding_with_nested_attributes
|
484
531
|
molecule = Molecule.new
|
485
|
-
valid_electron = Electron.new(name:
|
532
|
+
valid_electron = Electron.new(name: "electron")
|
486
533
|
|
487
534
|
molecule.electrons = [valid_electron]
|
488
535
|
molecule.save
|
489
536
|
|
490
|
-
|
491
|
-
|
537
|
+
assert_predicate valid_electron, :valid?
|
538
|
+
assert_predicate molecule, :persisted?
|
492
539
|
assert_equal 1, molecule.electrons.count
|
493
540
|
end
|
494
541
|
end
|
495
542
|
|
496
543
|
class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase
|
497
|
-
fixtures :companies, :
|
544
|
+
fixtures :companies, :developers
|
498
545
|
|
499
546
|
def test_invalid_adding
|
500
547
|
firm = Firm.find(1)
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
548
|
+
assert_not (firm.clients_of_firm << c = Client.new)
|
549
|
+
assert_not_predicate c, :persisted?
|
550
|
+
assert_not_predicate firm, :valid?
|
551
|
+
assert_not firm.save
|
552
|
+
assert_not_predicate c, :persisted?
|
506
553
|
end
|
507
554
|
|
508
555
|
def test_invalid_adding_before_save
|
509
556
|
new_firm = Firm.new("name" => "A New Firm, Inc")
|
510
557
|
new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")])
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
558
|
+
assert_not_predicate c, :persisted?
|
559
|
+
assert_not_predicate c, :valid?
|
560
|
+
assert_not_predicate new_firm, :valid?
|
561
|
+
assert_not new_firm.save
|
562
|
+
assert_not_predicate c, :persisted?
|
563
|
+
assert_not_predicate new_firm, :persisted?
|
564
|
+
end
|
565
|
+
|
566
|
+
def test_adding_unsavable_association
|
567
|
+
new_firm = Firm.new("name" => "A New Firm, Inc")
|
568
|
+
client = new_firm.clients.new("name" => "Apple")
|
569
|
+
client.throw_on_save = true
|
570
|
+
|
571
|
+
assert_predicate client, :valid?
|
572
|
+
assert_predicate new_firm, :valid?
|
573
|
+
assert_not new_firm.save
|
574
|
+
assert_not_predicate new_firm, :persisted?
|
575
|
+
assert_not_predicate client, :persisted?
|
517
576
|
end
|
518
577
|
|
519
578
|
def test_invalid_adding_with_validate_false
|
@@ -521,10 +580,10 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
|
|
521
580
|
client = Client.new
|
522
581
|
firm.unvalidated_clients_of_firm << client
|
523
582
|
|
524
|
-
|
525
|
-
|
583
|
+
assert_predicate firm, :valid?
|
584
|
+
assert_not_predicate client, :valid?
|
526
585
|
assert firm.save
|
527
|
-
|
586
|
+
assert_not_predicate client, :persisted?
|
528
587
|
end
|
529
588
|
|
530
589
|
def test_valid_adding_with_validate_false
|
@@ -533,24 +592,52 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
|
|
533
592
|
firm = Firm.first
|
534
593
|
client = Client.new("name" => "Apple")
|
535
594
|
|
536
|
-
|
537
|
-
|
538
|
-
|
595
|
+
assert_predicate firm, :valid?
|
596
|
+
assert_predicate client, :valid?
|
597
|
+
assert_not_predicate client, :persisted?
|
539
598
|
|
540
599
|
firm.unvalidated_clients_of_firm << client
|
541
600
|
|
542
601
|
assert firm.save
|
543
|
-
|
602
|
+
assert_predicate client, :persisted?
|
544
603
|
assert_equal no_of_clients + 1, Client.count
|
545
604
|
end
|
546
605
|
|
606
|
+
def test_parent_should_save_children_record_with_foreign_key_validation_set_in_before_save_callback
|
607
|
+
company = NewlyContractedCompany.new(name: "test")
|
608
|
+
|
609
|
+
assert company.save
|
610
|
+
assert_not_empty company.reload.new_contracts
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_parent_should_not_get_saved_with_duplicate_children_records
|
614
|
+
assert_no_difference "Reply.count" do
|
615
|
+
assert_no_difference "SillyUniqueReply.count" do
|
616
|
+
reply = Reply.new
|
617
|
+
reply.silly_unique_replies.build([
|
618
|
+
{ content: "Best content" },
|
619
|
+
{ content: "Best content" }
|
620
|
+
])
|
621
|
+
|
622
|
+
assert_not reply.save
|
623
|
+
assert_equal ["is invalid"], reply.errors[:silly_unique_replies]
|
624
|
+
assert_empty reply.silly_unique_replies.first.errors
|
625
|
+
|
626
|
+
assert_equal(
|
627
|
+
["has already been taken"],
|
628
|
+
reply.silly_unique_replies.last.errors[:content]
|
629
|
+
)
|
630
|
+
end
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
547
634
|
def test_invalid_build
|
548
635
|
new_client = companies(:first_firm).clients_of_firm.build
|
549
|
-
|
550
|
-
|
636
|
+
assert_not_predicate new_client, :persisted?
|
637
|
+
assert_not_predicate new_client, :valid?
|
551
638
|
assert_equal new_client, companies(:first_firm).clients_of_firm.last
|
552
|
-
|
553
|
-
|
639
|
+
assert_not companies(:first_firm).save
|
640
|
+
assert_not_predicate new_client, :persisted?
|
554
641
|
assert_equal 2, companies(:first_firm).clients_of_firm.reload.size
|
555
642
|
end
|
556
643
|
|
@@ -569,8 +656,8 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
|
|
569
656
|
assert_equal no_of_firms, Firm.count # Firm was not saved to database.
|
570
657
|
assert_equal no_of_clients, Client.count # Clients were not saved to database.
|
571
658
|
assert new_firm.save
|
572
|
-
|
573
|
-
|
659
|
+
assert_predicate new_firm, :persisted?
|
660
|
+
assert_predicate c, :persisted?
|
574
661
|
assert_equal new_firm, c.firm
|
575
662
|
assert_equal no_of_firms + 1, Firm.count # Firm was saved to database.
|
576
663
|
assert_equal no_of_clients + 2, Client.count # Clients were saved to database.
|
@@ -585,58 +672,62 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
|
|
585
672
|
firm.save
|
586
673
|
firm.reload
|
587
674
|
assert_equal 2, firm.clients.length
|
588
|
-
|
675
|
+
assert_includes firm.clients, companies(:second_client)
|
589
676
|
end
|
590
677
|
|
591
678
|
def test_assign_ids_for_through_a_belongs_to
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
assert_equal 2,
|
597
|
-
|
679
|
+
firm = Firm.new("name" => "Apple")
|
680
|
+
firm.developer_ids = [developers(:david).id, developers(:jamis).id]
|
681
|
+
firm.save
|
682
|
+
firm.reload
|
683
|
+
assert_equal 2, firm.developers.length
|
684
|
+
assert_includes firm.developers, developers(:david)
|
598
685
|
end
|
599
686
|
|
600
687
|
def test_build_before_save
|
601
688
|
company = companies(:first_firm)
|
602
|
-
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
|
603
|
-
assert !company.clients_of_firm.loaded?
|
604
689
|
|
605
|
-
company.name
|
690
|
+
new_client = assert_queries(0) { company.clients_of_firm.build("name" => "Another Client") }
|
691
|
+
assert_not_predicate company.clients_of_firm, :loaded?
|
692
|
+
|
693
|
+
company.name += "-changed"
|
606
694
|
assert_queries(2) { assert company.save }
|
607
|
-
|
695
|
+
assert_predicate new_client, :persisted?
|
608
696
|
assert_equal 3, company.clients_of_firm.reload.size
|
609
697
|
end
|
610
698
|
|
611
699
|
def test_build_many_before_save
|
612
700
|
company = companies(:first_firm)
|
613
|
-
assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
|
614
701
|
|
615
|
-
company.name
|
702
|
+
assert_queries(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
|
703
|
+
|
704
|
+
company.name += "-changed"
|
616
705
|
assert_queries(3) { assert company.save }
|
617
706
|
assert_equal 4, company.clients_of_firm.reload.size
|
618
707
|
end
|
619
708
|
|
620
709
|
def test_build_via_block_before_save
|
621
710
|
company = companies(:first_firm)
|
622
|
-
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
|
623
|
-
assert !company.clients_of_firm.loaded?
|
624
711
|
|
625
|
-
company.name
|
712
|
+
new_client = assert_queries(0) { company.clients_of_firm.build { |client| client.name = "Another Client" } }
|
713
|
+
assert_not_predicate company.clients_of_firm, :loaded?
|
714
|
+
|
715
|
+
company.name += "-changed"
|
626
716
|
assert_queries(2) { assert company.save }
|
627
|
-
|
717
|
+
assert_predicate new_client, :persisted?
|
628
718
|
assert_equal 3, company.clients_of_firm.reload.size
|
629
719
|
end
|
630
720
|
|
631
721
|
def test_build_many_via_block_before_save
|
632
722
|
company = companies(:first_firm)
|
633
|
-
|
634
|
-
|
723
|
+
|
724
|
+
assert_queries(0) do
|
725
|
+
company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) do |client|
|
635
726
|
client.name = "changed"
|
636
727
|
end
|
637
728
|
end
|
638
729
|
|
639
|
-
company.name +=
|
730
|
+
company.name += "-changed"
|
640
731
|
assert_queries(3) { assert company.save }
|
641
732
|
assert_equal 4, company.clients_of_firm.reload.size
|
642
733
|
end
|
@@ -647,7 +738,16 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
|
|
647
738
|
assert firm.save
|
648
739
|
firm.reload
|
649
740
|
assert_equal 2, firm.clients.length
|
650
|
-
|
741
|
+
assert_includes firm.clients, Client.find_by_name("New Client")
|
742
|
+
end
|
743
|
+
|
744
|
+
def test_replace_on_duplicated_object
|
745
|
+
firm = Firm.create!("name" => "New Firm").dup
|
746
|
+
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
|
747
|
+
assert firm.save
|
748
|
+
firm.reload
|
749
|
+
assert_equal 2, firm.clients.length
|
750
|
+
assert_includes firm.clients, Client.find_by_name("New Client")
|
651
751
|
end
|
652
752
|
end
|
653
753
|
|
@@ -656,79 +756,88 @@ class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase
|
|
656
756
|
new_account = Account.new("credit_limit" => 1000)
|
657
757
|
new_firm = Firm.new("name" => "some firm")
|
658
758
|
|
659
|
-
|
759
|
+
assert_not_predicate new_firm, :persisted?
|
660
760
|
new_account.firm = new_firm
|
661
761
|
new_account.save!
|
662
762
|
|
663
|
-
|
763
|
+
assert_predicate new_firm, :persisted?
|
664
764
|
|
665
765
|
new_account = Account.new("credit_limit" => 1000)
|
666
766
|
new_autosaved_firm = Firm.new("name" => "some firm")
|
667
767
|
|
668
|
-
|
768
|
+
assert_not_predicate new_autosaved_firm, :persisted?
|
669
769
|
new_account.unautosaved_firm = new_autosaved_firm
|
670
770
|
new_account.save!
|
671
771
|
|
672
|
-
|
772
|
+
assert_not_predicate new_autosaved_firm, :persisted?
|
673
773
|
end
|
674
774
|
|
675
775
|
def test_autosave_new_record_on_has_one_can_be_disabled_per_relationship
|
676
776
|
firm = Firm.new("name" => "some firm")
|
677
777
|
account = Account.new("credit_limit" => 1000)
|
678
778
|
|
679
|
-
|
779
|
+
assert_not_predicate account, :persisted?
|
680
780
|
firm.account = account
|
681
781
|
firm.save!
|
682
782
|
|
683
|
-
|
783
|
+
assert_predicate account, :persisted?
|
684
784
|
|
685
785
|
firm = Firm.new("name" => "some firm")
|
686
786
|
account = Account.new("credit_limit" => 1000)
|
687
787
|
|
688
788
|
firm.unautosaved_account = account
|
689
789
|
|
690
|
-
|
790
|
+
assert_not_predicate account, :persisted?
|
691
791
|
firm.unautosaved_account = account
|
692
792
|
firm.save!
|
693
793
|
|
694
|
-
|
794
|
+
assert_not_predicate account, :persisted?
|
695
795
|
end
|
696
796
|
|
697
797
|
def test_autosave_new_record_on_has_many_can_be_disabled_per_relationship
|
698
798
|
firm = Firm.new("name" => "some firm")
|
699
799
|
account = Account.new("credit_limit" => 1000)
|
700
800
|
|
701
|
-
|
801
|
+
assert_not_predicate account, :persisted?
|
702
802
|
firm.accounts << account
|
703
803
|
|
704
804
|
firm.save!
|
705
|
-
|
805
|
+
assert_predicate account, :persisted?
|
706
806
|
|
707
807
|
firm = Firm.new("name" => "some firm")
|
708
808
|
account = Account.new("credit_limit" => 1000)
|
709
809
|
|
710
|
-
|
810
|
+
assert_not_predicate account, :persisted?
|
711
811
|
firm.unautosaved_accounts << account
|
712
812
|
|
713
813
|
firm.save!
|
714
|
-
|
814
|
+
assert_not_predicate account, :persisted?
|
715
815
|
end
|
716
816
|
|
717
817
|
def test_autosave_new_record_with_after_create_callback
|
718
|
-
post = PostWithAfterCreateCallback.new(title:
|
719
|
-
post.comments.build(body:
|
818
|
+
post = PostWithAfterCreateCallback.new(title: "Captain Murphy", body: "is back")
|
819
|
+
post.comments.build(body: "foo")
|
720
820
|
post.save!
|
721
821
|
|
722
822
|
assert_not_nil post.author_id
|
723
823
|
end
|
824
|
+
|
825
|
+
def test_autosave_new_record_with_after_create_callback_and_habtm_association
|
826
|
+
post = PostWithAfterCreateCallback.new(title: "Captain Murphy", body: "is back")
|
827
|
+
post.comments.build(body: "foo")
|
828
|
+
post.categories.build(name: "bar")
|
829
|
+
post.save!
|
830
|
+
|
831
|
+
assert_equal 1, post.categories.reload.length
|
832
|
+
end
|
724
833
|
end
|
725
834
|
|
726
835
|
class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
727
836
|
self.use_transactional_tests = false
|
728
837
|
|
729
838
|
setup do
|
730
|
-
@pirate = Pirate.create(:
|
731
|
-
@ship = @pirate.create_ship(:
|
839
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
840
|
+
@ship = @pirate.create_ship(name: "Nights Dirty Lightning")
|
732
841
|
end
|
733
842
|
|
734
843
|
teardown do
|
@@ -744,18 +853,18 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
744
853
|
@pirate.mark_for_destruction
|
745
854
|
@pirate.ship.mark_for_destruction
|
746
855
|
|
747
|
-
|
748
|
-
|
856
|
+
assert_not_predicate @pirate.reload, :marked_for_destruction?
|
857
|
+
assert_not_predicate @pirate.ship.reload, :marked_for_destruction?
|
749
858
|
end
|
750
859
|
|
751
860
|
# has_one
|
752
861
|
def test_should_destroy_a_child_association_as_part_of_the_save_transaction_if_it_was_marked_for_destruction
|
753
|
-
|
862
|
+
assert_not_predicate @pirate.ship, :marked_for_destruction?
|
754
863
|
|
755
864
|
@pirate.ship.mark_for_destruction
|
756
865
|
id = @pirate.ship.id
|
757
866
|
|
758
|
-
|
867
|
+
assert_predicate @pirate.ship, :marked_for_destruction?
|
759
868
|
assert Ship.find_by_id(id)
|
760
869
|
|
761
870
|
@pirate.save
|
@@ -764,12 +873,13 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
764
873
|
end
|
765
874
|
|
766
875
|
def test_should_skip_validation_on_a_child_association_if_marked_for_destruction
|
767
|
-
@pirate.ship.name =
|
768
|
-
|
876
|
+
@pirate.ship.name = ""
|
877
|
+
assert_not_predicate @pirate, :valid?
|
769
878
|
|
770
879
|
@pirate.ship.mark_for_destruction
|
771
|
-
@pirate.ship
|
772
|
-
|
880
|
+
assert_not_called(@pirate.ship, :valid?) do
|
881
|
+
assert_difference("Ship.count", -1) { @pirate.save! }
|
882
|
+
end
|
773
883
|
end
|
774
884
|
|
775
885
|
def test_a_child_marked_for_destruction_should_not_be_destroyed_twice
|
@@ -784,16 +894,17 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
784
894
|
def test_should_rollback_destructions_if_an_exception_occurred_while_saving_a_child
|
785
895
|
# Stub the save method of the @pirate.ship instance to destroy and then raise an exception
|
786
896
|
class << @pirate.ship
|
787
|
-
def save(
|
897
|
+
def save(**)
|
788
898
|
super
|
789
899
|
destroy
|
790
|
-
raise
|
900
|
+
raise "Oh noes!"
|
791
901
|
end
|
792
902
|
end
|
793
903
|
|
794
904
|
@ship.pirate.catchphrase = "Changed Catchphrase"
|
905
|
+
@ship.name_will_change!
|
795
906
|
|
796
|
-
assert_raise(RuntimeError) {
|
907
|
+
assert_raise(RuntimeError) { assert_not @pirate.save }
|
797
908
|
assert_not_nil @pirate.reload.ship
|
798
909
|
end
|
799
910
|
|
@@ -804,18 +915,19 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
804
915
|
end
|
805
916
|
|
806
917
|
def test_should_not_save_changed_has_one_unchanged_object_if_child_is_saved
|
807
|
-
@pirate.ship
|
808
|
-
|
918
|
+
assert_not_called(@pirate.ship, :save) do
|
919
|
+
assert @pirate.save
|
920
|
+
end
|
809
921
|
end
|
810
922
|
|
811
923
|
# belongs_to
|
812
924
|
def test_should_destroy_a_parent_association_as_part_of_the_save_transaction_if_it_was_marked_for_destruction
|
813
|
-
|
925
|
+
assert_not_predicate @ship.pirate, :marked_for_destruction?
|
814
926
|
|
815
927
|
@ship.pirate.mark_for_destruction
|
816
928
|
id = @ship.pirate.id
|
817
929
|
|
818
|
-
|
930
|
+
assert_predicate @ship.pirate, :marked_for_destruction?
|
819
931
|
assert Pirate.find_by_id(id)
|
820
932
|
|
821
933
|
@ship.save
|
@@ -824,12 +936,13 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
824
936
|
end
|
825
937
|
|
826
938
|
def test_should_skip_validation_on_a_parent_association_if_marked_for_destruction
|
827
|
-
@ship.pirate.catchphrase =
|
828
|
-
|
939
|
+
@ship.pirate.catchphrase = ""
|
940
|
+
assert_not_predicate @ship, :valid?
|
829
941
|
|
830
942
|
@ship.pirate.mark_for_destruction
|
831
|
-
@ship.pirate
|
832
|
-
|
943
|
+
assert_not_called(@ship.pirate, :valid?) do
|
944
|
+
assert_difference("Pirate.count", -1) { @ship.save! }
|
945
|
+
end
|
833
946
|
end
|
834
947
|
|
835
948
|
def test_a_parent_marked_for_destruction_should_not_be_destroyed_twice
|
@@ -844,32 +957,32 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
844
957
|
def test_should_rollback_destructions_if_an_exception_occurred_while_saving_a_parent
|
845
958
|
# Stub the save method of the @ship.pirate instance to destroy and then raise an exception
|
846
959
|
class << @ship.pirate
|
847
|
-
def save(
|
960
|
+
def save(**)
|
848
961
|
super
|
849
962
|
destroy
|
850
|
-
raise
|
963
|
+
raise "Oh noes!"
|
851
964
|
end
|
852
965
|
end
|
853
966
|
|
854
967
|
@ship.pirate.catchphrase = "Changed Catchphrase"
|
855
968
|
|
856
|
-
assert_raise(RuntimeError) {
|
969
|
+
assert_raise(RuntimeError) { assert_not @ship.save }
|
857
970
|
assert_not_nil @ship.reload.pirate
|
858
971
|
end
|
859
972
|
|
860
973
|
def test_should_save_changed_child_objects_if_parent_is_saved
|
861
|
-
@pirate = @ship.create_pirate(:
|
862
|
-
@parrot = @pirate.parrots.create!(:
|
974
|
+
@pirate = @ship.create_pirate(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
975
|
+
@parrot = @pirate.parrots.create!(name: "Posideons Killer")
|
863
976
|
@parrot.name = "NewName"
|
864
977
|
@ship.save
|
865
978
|
|
866
|
-
assert_equal
|
979
|
+
assert_equal "NewName", @parrot.reload.name
|
867
980
|
end
|
868
981
|
|
869
982
|
def test_should_destroy_has_many_as_part_of_the_save_transaction_if_they_were_marked_for_destruction
|
870
|
-
2.times { |i| @pirate.birds.create!(:
|
983
|
+
2.times { |i| @pirate.birds.create!(name: "birds_#{i}") }
|
871
984
|
|
872
|
-
|
985
|
+
assert_not @pirate.birds.any?(&:marked_for_destruction?)
|
873
986
|
|
874
987
|
@pirate.birds.each(&:mark_for_destruction)
|
875
988
|
klass = @pirate.birds.first.class
|
@@ -879,7 +992,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
879
992
|
ids.each { |id| assert klass.find_by_id(id) }
|
880
993
|
|
881
994
|
@pirate.save
|
882
|
-
|
995
|
+
assert_empty @pirate.reload.birds
|
883
996
|
ids.each { |id| assert_nil klass.find_by_id(id) }
|
884
997
|
end
|
885
998
|
|
@@ -887,62 +1000,67 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
887
1000
|
@pirate.birds.create!(name: :parrot)
|
888
1001
|
@pirate.birds.first.destroy
|
889
1002
|
@pirate.save!
|
890
|
-
|
1003
|
+
assert_empty @pirate.reload.birds
|
891
1004
|
end
|
892
1005
|
|
893
1006
|
def test_should_skip_validation_on_has_many_if_marked_for_destruction
|
894
|
-
2.times { |i| @pirate.birds.create!(:
|
1007
|
+
2.times { |i| @pirate.birds.create!(name: "birds_#{i}") }
|
895
1008
|
|
896
|
-
@pirate.birds.each { |bird| bird.name =
|
897
|
-
|
1009
|
+
@pirate.birds.each { |bird| bird.name = "" }
|
1010
|
+
assert_not_predicate @pirate, :valid?
|
898
1011
|
|
899
|
-
@pirate.birds.each
|
900
|
-
|
901
|
-
|
1012
|
+
@pirate.birds.each(&:mark_for_destruction)
|
1013
|
+
|
1014
|
+
assert_not_called(@pirate.birds.first, :valid?) do
|
1015
|
+
assert_not_called(@pirate.birds.last, :valid?) do
|
1016
|
+
assert_difference("Bird.count", -2) { @pirate.save! }
|
1017
|
+
end
|
902
1018
|
end
|
903
|
-
assert_difference("Bird.count", -2) { @pirate.save! }
|
904
1019
|
end
|
905
1020
|
|
906
1021
|
def test_should_skip_validation_on_has_many_if_destroyed
|
907
|
-
@pirate.birds.create!(:
|
1022
|
+
@pirate.birds.create!(name: "birds_1")
|
908
1023
|
|
909
|
-
@pirate.birds.each { |bird| bird.name =
|
910
|
-
|
1024
|
+
@pirate.birds.each { |bird| bird.name = "" }
|
1025
|
+
assert_not_predicate @pirate, :valid?
|
911
1026
|
|
912
1027
|
@pirate.birds.each(&:destroy)
|
913
|
-
|
1028
|
+
assert_predicate @pirate, :valid?
|
914
1029
|
end
|
915
1030
|
|
916
1031
|
def test_a_child_marked_for_destruction_should_not_be_destroyed_twice_while_saving_has_many
|
917
|
-
@pirate.birds.create!(:
|
1032
|
+
@pirate.birds.create!(name: "birds_1")
|
918
1033
|
|
919
1034
|
@pirate.birds.each(&:mark_for_destruction)
|
920
1035
|
assert @pirate.save
|
921
1036
|
|
922
|
-
@pirate.birds.each
|
923
|
-
|
1037
|
+
@pirate.birds.each do |bird|
|
1038
|
+
assert_not_called(bird, :destroy) do
|
1039
|
+
assert @pirate.save
|
1040
|
+
end
|
1041
|
+
end
|
924
1042
|
end
|
925
1043
|
|
926
1044
|
def test_should_rollback_destructions_if_an_exception_occurred_while_saving_has_many
|
927
|
-
2.times { |i| @pirate.birds.create!(:
|
1045
|
+
2.times { |i| @pirate.birds.create!(name: "birds_#{i}") }
|
928
1046
|
before = @pirate.birds.map { |c| c.mark_for_destruction ; c }
|
929
1047
|
|
930
1048
|
# Stub the destroy method of the second child to raise an exception
|
931
1049
|
class << before.last
|
932
1050
|
def destroy(*args)
|
933
1051
|
super
|
934
|
-
raise
|
1052
|
+
raise "Oh noes!"
|
935
1053
|
end
|
936
1054
|
end
|
937
1055
|
|
938
|
-
assert_raise(RuntimeError) {
|
1056
|
+
assert_raise(RuntimeError) { assert_not @pirate.save }
|
939
1057
|
assert_equal before, @pirate.reload.birds
|
940
1058
|
end
|
941
1059
|
|
942
1060
|
def test_when_new_record_a_child_marked_for_destruction_should_not_affect_other_records_from_saving
|
943
|
-
@pirate = @ship.build_pirate(:
|
1061
|
+
@pirate = @ship.build_pirate(catchphrase: "Arr' now I shall keep me eye on you matey!") # new record
|
944
1062
|
|
945
|
-
3.times { |i| @pirate.birds.build(:
|
1063
|
+
3.times { |i| @pirate.birds.build(name: "birds_#{i}") }
|
946
1064
|
@pirate.birds[1].mark_for_destruction
|
947
1065
|
@pirate.save!
|
948
1066
|
|
@@ -968,8 +1086,8 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
968
1086
|
define_method("test_should_run_add_callback_#{callback_type}s_for_has_many") do
|
969
1087
|
association_name_with_callbacks = "birds_with_#{callback_type}_callbacks"
|
970
1088
|
|
971
|
-
pirate = Pirate.new(:
|
972
|
-
pirate.
|
1089
|
+
pirate = Pirate.new(catchphrase: "Arr")
|
1090
|
+
pirate.public_send(association_name_with_callbacks).build(name: "Crowe the One-Eyed")
|
973
1091
|
|
974
1092
|
expected = [
|
975
1093
|
"before_adding_#{callback_type}_bird_<new>",
|
@@ -982,9 +1100,9 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
982
1100
|
define_method("test_should_run_remove_callback_#{callback_type}s_for_has_many") do
|
983
1101
|
association_name_with_callbacks = "birds_with_#{callback_type}_callbacks"
|
984
1102
|
|
985
|
-
@pirate.
|
986
|
-
@pirate.
|
987
|
-
child_id = @pirate.
|
1103
|
+
@pirate.public_send(association_name_with_callbacks).create!(name: "Crowe the One-Eyed")
|
1104
|
+
@pirate.public_send(association_name_with_callbacks).each(&:mark_for_destruction)
|
1105
|
+
child_id = @pirate.public_send(association_name_with_callbacks).first.id
|
988
1106
|
|
989
1107
|
@pirate.ship_log.clear
|
990
1108
|
@pirate.save
|
@@ -999,71 +1117,73 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
999
1117
|
end
|
1000
1118
|
|
1001
1119
|
def test_should_destroy_habtm_as_part_of_the_save_transaction_if_they_were_marked_for_destruction
|
1002
|
-
2.times { |i| @pirate.parrots.create!(:
|
1120
|
+
2.times { |i| @pirate.parrots.create!(name: "parrots_#{i}") }
|
1003
1121
|
|
1004
|
-
|
1122
|
+
assert_not @pirate.parrots.any?(&:marked_for_destruction?)
|
1005
1123
|
@pirate.parrots.each(&:mark_for_destruction)
|
1006
1124
|
|
1007
1125
|
assert_no_difference "Parrot.count" do
|
1008
1126
|
@pirate.save
|
1009
1127
|
end
|
1010
1128
|
|
1011
|
-
|
1129
|
+
assert_empty @pirate.reload.parrots
|
1012
1130
|
|
1013
1131
|
join_records = Pirate.connection.select_all("SELECT * FROM parrots_pirates WHERE pirate_id = #{@pirate.id}")
|
1014
|
-
|
1132
|
+
assert_empty join_records
|
1015
1133
|
end
|
1016
1134
|
|
1017
1135
|
def test_should_skip_validation_on_habtm_if_marked_for_destruction
|
1018
|
-
2.times { |i| @pirate.parrots.create!(:
|
1136
|
+
2.times { |i| @pirate.parrots.create!(name: "parrots_#{i}") }
|
1019
1137
|
|
1020
|
-
@pirate.parrots.each { |parrot| parrot.name =
|
1021
|
-
|
1138
|
+
@pirate.parrots.each { |parrot| parrot.name = "" }
|
1139
|
+
assert_not_predicate @pirate, :valid?
|
1022
1140
|
|
1023
|
-
@pirate.parrots.each
|
1024
|
-
|
1025
|
-
|
1141
|
+
@pirate.parrots.each { |parrot| parrot.mark_for_destruction }
|
1142
|
+
|
1143
|
+
assert_not_called(@pirate.parrots.first, :valid?) do
|
1144
|
+
assert_not_called(@pirate.parrots.last, :valid?) do
|
1145
|
+
@pirate.save!
|
1146
|
+
end
|
1026
1147
|
end
|
1027
1148
|
|
1028
|
-
@pirate.
|
1029
|
-
assert @pirate.reload.parrots.empty?
|
1149
|
+
assert_empty @pirate.reload.parrots
|
1030
1150
|
end
|
1031
1151
|
|
1032
1152
|
def test_should_skip_validation_on_habtm_if_destroyed
|
1033
|
-
@pirate.parrots.create!(:
|
1153
|
+
@pirate.parrots.create!(name: "parrots_1")
|
1034
1154
|
|
1035
|
-
@pirate.parrots.each { |parrot| parrot.name =
|
1036
|
-
|
1155
|
+
@pirate.parrots.each { |parrot| parrot.name = "" }
|
1156
|
+
assert_not_predicate @pirate, :valid?
|
1037
1157
|
|
1038
1158
|
@pirate.parrots.each(&:destroy)
|
1039
|
-
|
1159
|
+
assert_predicate @pirate, :valid?
|
1040
1160
|
end
|
1041
1161
|
|
1042
1162
|
def test_a_child_marked_for_destruction_should_not_be_destroyed_twice_while_saving_habtm
|
1043
|
-
@pirate.parrots.create!(:
|
1163
|
+
@pirate.parrots.create!(name: "parrots_1")
|
1044
1164
|
|
1045
1165
|
@pirate.parrots.each(&:mark_for_destruction)
|
1046
1166
|
assert @pirate.save
|
1047
1167
|
|
1048
1168
|
Pirate.transaction do
|
1049
|
-
|
1169
|
+
assert_no_queries do
|
1050
1170
|
assert @pirate.save
|
1051
1171
|
end
|
1052
1172
|
end
|
1053
1173
|
end
|
1054
1174
|
|
1055
1175
|
def test_should_rollback_destructions_if_an_exception_occurred_while_saving_habtm
|
1056
|
-
2.times { |i| @pirate.parrots.create!(:
|
1176
|
+
2.times { |i| @pirate.parrots.create!(name: "parrots_#{i}") }
|
1057
1177
|
before = @pirate.parrots.map { |c| c.mark_for_destruction ; c }
|
1058
1178
|
|
1059
1179
|
class << @pirate.association(:parrots)
|
1060
1180
|
def destroy(*args)
|
1061
1181
|
super
|
1062
|
-
raise
|
1182
|
+
raise "Oh noes!"
|
1063
1183
|
end
|
1064
1184
|
end
|
1065
1185
|
|
1066
|
-
assert_raise(RuntimeError) {
|
1186
|
+
assert_raise(RuntimeError) { assert_not @pirate.save }
|
1067
1187
|
assert_equal before, @pirate.reload.parrots
|
1068
1188
|
end
|
1069
1189
|
|
@@ -1072,8 +1192,8 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
1072
1192
|
define_method("test_should_run_add_callback_#{callback_type}s_for_habtm") do
|
1073
1193
|
association_name_with_callbacks = "parrots_with_#{callback_type}_callbacks"
|
1074
1194
|
|
1075
|
-
pirate = Pirate.new(:
|
1076
|
-
pirate.
|
1195
|
+
pirate = Pirate.new(catchphrase: "Arr")
|
1196
|
+
pirate.public_send(association_name_with_callbacks).build(name: "Crowe the One-Eyed")
|
1077
1197
|
|
1078
1198
|
expected = [
|
1079
1199
|
"before_adding_#{callback_type}_parrot_<new>",
|
@@ -1086,9 +1206,9 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|
1086
1206
|
define_method("test_should_run_remove_callback_#{callback_type}s_for_habtm") do
|
1087
1207
|
association_name_with_callbacks = "parrots_with_#{callback_type}_callbacks"
|
1088
1208
|
|
1089
|
-
@pirate.
|
1090
|
-
@pirate.
|
1091
|
-
child_id = @pirate.
|
1209
|
+
@pirate.public_send(association_name_with_callbacks).create!(name: "Crowe the One-Eyed")
|
1210
|
+
@pirate.public_send(association_name_with_callbacks).each(&:mark_for_destruction)
|
1211
|
+
child_id = @pirate.public_send(association_name_with_callbacks).first.id
|
1092
1212
|
|
1093
1213
|
@pirate.ship_log.clear
|
1094
1214
|
@pirate.save
|
@@ -1108,60 +1228,60 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
|
1108
1228
|
|
1109
1229
|
def setup
|
1110
1230
|
super
|
1111
|
-
@pirate = Pirate.create(:
|
1112
|
-
@ship = @pirate.create_ship(:
|
1231
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1232
|
+
@ship = @pirate.create_ship(name: "Nights Dirty Lightning")
|
1113
1233
|
end
|
1114
1234
|
|
1115
1235
|
def test_should_still_work_without_an_associated_model
|
1116
1236
|
@ship.destroy
|
1117
1237
|
@pirate.reload.catchphrase = "Arr"
|
1118
1238
|
@pirate.save
|
1119
|
-
assert_equal
|
1239
|
+
assert_equal "Arr", @pirate.reload.catchphrase
|
1120
1240
|
end
|
1121
1241
|
|
1122
1242
|
def test_should_automatically_save_the_associated_model
|
1123
|
-
@pirate.ship.name =
|
1243
|
+
@pirate.ship.name = "The Vile Insanity"
|
1124
1244
|
@pirate.save
|
1125
|
-
assert_equal
|
1245
|
+
assert_equal "The Vile Insanity", @pirate.reload.ship.name
|
1126
1246
|
end
|
1127
1247
|
|
1128
1248
|
def test_changed_for_autosave_should_handle_cycles
|
1129
1249
|
@ship.pirate = @pirate
|
1130
|
-
|
1250
|
+
assert_no_queries { @ship.save! }
|
1131
1251
|
|
1132
1252
|
@parrot = @pirate.parrots.create(name: "some_name")
|
1133
|
-
@parrot.name="changed_name"
|
1253
|
+
@parrot.name = "changed_name"
|
1134
1254
|
assert_queries(1) { @ship.save! }
|
1135
|
-
|
1255
|
+
assert_no_queries { @ship.save! }
|
1136
1256
|
end
|
1137
1257
|
|
1138
1258
|
def test_should_automatically_save_bang_the_associated_model
|
1139
|
-
@pirate.ship.name =
|
1259
|
+
@pirate.ship.name = "The Vile Insanity"
|
1140
1260
|
@pirate.save!
|
1141
|
-
assert_equal
|
1261
|
+
assert_equal "The Vile Insanity", @pirate.reload.ship.name
|
1142
1262
|
end
|
1143
1263
|
|
1144
1264
|
def test_should_automatically_validate_the_associated_model
|
1145
|
-
@pirate.ship.name =
|
1146
|
-
|
1147
|
-
|
1265
|
+
@pirate.ship.name = ""
|
1266
|
+
assert_predicate @pirate, :invalid?
|
1267
|
+
assert_predicate @pirate.errors[:"ship.name"], :any?
|
1148
1268
|
end
|
1149
1269
|
|
1150
1270
|
def test_should_merge_errors_on_the_associated_models_onto_the_parent_even_if_it_is_not_valid
|
1151
1271
|
@pirate.ship.name = nil
|
1152
1272
|
@pirate.catchphrase = nil
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1273
|
+
assert_predicate @pirate, :invalid?
|
1274
|
+
assert_predicate @pirate.errors[:"ship.name"], :any?
|
1275
|
+
assert_predicate @pirate.errors[:catchphrase], :any?
|
1156
1276
|
end
|
1157
1277
|
|
1158
1278
|
def test_should_not_ignore_different_error_messages_on_the_same_attribute
|
1159
1279
|
old_validators = Ship._validators.deep_dup
|
1160
1280
|
old_callbacks = Ship._validate_callbacks.deep_dup
|
1161
|
-
Ship.validates_format_of :name, :
|
1281
|
+
Ship.validates_format_of :name, with: /\w/
|
1162
1282
|
@pirate.ship.name = ""
|
1163
1283
|
@pirate.catchphrase = nil
|
1164
|
-
|
1284
|
+
assert_predicate @pirate, :invalid?
|
1165
1285
|
assert_equal ["can't be blank", "is invalid"], @pirate.errors[:"ship.name"]
|
1166
1286
|
ensure
|
1167
1287
|
Ship._validators = old_validators if old_validators
|
@@ -1169,49 +1289,49 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
|
1169
1289
|
end
|
1170
1290
|
|
1171
1291
|
def test_should_still_allow_to_bypass_validations_on_the_associated_model
|
1172
|
-
@pirate.catchphrase =
|
1173
|
-
@pirate.ship.name =
|
1174
|
-
@pirate.save(:
|
1292
|
+
@pirate.catchphrase = ""
|
1293
|
+
@pirate.ship.name = ""
|
1294
|
+
@pirate.save(validate: false)
|
1175
1295
|
# Oracle saves empty string as NULL
|
1176
1296
|
if current_adapter?(:OracleAdapter)
|
1177
1297
|
assert_equal [nil, nil], [@pirate.reload.catchphrase, @pirate.ship.name]
|
1178
1298
|
else
|
1179
|
-
assert_equal [
|
1299
|
+
assert_equal ["", ""], [@pirate.reload.catchphrase, @pirate.ship.name]
|
1180
1300
|
end
|
1181
1301
|
end
|
1182
1302
|
|
1183
1303
|
def test_should_allow_to_bypass_validations_on_associated_models_at_any_depth
|
1184
|
-
2.times { |i| @pirate.ship.parts.create!(:
|
1304
|
+
2.times { |i| @pirate.ship.parts.create!(name: "part #{i}") }
|
1185
1305
|
|
1186
|
-
@pirate.catchphrase =
|
1187
|
-
@pirate.ship.name =
|
1188
|
-
@pirate.ship.parts.each { |part| part.name =
|
1189
|
-
@pirate.save(:
|
1306
|
+
@pirate.catchphrase = ""
|
1307
|
+
@pirate.ship.name = ""
|
1308
|
+
@pirate.ship.parts.each { |part| part.name = "" }
|
1309
|
+
@pirate.save(validate: false)
|
1190
1310
|
|
1191
1311
|
values = [@pirate.reload.catchphrase, @pirate.ship.name, *@pirate.ship.parts.map(&:name)]
|
1192
1312
|
# Oracle saves empty string as NULL
|
1193
1313
|
if current_adapter?(:OracleAdapter)
|
1194
1314
|
assert_equal [nil, nil, nil, nil], values
|
1195
1315
|
else
|
1196
|
-
assert_equal [
|
1316
|
+
assert_equal ["", "", "", ""], values
|
1197
1317
|
end
|
1198
1318
|
end
|
1199
1319
|
|
1200
1320
|
def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_that
|
1201
|
-
@pirate.ship.name =
|
1321
|
+
@pirate.ship.name = ""
|
1202
1322
|
assert_raise(ActiveRecord::RecordInvalid) do
|
1203
1323
|
@pirate.save!
|
1204
1324
|
end
|
1205
1325
|
end
|
1206
1326
|
|
1207
1327
|
def test_should_not_save_and_return_false_if_a_callback_cancelled_saving
|
1208
|
-
pirate = Pirate.new(:
|
1209
|
-
ship = pirate.build_ship(:
|
1328
|
+
pirate = Pirate.new(catchphrase: "Arr")
|
1329
|
+
ship = pirate.build_ship(name: "The Vile Insanity")
|
1210
1330
|
ship.cancel_save_from_callback = true
|
1211
1331
|
|
1212
|
-
assert_no_difference
|
1213
|
-
assert_no_difference
|
1214
|
-
|
1332
|
+
assert_no_difference "Pirate.count" do
|
1333
|
+
assert_no_difference "Ship.count" do
|
1334
|
+
assert_not pirate.save
|
1215
1335
|
end
|
1216
1336
|
end
|
1217
1337
|
end
|
@@ -1219,51 +1339,75 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
|
1219
1339
|
def test_should_rollback_any_changes_if_an_exception_occurred_while_saving
|
1220
1340
|
before = [@pirate.catchphrase, @pirate.ship.name]
|
1221
1341
|
|
1222
|
-
@pirate.catchphrase =
|
1223
|
-
@pirate.ship.name =
|
1342
|
+
@pirate.catchphrase = "Arr"
|
1343
|
+
@pirate.ship.name = "The Vile Insanity"
|
1224
1344
|
|
1225
1345
|
# Stub the save method of the @pirate.ship instance to raise an exception
|
1226
1346
|
class << @pirate.ship
|
1227
|
-
def save(
|
1347
|
+
def save(**)
|
1228
1348
|
super
|
1229
|
-
raise
|
1349
|
+
raise "Oh noes!"
|
1230
1350
|
end
|
1231
1351
|
end
|
1232
1352
|
|
1233
|
-
assert_raise(RuntimeError) {
|
1353
|
+
assert_raise(RuntimeError) { assert_not @pirate.save }
|
1234
1354
|
assert_equal before, [@pirate.reload.catchphrase, @pirate.ship.name]
|
1235
1355
|
end
|
1236
1356
|
|
1237
1357
|
def test_should_not_load_the_associated_model
|
1238
|
-
assert_queries(1) { @pirate.catchphrase =
|
1358
|
+
assert_queries(1) { @pirate.catchphrase = "Arr"; @pirate.save! }
|
1239
1359
|
end
|
1240
1360
|
|
1241
1361
|
def test_mark_for_destruction_is_ignored_without_autosave_true
|
1242
1362
|
ship = ShipWithoutNestedAttributes.new(name: "The Black Flag")
|
1243
1363
|
ship.parts.build.mark_for_destruction
|
1244
1364
|
|
1245
|
-
|
1365
|
+
assert_not_predicate ship, :valid?
|
1246
1366
|
end
|
1247
1367
|
end
|
1248
1368
|
|
1249
1369
|
class TestAutosaveAssociationOnAHasOneThroughAssociation < ActiveRecord::TestCase
|
1250
1370
|
self.use_transactional_tests = false unless supports_savepoints?
|
1251
1371
|
|
1252
|
-
def
|
1253
|
-
super
|
1372
|
+
def create_member_with_organization
|
1254
1373
|
organization = Organization.create
|
1255
|
-
|
1256
|
-
MemberDetail.create(organization: organization, member:
|
1374
|
+
member = Member.create
|
1375
|
+
MemberDetail.create(organization: organization, member: member)
|
1376
|
+
|
1377
|
+
member
|
1257
1378
|
end
|
1258
1379
|
|
1259
1380
|
def test_should_not_has_one_through_model
|
1260
|
-
|
1261
|
-
|
1381
|
+
member = create_member_with_organization
|
1382
|
+
|
1383
|
+
class << member.organization
|
1384
|
+
def save(**)
|
1385
|
+
super
|
1386
|
+
raise "Oh noes!"
|
1387
|
+
end
|
1388
|
+
end
|
1389
|
+
assert_nothing_raised { member.save }
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
def create_author_with_post_with_comment
|
1393
|
+
Author.create! name: "David" # make comment_id not match author_id
|
1394
|
+
author = Author.create! name: "Sergiy"
|
1395
|
+
post = Post.create! author: author, title: "foo", body: "bar"
|
1396
|
+
Comment.create! post: post, body: "cool comment"
|
1397
|
+
|
1398
|
+
author
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
def test_should_not_reversed_has_one_through_model
|
1402
|
+
author = create_author_with_post_with_comment
|
1403
|
+
|
1404
|
+
class << author.comment_on_first_post
|
1405
|
+
def save(**)
|
1262
1406
|
super
|
1263
|
-
raise
|
1407
|
+
raise "Oh noes!"
|
1264
1408
|
end
|
1265
1409
|
end
|
1266
|
-
assert_nothing_raised {
|
1410
|
+
assert_nothing_raised { author.save }
|
1267
1411
|
end
|
1268
1412
|
end
|
1269
1413
|
|
@@ -1272,70 +1416,70 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
|
|
1272
1416
|
|
1273
1417
|
def setup
|
1274
1418
|
super
|
1275
|
-
@ship = Ship.create(:
|
1276
|
-
@pirate = @ship.create_pirate(:
|
1419
|
+
@ship = Ship.create(name: "Nights Dirty Lightning")
|
1420
|
+
@pirate = @ship.create_pirate(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1277
1421
|
end
|
1278
1422
|
|
1279
1423
|
def test_should_still_work_without_an_associated_model
|
1280
1424
|
@pirate.destroy
|
1281
1425
|
@ship.reload.name = "The Vile Insanity"
|
1282
1426
|
@ship.save
|
1283
|
-
assert_equal
|
1427
|
+
assert_equal "The Vile Insanity", @ship.reload.name
|
1284
1428
|
end
|
1285
1429
|
|
1286
1430
|
def test_should_automatically_save_the_associated_model
|
1287
|
-
@ship.pirate.catchphrase =
|
1431
|
+
@ship.pirate.catchphrase = "Arr"
|
1288
1432
|
@ship.save
|
1289
|
-
assert_equal
|
1433
|
+
assert_equal "Arr", @ship.reload.pirate.catchphrase
|
1290
1434
|
end
|
1291
1435
|
|
1292
1436
|
def test_should_automatically_save_bang_the_associated_model
|
1293
|
-
@ship.pirate.catchphrase =
|
1437
|
+
@ship.pirate.catchphrase = "Arr"
|
1294
1438
|
@ship.save!
|
1295
|
-
assert_equal
|
1439
|
+
assert_equal "Arr", @ship.reload.pirate.catchphrase
|
1296
1440
|
end
|
1297
1441
|
|
1298
1442
|
def test_should_automatically_validate_the_associated_model
|
1299
|
-
@ship.pirate.catchphrase =
|
1300
|
-
|
1301
|
-
|
1443
|
+
@ship.pirate.catchphrase = ""
|
1444
|
+
assert_predicate @ship, :invalid?
|
1445
|
+
assert_predicate @ship.errors[:"pirate.catchphrase"], :any?
|
1302
1446
|
end
|
1303
1447
|
|
1304
1448
|
def test_should_merge_errors_on_the_associated_model_onto_the_parent_even_if_it_is_not_valid
|
1305
1449
|
@ship.name = nil
|
1306
1450
|
@ship.pirate.catchphrase = nil
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1451
|
+
assert_predicate @ship, :invalid?
|
1452
|
+
assert_predicate @ship.errors[:name], :any?
|
1453
|
+
assert_predicate @ship.errors[:"pirate.catchphrase"], :any?
|
1310
1454
|
end
|
1311
1455
|
|
1312
1456
|
def test_should_still_allow_to_bypass_validations_on_the_associated_model
|
1313
|
-
@ship.pirate.catchphrase =
|
1314
|
-
@ship.name =
|
1315
|
-
@ship.save(:
|
1457
|
+
@ship.pirate.catchphrase = ""
|
1458
|
+
@ship.name = ""
|
1459
|
+
@ship.save(validate: false)
|
1316
1460
|
# Oracle saves empty string as NULL
|
1317
1461
|
if current_adapter?(:OracleAdapter)
|
1318
1462
|
assert_equal [nil, nil], [@ship.reload.name, @ship.pirate.catchphrase]
|
1319
1463
|
else
|
1320
|
-
assert_equal [
|
1464
|
+
assert_equal ["", ""], [@ship.reload.name, @ship.pirate.catchphrase]
|
1321
1465
|
end
|
1322
1466
|
end
|
1323
1467
|
|
1324
1468
|
def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_that
|
1325
|
-
@ship.pirate.catchphrase =
|
1469
|
+
@ship.pirate.catchphrase = ""
|
1326
1470
|
assert_raise(ActiveRecord::RecordInvalid) do
|
1327
1471
|
@ship.save!
|
1328
1472
|
end
|
1329
1473
|
end
|
1330
1474
|
|
1331
1475
|
def test_should_not_save_and_return_false_if_a_callback_cancelled_saving
|
1332
|
-
ship = Ship.new(:
|
1333
|
-
pirate = ship.build_pirate(:
|
1476
|
+
ship = Ship.new(name: "The Vile Insanity")
|
1477
|
+
pirate = ship.build_pirate(catchphrase: "Arr")
|
1334
1478
|
pirate.cancel_save_from_callback = true
|
1335
1479
|
|
1336
|
-
assert_no_difference
|
1337
|
-
assert_no_difference
|
1338
|
-
|
1480
|
+
assert_no_difference "Ship.count" do
|
1481
|
+
assert_no_difference "Pirate.count" do
|
1482
|
+
assert_not ship.save
|
1339
1483
|
end
|
1340
1484
|
end
|
1341
1485
|
end
|
@@ -1343,41 +1487,41 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
|
|
1343
1487
|
def test_should_rollback_any_changes_if_an_exception_occurred_while_saving
|
1344
1488
|
before = [@ship.pirate.catchphrase, @ship.name]
|
1345
1489
|
|
1346
|
-
@ship.pirate.catchphrase =
|
1347
|
-
@ship.name =
|
1490
|
+
@ship.pirate.catchphrase = "Arr"
|
1491
|
+
@ship.name = "The Vile Insanity"
|
1348
1492
|
|
1349
1493
|
# Stub the save method of the @ship.pirate instance to raise an exception
|
1350
1494
|
class << @ship.pirate
|
1351
|
-
def save(
|
1495
|
+
def save(**)
|
1352
1496
|
super
|
1353
|
-
raise
|
1497
|
+
raise "Oh noes!"
|
1354
1498
|
end
|
1355
1499
|
end
|
1356
1500
|
|
1357
|
-
assert_raise(RuntimeError) {
|
1501
|
+
assert_raise(RuntimeError) { assert_not @ship.save }
|
1358
1502
|
assert_equal before, [@ship.pirate.reload.catchphrase, @ship.reload.name]
|
1359
1503
|
end
|
1360
1504
|
|
1361
1505
|
def test_should_not_load_the_associated_model
|
1362
|
-
assert_queries(1) { @ship.name =
|
1506
|
+
assert_queries(1) { @ship.name = "The Vile Insanity"; @ship.save! }
|
1363
1507
|
end
|
1364
1508
|
end
|
1365
1509
|
|
1366
1510
|
module AutosaveAssociationOnACollectionAssociationTests
|
1367
1511
|
def test_should_automatically_save_the_associated_models
|
1368
|
-
new_names = [
|
1369
|
-
@pirate.
|
1512
|
+
new_names = ["Grace OMalley", "Privateers Greed"]
|
1513
|
+
@pirate.public_send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
1370
1514
|
|
1371
1515
|
@pirate.save
|
1372
|
-
assert_equal new_names, @pirate.reload.
|
1516
|
+
assert_equal new_names.sort, @pirate.reload.public_send(@association_name).map(&:name).sort
|
1373
1517
|
end
|
1374
1518
|
|
1375
1519
|
def test_should_automatically_save_bang_the_associated_models
|
1376
|
-
new_names = [
|
1377
|
-
@pirate.
|
1520
|
+
new_names = ["Grace OMalley", "Privateers Greed"]
|
1521
|
+
@pirate.public_send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
1378
1522
|
|
1379
1523
|
@pirate.save!
|
1380
|
-
assert_equal new_names, @pirate.reload.
|
1524
|
+
assert_equal new_names.sort, @pirate.reload.public_send(@association_name).map(&:name).sort
|
1381
1525
|
end
|
1382
1526
|
|
1383
1527
|
def test_should_update_children_when_autosave_is_true_and_parent_is_new_but_child_is_not
|
@@ -1399,135 +1543,135 @@ module AutosaveAssociationOnACollectionAssociationTests
|
|
1399
1543
|
end
|
1400
1544
|
|
1401
1545
|
def test_should_automatically_validate_the_associated_models
|
1402
|
-
@pirate.
|
1546
|
+
@pirate.public_send(@association_name).each { |child| child.name = "" }
|
1403
1547
|
|
1404
|
-
|
1548
|
+
assert_not_predicate @pirate, :valid?
|
1405
1549
|
assert_equal ["can't be blank"], @pirate.errors["#{@association_name}.name"]
|
1406
|
-
|
1550
|
+
assert_empty @pirate.errors[@association_name]
|
1407
1551
|
end
|
1408
1552
|
|
1409
1553
|
def test_should_not_use_default_invalid_error_on_associated_models
|
1410
|
-
@pirate.
|
1554
|
+
@pirate.public_send(@association_name).build(name: "")
|
1411
1555
|
|
1412
|
-
|
1556
|
+
assert_not_predicate @pirate, :valid?
|
1413
1557
|
assert_equal ["can't be blank"], @pirate.errors["#{@association_name}.name"]
|
1414
|
-
|
1558
|
+
assert_empty @pirate.errors[@association_name]
|
1415
1559
|
end
|
1416
1560
|
|
1417
1561
|
def test_should_default_invalid_error_from_i18n
|
1418
|
-
I18n.backend.store_translations(:en, activerecord: {errors: { models:
|
1562
|
+
I18n.backend.store_translations(:en, activerecord: { errors: { models:
|
1419
1563
|
{ @associated_model_name.to_s.to_sym => { blank: "cannot be blank" } }
|
1420
|
-
}})
|
1564
|
+
} })
|
1421
1565
|
|
1422
|
-
@pirate.
|
1566
|
+
@pirate.public_send(@association_name).build(name: "")
|
1423
1567
|
|
1424
|
-
|
1568
|
+
assert_not_predicate @pirate, :valid?
|
1425
1569
|
assert_equal ["cannot be blank"], @pirate.errors["#{@association_name}.name"]
|
1426
1570
|
assert_equal ["#{@association_name.to_s.humanize} name cannot be blank"], @pirate.errors.full_messages
|
1427
|
-
|
1571
|
+
assert_empty @pirate.errors[@association_name]
|
1428
1572
|
ensure
|
1429
1573
|
I18n.backend = I18n::Backend::Simple.new
|
1430
1574
|
end
|
1431
1575
|
|
1432
1576
|
def test_should_merge_errors_on_the_associated_models_onto_the_parent_even_if_it_is_not_valid
|
1433
|
-
@pirate.
|
1577
|
+
@pirate.public_send(@association_name).each { |child| child.name = "" }
|
1434
1578
|
@pirate.catchphrase = nil
|
1435
1579
|
|
1436
|
-
|
1580
|
+
assert_not_predicate @pirate, :valid?
|
1437
1581
|
assert_equal ["can't be blank"], @pirate.errors["#{@association_name}.name"]
|
1438
|
-
|
1582
|
+
assert_predicate @pirate.errors[:catchphrase], :any?
|
1439
1583
|
end
|
1440
1584
|
|
1441
1585
|
def test_should_allow_to_bypass_validations_on_the_associated_models_on_update
|
1442
|
-
@pirate.catchphrase =
|
1443
|
-
@pirate.
|
1586
|
+
@pirate.catchphrase = ""
|
1587
|
+
@pirate.public_send(@association_name).each { |child| child.name = "" }
|
1444
1588
|
|
1445
|
-
assert @pirate.save(:
|
1589
|
+
assert @pirate.save(validate: false)
|
1446
1590
|
# Oracle saves empty string as NULL
|
1447
1591
|
if current_adapter?(:OracleAdapter)
|
1448
1592
|
assert_equal [nil, nil, nil], [
|
1449
1593
|
@pirate.reload.catchphrase,
|
1450
|
-
@pirate.
|
1451
|
-
@pirate.
|
1594
|
+
@pirate.public_send(@association_name).first.name,
|
1595
|
+
@pirate.public_send(@association_name).last.name
|
1452
1596
|
]
|
1453
1597
|
else
|
1454
|
-
assert_equal [
|
1598
|
+
assert_equal ["", "", ""], [
|
1455
1599
|
@pirate.reload.catchphrase,
|
1456
|
-
@pirate.
|
1457
|
-
@pirate.
|
1600
|
+
@pirate.public_send(@association_name).first.name,
|
1601
|
+
@pirate.public_send(@association_name).last.name
|
1458
1602
|
]
|
1459
1603
|
end
|
1460
1604
|
end
|
1461
1605
|
|
1462
1606
|
def test_should_validation_the_associated_models_on_create
|
1463
1607
|
assert_no_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count") do
|
1464
|
-
2.times { @pirate.
|
1608
|
+
2.times { @pirate.public_send(@association_name).build }
|
1465
1609
|
@pirate.save
|
1466
1610
|
end
|
1467
1611
|
end
|
1468
1612
|
|
1469
1613
|
def test_should_allow_to_bypass_validations_on_the_associated_models_on_create
|
1470
1614
|
assert_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count", 2) do
|
1471
|
-
2.times { @pirate.
|
1472
|
-
@pirate.save(:
|
1615
|
+
2.times { @pirate.public_send(@association_name).build }
|
1616
|
+
@pirate.save(validate: false)
|
1473
1617
|
end
|
1474
1618
|
end
|
1475
1619
|
|
1476
1620
|
def test_should_not_save_and_return_false_if_a_callback_cancelled_saving_in_either_create_or_update
|
1477
|
-
@pirate.catchphrase =
|
1478
|
-
@child_1.name =
|
1621
|
+
@pirate.catchphrase = "Changed"
|
1622
|
+
@child_1.name = "Changed"
|
1479
1623
|
@child_1.cancel_save_from_callback = true
|
1480
1624
|
|
1481
|
-
|
1625
|
+
assert_not @pirate.save
|
1482
1626
|
assert_equal "Don' botharrr talkin' like one, savvy?", @pirate.reload.catchphrase
|
1483
1627
|
assert_equal "Posideons Killer", @child_1.reload.name
|
1484
1628
|
|
1485
|
-
new_pirate = Pirate.new(:
|
1486
|
-
new_child = new_pirate.
|
1629
|
+
new_pirate = Pirate.new(catchphrase: "Arr")
|
1630
|
+
new_child = new_pirate.public_send(@association_name).build(name: "Grace OMalley")
|
1487
1631
|
new_child.cancel_save_from_callback = true
|
1488
1632
|
|
1489
|
-
assert_no_difference
|
1633
|
+
assert_no_difference "Pirate.count" do
|
1490
1634
|
assert_no_difference "#{new_child.class.name}.count" do
|
1491
|
-
|
1635
|
+
assert_not new_pirate.save
|
1492
1636
|
end
|
1493
1637
|
end
|
1494
1638
|
end
|
1495
1639
|
|
1496
1640
|
def test_should_rollback_any_changes_if_an_exception_occurred_while_saving
|
1497
|
-
before = [@pirate.catchphrase, *@pirate.
|
1498
|
-
new_names = [
|
1641
|
+
before = [@pirate.catchphrase, *@pirate.public_send(@association_name).map(&:name)]
|
1642
|
+
new_names = ["Grace OMalley", "Privateers Greed"]
|
1499
1643
|
|
1500
|
-
@pirate.catchphrase =
|
1501
|
-
@pirate.
|
1644
|
+
@pirate.catchphrase = "Arr"
|
1645
|
+
@pirate.public_send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
1502
1646
|
|
1503
1647
|
# Stub the save method of the first child instance to raise an exception
|
1504
|
-
class << @pirate.
|
1505
|
-
def save(
|
1648
|
+
class << @pirate.public_send(@association_name).first
|
1649
|
+
def save(**)
|
1506
1650
|
super
|
1507
|
-
raise
|
1651
|
+
raise "Oh noes!"
|
1508
1652
|
end
|
1509
1653
|
end
|
1510
1654
|
|
1511
|
-
assert_raise(RuntimeError) {
|
1655
|
+
assert_raise(RuntimeError) { assert_not @pirate.save }
|
1512
1656
|
assert_equal before, [@pirate.reload.catchphrase, *@pirate.send(@association_name).map(&:name)]
|
1513
1657
|
end
|
1514
1658
|
|
1515
1659
|
def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_that
|
1516
|
-
@pirate.
|
1660
|
+
@pirate.public_send(@association_name).each { |child| child.name = "" }
|
1517
1661
|
assert_raise(ActiveRecord::RecordInvalid) do
|
1518
1662
|
@pirate.save!
|
1519
1663
|
end
|
1520
1664
|
end
|
1521
1665
|
|
1522
1666
|
def test_should_not_load_the_associated_models_if_they_were_not_loaded_yet
|
1523
|
-
assert_queries(1) { @pirate.catchphrase =
|
1667
|
+
assert_queries(1) { @pirate.catchphrase = "Arr"; @pirate.save! }
|
1524
1668
|
|
1525
|
-
@pirate.
|
1669
|
+
@pirate.public_send(@association_name).load_target
|
1526
1670
|
|
1527
1671
|
assert_queries(3) do
|
1528
|
-
@pirate.catchphrase =
|
1529
|
-
new_names = [
|
1530
|
-
@pirate.
|
1672
|
+
@pirate.catchphrase = "Yarr"
|
1673
|
+
new_names = ["Grace OMalley", "Privateers Greed"]
|
1674
|
+
@pirate.public_send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
1531
1675
|
@pirate.save!
|
1532
1676
|
end
|
1533
1677
|
end
|
@@ -1541,9 +1685,9 @@ class TestAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase
|
|
1541
1685
|
@association_name = :birds
|
1542
1686
|
@associated_model_name = :bird
|
1543
1687
|
|
1544
|
-
@pirate = Pirate.create(:
|
1545
|
-
@child_1 = @pirate.birds.create(:
|
1546
|
-
@child_2 = @pirate.birds.create(:
|
1688
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1689
|
+
@child_1 = @pirate.birds.create(name: "Posideons Killer")
|
1690
|
+
@child_2 = @pirate.birds.create(name: "Killer bandita Dionne")
|
1547
1691
|
end
|
1548
1692
|
|
1549
1693
|
include AutosaveAssociationOnACollectionAssociationTests
|
@@ -1559,8 +1703,8 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T
|
|
1559
1703
|
@habtm = true
|
1560
1704
|
|
1561
1705
|
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1562
|
-
@child_1 = @pirate.parrots.create(name:
|
1563
|
-
@child_2 = @pirate.parrots.create(name:
|
1706
|
+
@child_1 = @pirate.parrots.create(name: "Posideons Killer")
|
1707
|
+
@child_2 = @pirate.parrots.create(name: "Killer bandita Dionne")
|
1564
1708
|
end
|
1565
1709
|
|
1566
1710
|
include AutosaveAssociationOnACollectionAssociationTests
|
@@ -1576,8 +1720,8 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociationWithAcceptsNestedA
|
|
1576
1720
|
@habtm = true
|
1577
1721
|
|
1578
1722
|
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1579
|
-
@child_1 = @pirate.parrots.create(name:
|
1580
|
-
@child_2 = @pirate.parrots.create(name:
|
1723
|
+
@child_1 = @pirate.parrots.create(name: "Posideons Killer")
|
1724
|
+
@child_2 = @pirate.parrots.create(name: "Killer bandita Dionne")
|
1581
1725
|
end
|
1582
1726
|
|
1583
1727
|
include AutosaveAssociationOnACollectionAssociationTests
|
@@ -1588,15 +1732,63 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te
|
|
1588
1732
|
|
1589
1733
|
def setup
|
1590
1734
|
super
|
1591
|
-
@pirate = Pirate.create(:
|
1592
|
-
@pirate.birds.create(:
|
1735
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1736
|
+
@pirate.birds.create(name: "cookoo")
|
1737
|
+
|
1738
|
+
@author = Author.new(name: "DHH")
|
1739
|
+
@author.published_books.build(name: "Rework", isbn: "1234")
|
1740
|
+
@author.published_books.build(name: "Remote", isbn: "1234")
|
1593
1741
|
end
|
1594
1742
|
|
1595
1743
|
test "should automatically validate associations" do
|
1596
|
-
|
1597
|
-
@pirate.birds.each { |bird| bird.name =
|
1744
|
+
assert_predicate @pirate, :valid?
|
1745
|
+
@pirate.birds.each { |bird| bird.name = "" }
|
1746
|
+
|
1747
|
+
assert_not_predicate @pirate, :valid?
|
1748
|
+
end
|
1749
|
+
|
1750
|
+
test "rollbacks whole transaction and raises ActiveRecord::RecordInvalid when associations fail to #save! due to uniqueness validation failure" do
|
1751
|
+
author_count_before_save = Author.count
|
1752
|
+
book_count_before_save = Book.count
|
1753
|
+
|
1754
|
+
assert_no_difference "Author.count" do
|
1755
|
+
assert_no_difference "Book.count" do
|
1756
|
+
exception = assert_raises(ActiveRecord::RecordInvalid) do
|
1757
|
+
@author.save!
|
1758
|
+
end
|
1759
|
+
|
1760
|
+
assert_equal("Validation failed: Published books is invalid", exception.message)
|
1761
|
+
end
|
1762
|
+
end
|
1763
|
+
|
1764
|
+
assert_equal(author_count_before_save, Author.count)
|
1765
|
+
assert_equal(book_count_before_save, Book.count)
|
1766
|
+
end
|
1598
1767
|
|
1599
|
-
|
1768
|
+
test "rollbacks whole transaction when associations fail to #save due to uniqueness validation failure" do
|
1769
|
+
author_count_before_save = Author.count
|
1770
|
+
book_count_before_save = Book.count
|
1771
|
+
|
1772
|
+
assert_no_difference "Author.count" do
|
1773
|
+
assert_no_difference "Book.count" do
|
1774
|
+
assert_nothing_raised do
|
1775
|
+
result = @author.save
|
1776
|
+
|
1777
|
+
assert_not(result)
|
1778
|
+
end
|
1779
|
+
end
|
1780
|
+
end
|
1781
|
+
|
1782
|
+
assert_equal(author_count_before_save, Author.count)
|
1783
|
+
assert_equal(book_count_before_save, Book.count)
|
1784
|
+
end
|
1785
|
+
|
1786
|
+
def test_validations_still_fire_on_unchanged_association_with_custom_validation_context
|
1787
|
+
pirate = FamousPirate.create!(catchphrase: "Avast Ye!")
|
1788
|
+
pirate.famous_ships.create!
|
1789
|
+
|
1790
|
+
assert pirate.valid?
|
1791
|
+
assert_not pirate.valid?(:conference)
|
1600
1792
|
end
|
1601
1793
|
end
|
1602
1794
|
|
@@ -1605,21 +1797,21 @@ class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::Tes
|
|
1605
1797
|
|
1606
1798
|
def setup
|
1607
1799
|
super
|
1608
|
-
@pirate = Pirate.create(:
|
1609
|
-
@pirate.create_ship(:
|
1800
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1801
|
+
@pirate.create_ship(name: "titanic")
|
1610
1802
|
super
|
1611
1803
|
end
|
1612
1804
|
|
1613
1805
|
test "should automatically validate associations with :validate => true" do
|
1614
|
-
|
1615
|
-
@pirate.ship.name =
|
1616
|
-
|
1806
|
+
assert_predicate @pirate, :valid?
|
1807
|
+
@pirate.ship.name = ""
|
1808
|
+
assert_not_predicate @pirate, :valid?
|
1617
1809
|
end
|
1618
1810
|
|
1619
1811
|
test "should not automatically add validate associations without :validate => true" do
|
1620
|
-
|
1621
|
-
@pirate.non_validated_ship.name =
|
1622
|
-
|
1812
|
+
assert_predicate @pirate, :valid?
|
1813
|
+
@pirate.non_validated_ship.name = ""
|
1814
|
+
assert_predicate @pirate, :valid?
|
1623
1815
|
end
|
1624
1816
|
end
|
1625
1817
|
|
@@ -1628,19 +1820,26 @@ class TestAutosaveAssociationValidationsOnABelongsToAssociation < ActiveRecord::
|
|
1628
1820
|
|
1629
1821
|
def setup
|
1630
1822
|
super
|
1631
|
-
@pirate = Pirate.create(:
|
1823
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1632
1824
|
end
|
1633
1825
|
|
1634
1826
|
test "should automatically validate associations with :validate => true" do
|
1635
|
-
|
1636
|
-
@pirate.parrot = Parrot.new(:
|
1637
|
-
|
1827
|
+
assert_predicate @pirate, :valid?
|
1828
|
+
@pirate.parrot = Parrot.new(name: "")
|
1829
|
+
assert_not_predicate @pirate, :valid?
|
1638
1830
|
end
|
1639
1831
|
|
1640
1832
|
test "should not automatically validate associations without :validate => true" do
|
1641
|
-
|
1642
|
-
@pirate.non_validated_parrot = Parrot.new(:
|
1643
|
-
|
1833
|
+
assert_predicate @pirate, :valid?
|
1834
|
+
@pirate.non_validated_parrot = Parrot.new(name: "")
|
1835
|
+
assert_predicate @pirate, :valid?
|
1836
|
+
end
|
1837
|
+
|
1838
|
+
def test_validations_still_fire_on_unchanged_association_with_custom_validation_context
|
1839
|
+
firm_with_low_credit = Firm.create!(name: "Something", account: Account.new(credit_limit: 50))
|
1840
|
+
|
1841
|
+
assert firm_with_low_credit.valid?
|
1842
|
+
assert_not firm_with_low_credit.valid?(:bank_loan)
|
1644
1843
|
end
|
1645
1844
|
end
|
1646
1845
|
|
@@ -1649,21 +1848,21 @@ class TestAutosaveAssociationValidationsOnAHABTMAssociation < ActiveRecord::Test
|
|
1649
1848
|
|
1650
1849
|
def setup
|
1651
1850
|
super
|
1652
|
-
@pirate = Pirate.create(:
|
1851
|
+
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1653
1852
|
end
|
1654
1853
|
|
1655
1854
|
test "should automatically validate associations with :validate => true" do
|
1656
|
-
|
1657
|
-
@pirate.parrots = [ Parrot.new(:
|
1658
|
-
@pirate.parrots.each { |parrot| parrot.name =
|
1659
|
-
|
1855
|
+
assert_predicate @pirate, :valid?
|
1856
|
+
@pirate.parrots = [ Parrot.new(name: "popuga") ]
|
1857
|
+
@pirate.parrots.each { |parrot| parrot.name = "" }
|
1858
|
+
assert_not_predicate @pirate, :valid?
|
1660
1859
|
end
|
1661
1860
|
|
1662
1861
|
test "should not automatically validate associations without :validate => true" do
|
1663
|
-
|
1664
|
-
@pirate.non_validated_parrots = [ Parrot.new(:
|
1665
|
-
@pirate.non_validated_parrots.each { |parrot| parrot.name =
|
1666
|
-
|
1862
|
+
assert_predicate @pirate, :valid?
|
1863
|
+
@pirate.non_validated_parrots = [ Parrot.new(name: "popuga") ]
|
1864
|
+
@pirate.non_validated_parrots.each { |parrot| parrot.name = "" }
|
1865
|
+
assert_predicate @pirate, :valid?
|
1667
1866
|
end
|
1668
1867
|
end
|
1669
1868
|
|
@@ -1684,7 +1883,7 @@ class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCas
|
|
1684
1883
|
end
|
1685
1884
|
|
1686
1885
|
test "should not generate validation methods for has_one associations without :validate => true" do
|
1687
|
-
|
1886
|
+
assert_not_respond_to @pirate, :validate_associated_records_for_non_validated_ship
|
1688
1887
|
end
|
1689
1888
|
|
1690
1889
|
test "should generate validation methods for belongs_to associations with :validate => true" do
|
@@ -1692,7 +1891,7 @@ class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCas
|
|
1692
1891
|
end
|
1693
1892
|
|
1694
1893
|
test "should not generate validation methods for belongs_to associations without :validate => true" do
|
1695
|
-
|
1894
|
+
assert_not_respond_to @pirate, :validate_associated_records_for_non_validated_parrot
|
1696
1895
|
end
|
1697
1896
|
|
1698
1897
|
test "should generate validation methods for HABTM associations with :validate => true" do
|
@@ -1703,6 +1902,52 @@ end
|
|
1703
1902
|
class TestAutosaveAssociationWithTouch < ActiveRecord::TestCase
|
1704
1903
|
def test_autosave_with_touch_should_not_raise_system_stack_error
|
1705
1904
|
invoice = Invoice.create
|
1706
|
-
assert_nothing_raised { invoice.line_items.create(:
|
1905
|
+
assert_nothing_raised { invoice.line_items.create(amount: 10) }
|
1906
|
+
end
|
1907
|
+
end
|
1908
|
+
|
1909
|
+
class TestAutosaveAssociationOnAHasManyAssociationWithInverse < ActiveRecord::TestCase
|
1910
|
+
class Post < ActiveRecord::Base
|
1911
|
+
has_many :comments, inverse_of: :post
|
1912
|
+
end
|
1913
|
+
|
1914
|
+
class Comment < ActiveRecord::Base
|
1915
|
+
belongs_to :post, inverse_of: :comments
|
1916
|
+
|
1917
|
+
attr_accessor :post_comments_count
|
1918
|
+
after_save do
|
1919
|
+
self.post_comments_count = post.comments.count
|
1920
|
+
end
|
1921
|
+
end
|
1922
|
+
|
1923
|
+
def setup
|
1924
|
+
Comment.delete_all
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
def test_after_save_callback_with_autosave
|
1928
|
+
post = Post.new(title: "Test", body: "...")
|
1929
|
+
comment = post.comments.build(body: "...")
|
1930
|
+
post.save!
|
1931
|
+
|
1932
|
+
assert_equal 1, post.comments.count
|
1933
|
+
assert_equal 1, comment.post_comments_count
|
1934
|
+
end
|
1935
|
+
end
|
1936
|
+
|
1937
|
+
class TestAutosaveAssociationOnAHasManyAssociationDefinedInSubclassWithAcceptsNestedAttributes < ActiveRecord::TestCase
|
1938
|
+
def test_should_update_children_when_association_redefined_in_subclass
|
1939
|
+
agency = Agency.create!(name: "Agency")
|
1940
|
+
valid_project = Project.create!(firm: agency, name: "Initial")
|
1941
|
+
agency.update!(
|
1942
|
+
"projects_attributes" => {
|
1943
|
+
"0" => {
|
1944
|
+
"name" => "Updated",
|
1945
|
+
"id" => valid_project.id
|
1946
|
+
}
|
1947
|
+
}
|
1948
|
+
)
|
1949
|
+
valid_project.reload
|
1950
|
+
|
1951
|
+
assert_equal "Updated", valid_project.name
|
1707
1952
|
end
|
1708
1953
|
end
|