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,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cases/helper"
|
2
4
|
require "models/pirate"
|
3
5
|
require "models/ship"
|
@@ -5,15 +7,15 @@ require "models/ship_part"
|
|
5
7
|
require "models/bird"
|
6
8
|
require "models/parrot"
|
7
9
|
require "models/treasure"
|
8
|
-
require "models/
|
10
|
+
require "models/human"
|
9
11
|
require "models/interest"
|
10
12
|
require "models/owner"
|
11
13
|
require "models/pet"
|
12
|
-
require
|
14
|
+
require "active_support/hash_with_indifferent_access"
|
13
15
|
|
14
16
|
class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
15
17
|
teardown do
|
16
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
18
|
+
Pirate.accepts_nested_attributes_for :ship, allow_destroy: true, reject_if: proc(&:empty?)
|
17
19
|
end
|
18
20
|
|
19
21
|
def test_base_should_have_an_empty_nested_attributes_options
|
@@ -30,28 +32,28 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def test_should_not_build_a_new_record_using_reject_all_even_if_destroy_is_given
|
33
|
-
pirate = Pirate.create!(:
|
34
|
-
pirate.birds_with_reject_all_blank_attributes = [{:
|
35
|
+
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
36
|
+
pirate.birds_with_reject_all_blank_attributes = [{ name: "", color: "", _destroy: "0" }]
|
35
37
|
pirate.save!
|
36
38
|
|
37
|
-
|
39
|
+
assert_empty pirate.birds_with_reject_all_blank
|
38
40
|
end
|
39
41
|
|
40
42
|
def test_should_not_build_a_new_record_if_reject_all_blank_returns_false
|
41
|
-
pirate = Pirate.create!(:
|
42
|
-
pirate.birds_with_reject_all_blank_attributes = [{:
|
43
|
+
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
44
|
+
pirate.birds_with_reject_all_blank_attributes = [{ name: "", color: "" }]
|
43
45
|
pirate.save!
|
44
46
|
|
45
|
-
|
47
|
+
assert_empty pirate.birds_with_reject_all_blank
|
46
48
|
end
|
47
49
|
|
48
50
|
def test_should_build_a_new_record_if_reject_all_blank_does_not_return_false
|
49
|
-
pirate = Pirate.create!(:
|
50
|
-
pirate.birds_with_reject_all_blank_attributes = [{:
|
51
|
+
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
52
|
+
pirate.birds_with_reject_all_blank_attributes = [{ name: "Tweetie", color: "" }]
|
51
53
|
pirate.save!
|
52
54
|
|
53
55
|
assert_equal 1, pirate.birds_with_reject_all_blank.count
|
54
|
-
assert_equal
|
56
|
+
assert_equal "Tweetie", pirate.birds_with_reject_all_blank.first.name
|
55
57
|
end
|
56
58
|
|
57
59
|
def test_should_raise_an_ArgumentError_for_non_existing_associations
|
@@ -63,94 +65,94 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
|
63
65
|
|
64
66
|
def test_should_raise_an_UnknownAttributeError_for_non_existing_nested_attributes
|
65
67
|
exception = assert_raise ActiveModel::UnknownAttributeError do
|
66
|
-
Pirate.new(:
|
68
|
+
Pirate.new(ship_attributes: { sail: true })
|
67
69
|
end
|
68
|
-
|
70
|
+
assert_match "unknown attribute 'sail' for Ship.", exception.message
|
69
71
|
end
|
70
72
|
|
71
73
|
def test_should_disable_allow_destroy_by_default
|
72
74
|
Pirate.accepts_nested_attributes_for :ship
|
73
75
|
|
74
76
|
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
75
|
-
ship = pirate.create_ship(name:
|
77
|
+
ship = pirate.create_ship(name: "Nights Dirty Lightning")
|
76
78
|
|
77
|
-
pirate.update(ship_attributes: {
|
79
|
+
pirate.update(ship_attributes: { "_destroy" => true, :id => ship.id })
|
78
80
|
|
79
81
|
assert_nothing_raised { pirate.ship.reload }
|
80
82
|
end
|
81
83
|
|
82
84
|
def test_a_model_should_respond_to_underscore_destroy_and_return_if_it_is_marked_for_destruction
|
83
|
-
ship = Ship.create!(:
|
84
|
-
|
85
|
+
ship = Ship.create!(name: "Nights Dirty Lightning")
|
86
|
+
assert_not ship._destroy
|
85
87
|
ship.mark_for_destruction
|
86
88
|
assert ship._destroy
|
87
89
|
end
|
88
90
|
|
89
91
|
def test_reject_if_method_without_arguments
|
90
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
92
|
+
Pirate.accepts_nested_attributes_for :ship, reject_if: :new_record?
|
91
93
|
|
92
|
-
pirate = Pirate.new(:
|
93
|
-
pirate.ship_attributes = { :
|
94
|
-
assert_no_difference(
|
94
|
+
pirate = Pirate.new(catchphrase: "Stop wastin' me time")
|
95
|
+
pirate.ship_attributes = { name: "Black Pearl" }
|
96
|
+
assert_no_difference("Ship.count") { pirate.save! }
|
95
97
|
end
|
96
98
|
|
97
99
|
def test_reject_if_method_with_arguments
|
98
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
100
|
+
Pirate.accepts_nested_attributes_for :ship, reject_if: :reject_empty_ships_on_create
|
99
101
|
|
100
|
-
pirate = Pirate.new(:
|
101
|
-
pirate.ship_attributes = { :
|
102
|
-
assert_no_difference(
|
102
|
+
pirate = Pirate.new(catchphrase: "Stop wastin' me time")
|
103
|
+
pirate.ship_attributes = { name: "Red Pearl", _reject_me_if_new: true }
|
104
|
+
assert_no_difference("Ship.count") { pirate.save! }
|
103
105
|
|
104
106
|
# pirate.reject_empty_ships_on_create returns false for saved pirate records
|
105
107
|
# in the previous step note that pirate gets saved but ship fails
|
106
|
-
pirate.ship_attributes = { :
|
107
|
-
assert_difference(
|
108
|
+
pirate.ship_attributes = { name: "Red Pearl", _reject_me_if_new: true }
|
109
|
+
assert_difference("Ship.count") { pirate.save! }
|
108
110
|
end
|
109
111
|
|
110
112
|
def test_reject_if_with_indifferent_keys
|
111
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
113
|
+
Pirate.accepts_nested_attributes_for :ship, reject_if: proc { |attributes| attributes[:name].blank? }
|
112
114
|
|
113
|
-
pirate = Pirate.new(:
|
114
|
-
pirate.ship_attributes = { :
|
115
|
-
assert_difference(
|
115
|
+
pirate = Pirate.new(catchphrase: "Stop wastin' me time")
|
116
|
+
pirate.ship_attributes = { name: "Hello Pearl" }
|
117
|
+
assert_difference("Ship.count") { pirate.save! }
|
116
118
|
end
|
117
119
|
|
118
120
|
def test_reject_if_with_a_proc_which_returns_true_always_for_has_one
|
119
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
120
|
-
pirate = Pirate.
|
121
|
-
ship = pirate.create_ship(name:
|
122
|
-
pirate.update(
|
123
|
-
assert_equal
|
121
|
+
Pirate.accepts_nested_attributes_for :ship, reject_if: proc { |attributes| true }
|
122
|
+
pirate = Pirate.create(catchphrase: "Stop wastin' me time")
|
123
|
+
ship = pirate.create_ship(name: "s1")
|
124
|
+
pirate.update(ship_attributes: { name: "s2", id: ship.id })
|
125
|
+
assert_equal "s1", ship.reload.name
|
124
126
|
end
|
125
127
|
|
126
128
|
def test_reuse_already_built_new_record
|
127
129
|
pirate = Pirate.new
|
128
130
|
ship_built_first = pirate.build_ship
|
129
|
-
pirate.ship_attributes = { name:
|
130
|
-
|
131
|
+
pirate.ship_attributes = { name: "Ship 1" }
|
132
|
+
assert_same ship_built_first, pirate.ship
|
131
133
|
end
|
132
134
|
|
133
135
|
def test_do_not_allow_assigning_foreign_key_when_reusing_existing_new_record
|
134
136
|
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
135
137
|
pirate.build_ship
|
136
|
-
pirate.ship_attributes = { name:
|
138
|
+
pirate.ship_attributes = { name: "Ship 1", pirate_id: pirate.id + 1 }
|
137
139
|
assert_equal pirate.id, pirate.ship.pirate_id
|
138
140
|
end
|
139
141
|
|
140
142
|
def test_reject_if_with_a_proc_which_returns_true_always_for_has_many
|
141
|
-
|
142
|
-
|
143
|
-
interest =
|
144
|
-
|
145
|
-
assert_equal
|
143
|
+
Human.accepts_nested_attributes_for :interests, reject_if: proc { |attributes| true }
|
144
|
+
human = Human.create(name: "John")
|
145
|
+
interest = human.interests.create(topic: "photography")
|
146
|
+
human.update(interests_attributes: { topic: "gardening", id: interest.id })
|
147
|
+
assert_equal "photography", interest.reload.topic
|
146
148
|
end
|
147
149
|
|
148
150
|
def test_destroy_works_independent_of_reject_if
|
149
|
-
|
150
|
-
|
151
|
-
interest =
|
152
|
-
|
153
|
-
|
151
|
+
Human.accepts_nested_attributes_for :interests, reject_if: proc { |attributes| true }, allow_destroy: true
|
152
|
+
human = Human.create(name: "Jon")
|
153
|
+
interest = human.interests.create(topic: "the ladies")
|
154
|
+
human.update(interests_attributes: { _destroy: "1", id: interest.id })
|
155
|
+
assert_empty human.reload.interests
|
154
156
|
end
|
155
157
|
|
156
158
|
def test_reject_if_is_not_short_circuited_if_allow_destroy_is_false
|
@@ -167,40 +169,40 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
|
167
169
|
end
|
168
170
|
|
169
171
|
def test_has_many_association_updating_a_single_record
|
170
|
-
|
171
|
-
|
172
|
-
interest =
|
173
|
-
|
174
|
-
assert_equal
|
172
|
+
Human.accepts_nested_attributes_for(:interests)
|
173
|
+
human = Human.create(name: "John")
|
174
|
+
interest = human.interests.create(topic: "photography")
|
175
|
+
human.update(interests_attributes: { topic: "gardening", id: interest.id })
|
176
|
+
assert_equal "gardening", interest.reload.topic
|
175
177
|
end
|
176
178
|
|
177
179
|
def test_reject_if_with_blank_nested_attributes_id
|
178
180
|
# When using a select list to choose an existing 'ship' id, with include_blank: true
|
179
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
181
|
+
Pirate.accepts_nested_attributes_for :ship, reject_if: proc { |attributes| attributes[:id].blank? }
|
180
182
|
|
181
|
-
pirate = Pirate.new(:
|
182
|
-
pirate.ship_attributes = { :
|
183
|
+
pirate = Pirate.new(catchphrase: "Stop wastin' me time")
|
184
|
+
pirate.ship_attributes = { id: "" }
|
183
185
|
assert_nothing_raised { pirate.save! }
|
184
186
|
end
|
185
187
|
|
186
188
|
def test_first_and_array_index_zero_methods_return_the_same_value_when_nested_attributes_are_set_to_update_existing_record
|
187
|
-
|
188
|
-
|
189
|
-
interest =
|
190
|
-
|
191
|
-
|
192
|
-
assert_equal
|
189
|
+
Human.accepts_nested_attributes_for(:interests)
|
190
|
+
human = Human.create(name: "John")
|
191
|
+
interest = human.interests.create topic: "gardening"
|
192
|
+
human = Human.find human.id
|
193
|
+
human.interests_attributes = [{ id: interest.id, topic: "gardening" }]
|
194
|
+
assert_equal human.interests.first.topic, human.interests[0].topic
|
193
195
|
end
|
194
196
|
|
195
197
|
def test_allows_class_to_override_setter_and_call_super
|
196
198
|
mean_pirate_class = Class.new(Pirate) do
|
197
199
|
accepts_nested_attributes_for :parrot
|
198
200
|
def parrot_attributes=(attrs)
|
199
|
-
super(attrs.merge(:
|
201
|
+
super(attrs.merge(color: "blue"))
|
200
202
|
end
|
201
203
|
end
|
202
204
|
mean_pirate = mean_pirate_class.new
|
203
|
-
mean_pirate.parrot_attributes = { :
|
205
|
+
mean_pirate.parrot_attributes = { name: "James" }
|
204
206
|
assert_equal "James", mean_pirate.parrot.name
|
205
207
|
assert_equal "blue", mean_pirate.parrot.color
|
206
208
|
end
|
@@ -212,20 +214,32 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
|
212
214
|
accepts_nested_attributes_for :parrot
|
213
215
|
end
|
214
216
|
mean_pirate = mean_pirate_class.new
|
215
|
-
mean_pirate.parrot_attributes = { :
|
217
|
+
mean_pirate.parrot_attributes = { name: "James" }
|
216
218
|
assert_equal "James", mean_pirate.parrot.name
|
217
219
|
end
|
220
|
+
|
221
|
+
def test_should_not_create_duplicates_with_create_with
|
222
|
+
Human.accepts_nested_attributes_for(:interests)
|
223
|
+
|
224
|
+
assert_difference("Interest.count", 1) do
|
225
|
+
Human.create_with(
|
226
|
+
interests_attributes: [{ topic: "Pirate king" }]
|
227
|
+
).find_or_create_by!(
|
228
|
+
name: "Monkey D. Luffy"
|
229
|
+
)
|
230
|
+
end
|
231
|
+
end
|
218
232
|
end
|
219
233
|
|
220
234
|
class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
221
235
|
def setup
|
222
|
-
@pirate = Pirate.create!(:
|
223
|
-
@ship = @pirate.create_ship(:
|
236
|
+
@pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
237
|
+
@ship = @pirate.create_ship(name: "Nights Dirty Lightning")
|
224
238
|
end
|
225
239
|
|
226
240
|
def test_should_raise_argument_error_if_trying_to_build_polymorphic_belongs_to
|
227
241
|
exception = assert_raise ArgumentError do
|
228
|
-
Treasure.new(:
|
242
|
+
Treasure.new(name: "pearl", looter_attributes: { catchphrase: "Arrr" })
|
229
243
|
end
|
230
244
|
assert_equal "Cannot build association `looter'. Are you trying to build a polymorphic one-to-one association?", exception.message
|
231
245
|
end
|
@@ -236,15 +250,15 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|
236
250
|
|
237
251
|
def test_should_build_a_new_record_if_there_is_no_id
|
238
252
|
@ship.destroy
|
239
|
-
@pirate.reload.ship_attributes = { :
|
253
|
+
@pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger" }
|
240
254
|
|
241
|
-
|
242
|
-
assert_equal
|
255
|
+
assert_not_predicate @pirate.ship, :persisted?
|
256
|
+
assert_equal "Davy Jones Gold Dagger", @pirate.ship.name
|
243
257
|
end
|
244
258
|
|
245
259
|
def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
|
246
260
|
@ship.destroy
|
247
|
-
@pirate.reload.ship_attributes = { :
|
261
|
+
@pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger", _destroy: "1" }
|
248
262
|
|
249
263
|
assert_nil @pirate.ship
|
250
264
|
end
|
@@ -257,54 +271,54 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|
257
271
|
end
|
258
272
|
|
259
273
|
def test_should_replace_an_existing_record_if_there_is_no_id
|
260
|
-
@pirate.reload.ship_attributes = { :
|
274
|
+
@pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger" }
|
261
275
|
|
262
|
-
|
263
|
-
assert_equal
|
264
|
-
assert_equal
|
276
|
+
assert_not_predicate @pirate.ship, :persisted?
|
277
|
+
assert_equal "Davy Jones Gold Dagger", @pirate.ship.name
|
278
|
+
assert_equal "Nights Dirty Lightning", @ship.name
|
265
279
|
end
|
266
280
|
|
267
281
|
def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
|
268
|
-
@pirate.reload.ship_attributes = { :
|
282
|
+
@pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger", _destroy: "1" }
|
269
283
|
|
270
284
|
assert_equal @ship, @pirate.ship
|
271
|
-
assert_equal
|
285
|
+
assert_equal "Nights Dirty Lightning", @pirate.ship.name
|
272
286
|
end
|
273
287
|
|
274
288
|
def test_should_modify_an_existing_record_if_there_is_a_matching_id
|
275
|
-
@pirate.reload.ship_attributes = { :
|
289
|
+
@pirate.reload.ship_attributes = { id: @ship.id, name: "Davy Jones Gold Dagger" }
|
276
290
|
|
277
291
|
assert_equal @ship, @pirate.ship
|
278
|
-
assert_equal
|
292
|
+
assert_equal "Davy Jones Gold Dagger", @pirate.ship.name
|
279
293
|
end
|
280
294
|
|
281
295
|
def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
|
282
296
|
exception = assert_raise ActiveRecord::RecordNotFound do
|
283
|
-
@pirate.ship_attributes = { :
|
297
|
+
@pirate.ship_attributes = { id: 1234567890 }
|
284
298
|
end
|
285
299
|
assert_equal "Couldn't find Ship with ID=1234567890 for Pirate with ID=#{@pirate.id}", exception.message
|
286
300
|
end
|
287
301
|
|
288
302
|
def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
|
289
|
-
@pirate.reload.ship_attributes = {
|
303
|
+
@pirate.reload.ship_attributes = { "id" => @ship.id, "name" => "Davy Jones Gold Dagger" }
|
290
304
|
|
291
305
|
assert_equal @ship, @pirate.ship
|
292
|
-
assert_equal
|
306
|
+
assert_equal "Davy Jones Gold Dagger", @pirate.ship.name
|
293
307
|
end
|
294
308
|
|
295
309
|
def test_should_modify_an_existing_record_if_there_is_a_matching_composite_id
|
296
|
-
@ship.stub(:id,
|
297
|
-
@pirate.ship_attributes = { :
|
310
|
+
@ship.stub(:id, "ABC1X") do
|
311
|
+
@pirate.ship_attributes = { id: @ship.id, name: "Davy Jones Gold Dagger" }
|
298
312
|
|
299
|
-
assert_equal
|
313
|
+
assert_equal "Davy Jones Gold Dagger", @pirate.ship.name
|
300
314
|
end
|
301
315
|
end
|
302
316
|
|
303
317
|
def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
|
304
318
|
@pirate.ship.destroy
|
305
319
|
|
306
|
-
[1,
|
307
|
-
ship = @pirate.reload.create_ship(name:
|
320
|
+
[1, "1", true, "true"].each do |truth|
|
321
|
+
ship = @pirate.reload.create_ship(name: "Mister Pablo")
|
308
322
|
@pirate.update(ship_attributes: { id: ship.id, _destroy: truth })
|
309
323
|
|
310
324
|
assert_nil @pirate.reload.ship
|
@@ -313,7 +327,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|
313
327
|
end
|
314
328
|
|
315
329
|
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
|
316
|
-
[nil,
|
330
|
+
[nil, "0", 0, "false", false].each do |not_truth|
|
317
331
|
@pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: not_truth })
|
318
332
|
|
319
333
|
assert_equal @ship, @pirate.reload.ship
|
@@ -321,39 +335,39 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|
321
335
|
end
|
322
336
|
|
323
337
|
def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
|
324
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
338
|
+
Pirate.accepts_nested_attributes_for :ship, allow_destroy: false, reject_if: proc(&:empty?)
|
325
339
|
|
326
|
-
@pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy:
|
340
|
+
@pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: "1" })
|
327
341
|
|
328
342
|
assert_equal @ship, @pirate.reload.ship
|
329
343
|
|
330
|
-
Pirate.accepts_nested_attributes_for :ship, :
|
344
|
+
Pirate.accepts_nested_attributes_for :ship, allow_destroy: true, reject_if: proc(&:empty?)
|
331
345
|
end
|
332
346
|
|
333
347
|
def test_should_also_work_with_a_HashWithIndifferentAccess
|
334
|
-
@pirate.ship_attributes = ActiveSupport::HashWithIndifferentAccess.new(:
|
348
|
+
@pirate.ship_attributes = ActiveSupport::HashWithIndifferentAccess.new(id: @ship.id, name: "Davy Jones Gold Dagger")
|
335
349
|
|
336
|
-
|
337
|
-
assert_equal
|
350
|
+
assert_predicate @pirate.ship, :persisted?
|
351
|
+
assert_equal "Davy Jones Gold Dagger", @pirate.ship.name
|
338
352
|
end
|
339
353
|
|
340
354
|
def test_should_work_with_update_as_well
|
341
|
-
@pirate.update(
|
355
|
+
@pirate.update(catchphrase: "Arr", ship_attributes: { id: @ship.id, name: "Mister Pablo" })
|
342
356
|
@pirate.reload
|
343
357
|
|
344
|
-
assert_equal
|
345
|
-
assert_equal
|
358
|
+
assert_equal "Arr", @pirate.catchphrase
|
359
|
+
assert_equal "Mister Pablo", @pirate.ship.name
|
346
360
|
end
|
347
361
|
|
348
362
|
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
|
349
|
-
@pirate.attributes = { :
|
363
|
+
@pirate.attributes = { ship_attributes: { id: @ship.id, _destroy: "1" } }
|
350
364
|
|
351
|
-
|
352
|
-
|
365
|
+
assert_not_predicate @pirate.ship, :destroyed?
|
366
|
+
assert_predicate @pirate.ship, :marked_for_destruction?
|
353
367
|
|
354
368
|
@pirate.save
|
355
369
|
|
356
|
-
|
370
|
+
assert_predicate @pirate.ship, :destroyed?
|
357
371
|
assert_nil @pirate.reload.ship
|
358
372
|
end
|
359
373
|
|
@@ -362,56 +376,55 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|
362
376
|
end
|
363
377
|
|
364
378
|
def test_should_accept_update_only_option
|
365
|
-
@pirate.update(update_only_ship_attributes: { id: @pirate.ship.id, name:
|
379
|
+
@pirate.update(update_only_ship_attributes: { id: @pirate.ship.id, name: "Mayflower" })
|
366
380
|
end
|
367
381
|
|
368
382
|
def test_should_create_new_model_when_nothing_is_there_and_update_only_is_true
|
369
383
|
@ship.delete
|
370
384
|
|
371
|
-
@pirate.reload.update(update_only_ship_attributes: { name:
|
385
|
+
@pirate.reload.update(update_only_ship_attributes: { name: "Mayflower" })
|
372
386
|
|
373
387
|
assert_not_nil @pirate.ship
|
374
388
|
end
|
375
389
|
|
376
390
|
def test_should_update_existing_when_update_only_is_true_and_no_id_is_given
|
377
391
|
@ship.delete
|
378
|
-
@ship = @pirate.create_update_only_ship(name:
|
392
|
+
@ship = @pirate.create_update_only_ship(name: "Nights Dirty Lightning")
|
379
393
|
|
380
|
-
@pirate.update(update_only_ship_attributes: { name:
|
394
|
+
@pirate.update(update_only_ship_attributes: { name: "Mayflower" })
|
381
395
|
|
382
|
-
assert_equal
|
396
|
+
assert_equal "Mayflower", @ship.reload.name
|
383
397
|
assert_equal @ship, @pirate.reload.ship
|
384
398
|
end
|
385
399
|
|
386
400
|
def test_should_update_existing_when_update_only_is_true_and_id_is_given
|
387
401
|
@ship.delete
|
388
|
-
@ship = @pirate.create_update_only_ship(name:
|
402
|
+
@ship = @pirate.create_update_only_ship(name: "Nights Dirty Lightning")
|
389
403
|
|
390
|
-
@pirate.update(update_only_ship_attributes: { name:
|
404
|
+
@pirate.update(update_only_ship_attributes: { name: "Mayflower", id: @ship.id })
|
391
405
|
|
392
|
-
assert_equal
|
406
|
+
assert_equal "Mayflower", @ship.reload.name
|
393
407
|
assert_equal @ship, @pirate.reload.ship
|
394
408
|
end
|
395
409
|
|
396
410
|
def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is_marked_for_destruction
|
397
|
-
Pirate.accepts_nested_attributes_for :update_only_ship, :
|
411
|
+
Pirate.accepts_nested_attributes_for :update_only_ship, update_only: true, allow_destroy: true
|
398
412
|
@ship.delete
|
399
|
-
@ship = @pirate.create_update_only_ship(name:
|
413
|
+
@ship = @pirate.create_update_only_ship(name: "Nights Dirty Lightning")
|
400
414
|
|
401
|
-
@pirate.update(update_only_ship_attributes: { name:
|
415
|
+
@pirate.update(update_only_ship_attributes: { name: "Mayflower", id: @ship.id, _destroy: true })
|
402
416
|
|
403
417
|
assert_nil @pirate.reload.ship
|
404
418
|
assert_raise(ActiveRecord::RecordNotFound) { Ship.find(@ship.id) }
|
405
419
|
|
406
|
-
Pirate.accepts_nested_attributes_for :update_only_ship, :
|
420
|
+
Pirate.accepts_nested_attributes_for :update_only_ship, update_only: true, allow_destroy: false
|
407
421
|
end
|
408
|
-
|
409
422
|
end
|
410
423
|
|
411
424
|
class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
412
425
|
def setup
|
413
|
-
@ship = Ship.new(:
|
414
|
-
@pirate = @ship.build_pirate(:
|
426
|
+
@ship = Ship.new(name: "Nights Dirty Lightning")
|
427
|
+
@pirate = @ship.build_pirate(catchphrase: "Aye")
|
415
428
|
@ship.save!
|
416
429
|
end
|
417
430
|
|
@@ -421,15 +434,15 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|
421
434
|
|
422
435
|
def test_should_build_a_new_record_if_there_is_no_id
|
423
436
|
@pirate.destroy
|
424
|
-
@ship.reload.pirate_attributes = { :
|
437
|
+
@ship.reload.pirate_attributes = { catchphrase: "Arr" }
|
425
438
|
|
426
|
-
|
427
|
-
assert_equal
|
439
|
+
assert_not_predicate @ship.pirate, :persisted?
|
440
|
+
assert_equal "Arr", @ship.pirate.catchphrase
|
428
441
|
end
|
429
442
|
|
430
443
|
def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
|
431
444
|
@pirate.destroy
|
432
|
-
@ship.reload.pirate_attributes = { :
|
445
|
+
@ship.reload.pirate_attributes = { catchphrase: "Arr", _destroy: "1" }
|
433
446
|
|
434
447
|
assert_nil @ship.pirate
|
435
448
|
end
|
@@ -442,53 +455,53 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|
442
455
|
end
|
443
456
|
|
444
457
|
def test_should_replace_an_existing_record_if_there_is_no_id
|
445
|
-
@ship.reload.pirate_attributes = { :
|
458
|
+
@ship.reload.pirate_attributes = { catchphrase: "Arr" }
|
446
459
|
|
447
|
-
|
448
|
-
assert_equal
|
449
|
-
assert_equal
|
460
|
+
assert_not_predicate @ship.pirate, :persisted?
|
461
|
+
assert_equal "Arr", @ship.pirate.catchphrase
|
462
|
+
assert_equal "Aye", @pirate.catchphrase
|
450
463
|
end
|
451
464
|
|
452
465
|
def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
|
453
|
-
@ship.reload.pirate_attributes = { :
|
466
|
+
@ship.reload.pirate_attributes = { catchphrase: "Arr", _destroy: "1" }
|
454
467
|
|
455
468
|
assert_equal @pirate, @ship.pirate
|
456
|
-
assert_equal
|
469
|
+
assert_equal "Aye", @ship.pirate.catchphrase
|
457
470
|
end
|
458
471
|
|
459
472
|
def test_should_modify_an_existing_record_if_there_is_a_matching_id
|
460
|
-
@ship.reload.pirate_attributes = { :
|
473
|
+
@ship.reload.pirate_attributes = { id: @pirate.id, catchphrase: "Arr" }
|
461
474
|
|
462
475
|
assert_equal @pirate, @ship.pirate
|
463
|
-
assert_equal
|
476
|
+
assert_equal "Arr", @ship.pirate.catchphrase
|
464
477
|
end
|
465
478
|
|
466
479
|
def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
|
467
480
|
exception = assert_raise ActiveRecord::RecordNotFound do
|
468
|
-
@ship.pirate_attributes = { :
|
481
|
+
@ship.pirate_attributes = { id: 1234567890 }
|
469
482
|
end
|
470
483
|
assert_equal "Couldn't find Pirate with ID=1234567890 for Ship with ID=#{@ship.id}", exception.message
|
471
484
|
end
|
472
485
|
|
473
486
|
def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
|
474
|
-
@ship.reload.pirate_attributes = {
|
487
|
+
@ship.reload.pirate_attributes = { "id" => @pirate.id, "catchphrase" => "Arr" }
|
475
488
|
|
476
489
|
assert_equal @pirate, @ship.pirate
|
477
|
-
assert_equal
|
490
|
+
assert_equal "Arr", @ship.pirate.catchphrase
|
478
491
|
end
|
479
492
|
|
480
493
|
def test_should_modify_an_existing_record_if_there_is_a_matching_composite_id
|
481
|
-
@pirate.stub(:id,
|
482
|
-
@ship.pirate_attributes = { :
|
494
|
+
@pirate.stub(:id, "ABC1X") do
|
495
|
+
@ship.pirate_attributes = { id: @pirate.id, catchphrase: "Arr" }
|
483
496
|
|
484
|
-
assert_equal
|
497
|
+
assert_equal "Arr", @ship.pirate.catchphrase
|
485
498
|
end
|
486
499
|
end
|
487
500
|
|
488
501
|
def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
|
489
502
|
@ship.pirate.destroy
|
490
|
-
[1,
|
491
|
-
pirate = @ship.reload.create_pirate(catchphrase:
|
503
|
+
[1, "1", true, "true"].each do |truth|
|
504
|
+
pirate = @ship.reload.create_pirate(catchphrase: "Arr")
|
492
505
|
@ship.update(pirate_attributes: { id: pirate.id, _destroy: truth })
|
493
506
|
assert_raise(ActiveRecord::RecordNotFound) { pirate.reload }
|
494
507
|
end
|
@@ -509,33 +522,33 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|
509
522
|
end
|
510
523
|
|
511
524
|
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
|
512
|
-
[nil,
|
525
|
+
[nil, "0", 0, "false", false].each do |not_truth|
|
513
526
|
@ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: not_truth })
|
514
527
|
assert_nothing_raised { @ship.pirate.reload }
|
515
528
|
end
|
516
529
|
end
|
517
530
|
|
518
531
|
def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
|
519
|
-
Ship.accepts_nested_attributes_for :pirate, :
|
532
|
+
Ship.accepts_nested_attributes_for :pirate, allow_destroy: false, reject_if: proc(&:empty?)
|
520
533
|
|
521
|
-
@ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy:
|
534
|
+
@ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: "1" })
|
522
535
|
assert_nothing_raised { @ship.pirate.reload }
|
523
536
|
ensure
|
524
|
-
Ship.accepts_nested_attributes_for :pirate, :
|
537
|
+
Ship.accepts_nested_attributes_for :pirate, allow_destroy: true, reject_if: proc(&:empty?)
|
525
538
|
end
|
526
539
|
|
527
540
|
def test_should_work_with_update_as_well
|
528
|
-
@ship.update(
|
541
|
+
@ship.update(name: "Mister Pablo", pirate_attributes: { catchphrase: "Arr" })
|
529
542
|
@ship.reload
|
530
543
|
|
531
|
-
assert_equal
|
532
|
-
assert_equal
|
544
|
+
assert_equal "Mister Pablo", @ship.name
|
545
|
+
assert_equal "Arr", @ship.pirate.catchphrase
|
533
546
|
end
|
534
547
|
|
535
548
|
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
|
536
549
|
pirate = @ship.pirate
|
537
550
|
|
538
|
-
@ship.attributes = { :
|
551
|
+
@ship.attributes = { pirate_attributes: { :id => pirate.id, "_destroy" => true } }
|
539
552
|
assert_nothing_raised { Pirate.find(pirate.id) }
|
540
553
|
@ship.save
|
541
554
|
assert_raise(ActiveRecord::RecordNotFound) { Pirate.find(pirate.id) }
|
@@ -547,40 +560,40 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|
547
560
|
|
548
561
|
def test_should_create_new_model_when_nothing_is_there_and_update_only_is_true
|
549
562
|
@pirate.delete
|
550
|
-
@ship.reload.attributes = { :
|
563
|
+
@ship.reload.attributes = { update_only_pirate_attributes: { catchphrase: "Arr" } }
|
551
564
|
|
552
|
-
|
565
|
+
assert_not_predicate @ship.update_only_pirate, :persisted?
|
553
566
|
end
|
554
567
|
|
555
568
|
def test_should_update_existing_when_update_only_is_true_and_no_id_is_given
|
556
569
|
@pirate.delete
|
557
|
-
@pirate = @ship.create_update_only_pirate(catchphrase:
|
570
|
+
@pirate = @ship.create_update_only_pirate(catchphrase: "Aye")
|
558
571
|
|
559
|
-
@ship.update(update_only_pirate_attributes: { catchphrase:
|
560
|
-
assert_equal
|
572
|
+
@ship.update(update_only_pirate_attributes: { catchphrase: "Arr" })
|
573
|
+
assert_equal "Arr", @pirate.reload.catchphrase
|
561
574
|
assert_equal @pirate, @ship.reload.update_only_pirate
|
562
575
|
end
|
563
576
|
|
564
577
|
def test_should_update_existing_when_update_only_is_true_and_id_is_given
|
565
578
|
@pirate.delete
|
566
|
-
@pirate = @ship.create_update_only_pirate(catchphrase:
|
579
|
+
@pirate = @ship.create_update_only_pirate(catchphrase: "Aye")
|
567
580
|
|
568
|
-
@ship.update(update_only_pirate_attributes: { catchphrase:
|
581
|
+
@ship.update(update_only_pirate_attributes: { catchphrase: "Arr", id: @pirate.id })
|
569
582
|
|
570
|
-
assert_equal
|
583
|
+
assert_equal "Arr", @pirate.reload.catchphrase
|
571
584
|
assert_equal @pirate, @ship.reload.update_only_pirate
|
572
585
|
end
|
573
586
|
|
574
587
|
def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is_marked_for_destruction
|
575
|
-
Ship.accepts_nested_attributes_for :update_only_pirate, :
|
588
|
+
Ship.accepts_nested_attributes_for :update_only_pirate, update_only: true, allow_destroy: true
|
576
589
|
@pirate.delete
|
577
|
-
@pirate = @ship.create_update_only_pirate(catchphrase:
|
590
|
+
@pirate = @ship.create_update_only_pirate(catchphrase: "Aye")
|
578
591
|
|
579
|
-
@ship.update(update_only_pirate_attributes: { catchphrase:
|
592
|
+
@ship.update(update_only_pirate_attributes: { catchphrase: "Arr", id: @pirate.id, _destroy: true })
|
580
593
|
|
581
594
|
assert_raise(ActiveRecord::RecordNotFound) { @pirate.reload }
|
582
595
|
|
583
|
-
Ship.accepts_nested_attributes_for :update_only_pirate, :
|
596
|
+
Ship.accepts_nested_attributes_for :update_only_pirate, update_only: true, allow_destroy: false
|
584
597
|
end
|
585
598
|
end
|
586
599
|
|
@@ -593,105 +606,103 @@ module NestedAttributesOnACollectionAssociationTests
|
|
593
606
|
exception = assert_raise ActiveModel::UnknownAttributeError do
|
594
607
|
@pirate.parrots_attributes = [{ peg_leg: true }]
|
595
608
|
end
|
596
|
-
|
609
|
+
assert_match "unknown attribute 'peg_leg' for Parrot.", exception.message
|
597
610
|
end
|
598
611
|
|
599
612
|
def test_should_save_only_one_association_on_create
|
600
|
-
pirate = Pirate.create!(
|
601
|
-
:catchphrase =>
|
602
|
-
association_getter => {
|
603
|
-
})
|
613
|
+
pirate = Pirate.create!(
|
614
|
+
:catchphrase => "Arr",
|
615
|
+
association_getter => { "foo" => { name: "Grace OMalley" } })
|
604
616
|
|
605
|
-
assert_equal 1, pirate.reload.
|
617
|
+
assert_equal 1, pirate.reload.public_send(@association_name).count
|
606
618
|
end
|
607
619
|
|
608
620
|
def test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models
|
609
621
|
@alternate_params[association_getter].stringify_keys!
|
610
622
|
@pirate.update @alternate_params
|
611
|
-
assert_equal [
|
623
|
+
assert_equal ["Grace OMalley", "Privateers Greed"], [@child_1.reload.name, @child_2.reload.name]
|
612
624
|
end
|
613
625
|
|
614
626
|
def test_should_take_an_array_and_assign_the_attributes_to_the_associated_models
|
615
|
-
@pirate.
|
627
|
+
@pirate.public_send(association_setter, @alternate_params[association_getter].values)
|
616
628
|
@pirate.save
|
617
|
-
assert_equal [
|
629
|
+
assert_equal ["Grace OMalley", "Privateers Greed"], [@child_1.reload.name, @child_2.reload.name]
|
618
630
|
end
|
619
631
|
|
620
632
|
def test_should_also_work_with_a_HashWithIndifferentAccess
|
621
|
-
@pirate.
|
633
|
+
@pirate.public_send(association_setter, ActiveSupport::HashWithIndifferentAccess.new("foo" => ActiveSupport::HashWithIndifferentAccess.new(id: @child_1.id, name: "Grace OMalley")))
|
622
634
|
@pirate.save
|
623
|
-
assert_equal
|
635
|
+
assert_equal "Grace OMalley", @child_1.reload.name
|
624
636
|
end
|
625
637
|
|
626
638
|
def test_should_take_a_hash_and_assign_the_attributes_to_the_associated_models
|
627
639
|
@pirate.attributes = @alternate_params
|
628
|
-
assert_equal
|
629
|
-
assert_equal
|
640
|
+
assert_equal "Grace OMalley", @pirate.public_send(@association_name).first.name
|
641
|
+
assert_equal "Privateers Greed", @pirate.public_send(@association_name).last.name
|
630
642
|
end
|
631
643
|
|
632
644
|
def test_should_not_load_association_when_updating_existing_records
|
633
645
|
@pirate.reload
|
634
|
-
@pirate.
|
635
|
-
|
646
|
+
@pirate.public_send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
|
647
|
+
assert_not_predicate @pirate.public_send(@association_name), :loaded?
|
636
648
|
|
637
649
|
@pirate.save
|
638
|
-
|
639
|
-
assert_equal
|
650
|
+
assert_not_predicate @pirate.public_send(@association_name), :loaded?
|
651
|
+
assert_equal "Grace OMalley", @child_1.reload.name
|
640
652
|
end
|
641
653
|
|
642
654
|
def test_should_not_overwrite_unsaved_updates_when_loading_association
|
643
655
|
@pirate.reload
|
644
|
-
@pirate.
|
645
|
-
assert_equal
|
656
|
+
@pirate.public_send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
|
657
|
+
assert_equal "Grace OMalley", @pirate.public_send(@association_name).load_target.find { |r| r.id == @child_1.id }.name
|
646
658
|
end
|
647
659
|
|
648
660
|
def test_should_preserve_order_when_not_overwriting_unsaved_updates
|
649
661
|
@pirate.reload
|
650
|
-
@pirate.
|
651
|
-
assert_equal @child_1.id, @pirate.
|
662
|
+
@pirate.public_send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
|
663
|
+
assert_equal @child_1.id, @pirate.public_send(@association_name).load_target.first.id
|
652
664
|
end
|
653
665
|
|
654
666
|
def test_should_refresh_saved_records_when_not_overwriting_unsaved_updates
|
655
667
|
@pirate.reload
|
656
|
-
record = @pirate.class.reflect_on_association(@association_name).klass.new(name:
|
657
|
-
@pirate.
|
668
|
+
record = @pirate.class.reflect_on_association(@association_name).klass.new(name: "Grace OMalley")
|
669
|
+
@pirate.public_send(@association_name) << record
|
658
670
|
record.save!
|
659
|
-
@pirate.
|
660
|
-
assert_equal
|
671
|
+
@pirate.public_send(@association_name).last.update!(name: "Polly")
|
672
|
+
assert_equal "Polly", @pirate.public_send(@association_name).load_target.last.name
|
661
673
|
end
|
662
674
|
|
663
675
|
def test_should_not_remove_scheduled_destroys_when_loading_association
|
664
676
|
@pirate.reload
|
665
|
-
@pirate.
|
666
|
-
|
677
|
+
@pirate.public_send(association_setter, [{ id: @child_1.id, _destroy: "1" }])
|
678
|
+
assert_predicate @pirate.public_send(@association_name).load_target.find { |r| r.id == @child_1.id }, :marked_for_destruction?
|
667
679
|
end
|
668
680
|
|
669
681
|
def test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models
|
670
|
-
@child_1.stub(:id,
|
671
|
-
@child_2.stub(:id,
|
672
|
-
|
682
|
+
@child_1.stub(:id, "ABC1X") do
|
683
|
+
@child_2.stub(:id, "ABC2X") do
|
673
684
|
@pirate.attributes = {
|
674
685
|
association_getter => [
|
675
|
-
{ :
|
676
|
-
{ :
|
686
|
+
{ id: @child_1.id, name: "Grace OMalley" },
|
687
|
+
{ id: @child_2.id, name: "Privateers Greed" }
|
677
688
|
]
|
678
689
|
}
|
679
690
|
|
680
|
-
assert_equal [
|
691
|
+
assert_equal ["Grace OMalley", "Privateers Greed"], [@child_1.name, @child_2.name]
|
681
692
|
end
|
682
693
|
end
|
683
694
|
end
|
684
695
|
|
685
696
|
def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
|
686
697
|
exception = assert_raise ActiveRecord::RecordNotFound do
|
687
|
-
@pirate.attributes = { association_getter => [{ :
|
698
|
+
@pirate.attributes = { association_getter => [{ id: 1234567890 }] }
|
688
699
|
end
|
689
700
|
assert_equal "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}", exception.message
|
690
701
|
end
|
691
702
|
|
692
703
|
def test_should_raise_RecordNotFound_if_an_id_belonging_to_a_different_record_is_given
|
693
|
-
other_pirate = Pirate.create! catchphrase:
|
694
|
-
other_child = other_pirate.
|
704
|
+
other_pirate = Pirate.create! catchphrase: "Ahoy!"
|
705
|
+
other_child = other_pirate.public_send(@association_name).create! name: "Buccaneers Servant"
|
695
706
|
|
696
707
|
exception = assert_raise ActiveRecord::RecordNotFound do
|
697
708
|
@pirate.attributes = { association_getter => [{ id: other_child.id }] }
|
@@ -700,105 +711,105 @@ module NestedAttributesOnACollectionAssociationTests
|
|
700
711
|
end
|
701
712
|
|
702
713
|
def test_should_automatically_build_new_associated_models_for_each_entry_in_a_hash_where_the_id_is_missing
|
703
|
-
@pirate.
|
714
|
+
@pirate.public_send(@association_name).destroy_all
|
704
715
|
@pirate.reload.attributes = {
|
705
|
-
association_getter => {
|
716
|
+
association_getter => { "foo" => { name: "Grace OMalley" }, "bar" => { name: "Privateers Greed" } }
|
706
717
|
}
|
707
718
|
|
708
|
-
|
709
|
-
assert_equal
|
719
|
+
assert_not_predicate @pirate.public_send(@association_name).first, :persisted?
|
720
|
+
assert_equal "Grace OMalley", @pirate.public_send(@association_name).first.name
|
710
721
|
|
711
|
-
|
712
|
-
assert_equal
|
722
|
+
assert_not_predicate @pirate.public_send(@association_name).last, :persisted?
|
723
|
+
assert_equal "Privateers Greed", @pirate.public_send(@association_name).last.name
|
713
724
|
end
|
714
725
|
|
715
726
|
def test_should_not_assign_destroy_key_to_a_record
|
716
727
|
assert_nothing_raised do
|
717
|
-
@pirate.
|
728
|
+
@pirate.public_send(association_setter, "foo" => { "_destroy" => "0" })
|
718
729
|
end
|
719
730
|
end
|
720
731
|
|
721
732
|
def test_should_ignore_new_associated_records_with_truthy_destroy_attribute
|
722
|
-
@pirate.
|
733
|
+
@pirate.public_send(@association_name).destroy_all
|
723
734
|
@pirate.reload.attributes = {
|
724
735
|
association_getter => {
|
725
|
-
|
726
|
-
|
736
|
+
"foo" => { name: "Grace OMalley" },
|
737
|
+
"bar" => { :name => "Privateers Greed", "_destroy" => "1" }
|
727
738
|
}
|
728
739
|
}
|
729
740
|
|
730
|
-
assert_equal 1, @pirate.
|
731
|
-
assert_equal
|
741
|
+
assert_equal 1, @pirate.public_send(@association_name).length
|
742
|
+
assert_equal "Grace OMalley", @pirate.public_send(@association_name).first.name
|
732
743
|
end
|
733
744
|
|
734
745
|
def test_should_ignore_new_associated_records_if_a_reject_if_proc_returns_false
|
735
|
-
@alternate_params[association_getter][
|
736
|
-
assert_no_difference("@pirate.
|
746
|
+
@alternate_params[association_getter]["baz"] = {}
|
747
|
+
assert_no_difference("@pirate.public_send(@association_name).count") do
|
737
748
|
@pirate.attributes = @alternate_params
|
738
749
|
end
|
739
750
|
end
|
740
751
|
|
741
752
|
def test_should_sort_the_hash_by_the_keys_before_building_new_associated_models
|
742
753
|
attributes = {}
|
743
|
-
attributes[
|
744
|
-
attributes[
|
745
|
-
@pirate.
|
754
|
+
attributes["123726353"] = { name: "Grace OMalley" }
|
755
|
+
attributes["2"] = { name: "Privateers Greed" } # 2 is lower then 123726353
|
756
|
+
@pirate.public_send(association_setter, attributes)
|
746
757
|
|
747
|
-
assert_equal [
|
758
|
+
assert_equal ["Posideons Killer", "Killer bandita Dionne", "Privateers Greed", "Grace OMalley"].to_set, @pirate.public_send(@association_name).map(&:name).to_set
|
748
759
|
end
|
749
760
|
|
750
761
|
def test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed
|
751
|
-
assert_nothing_raised { @pirate.
|
752
|
-
assert_nothing_raised { @pirate.
|
762
|
+
assert_nothing_raised { @pirate.public_send(association_setter, {}) }
|
763
|
+
assert_nothing_raised { @pirate.public_send(association_setter, Hash.new) }
|
753
764
|
|
754
765
|
exception = assert_raise ArgumentError do
|
755
|
-
@pirate.
|
766
|
+
@pirate.public_send(association_setter, "foo")
|
756
767
|
end
|
757
|
-
assert_equal
|
768
|
+
assert_equal %{Hash or Array expected for attribute `#{@association_name}`, got String ("foo")}, exception.message
|
758
769
|
end
|
759
770
|
|
760
771
|
def test_should_work_with_update_as_well
|
761
|
-
@pirate.update(catchphrase:
|
762
|
-
association_getter => {
|
772
|
+
@pirate.update(catchphrase: "Arr",
|
773
|
+
association_getter => { "foo" => { id: @child_1.id, name: "Grace OMalley" } })
|
763
774
|
|
764
|
-
assert_equal
|
775
|
+
assert_equal "Grace OMalley", @child_1.reload.name
|
765
776
|
end
|
766
777
|
|
767
778
|
def test_should_update_existing_records_and_add_new_ones_that_have_no_id
|
768
|
-
@alternate_params[association_getter][
|
769
|
-
assert_difference(
|
779
|
+
@alternate_params[association_getter]["baz"] = { name: "Buccaneers Servant" }
|
780
|
+
assert_difference("@pirate.public_send(@association_name).count", +1) do
|
770
781
|
@pirate.update @alternate_params
|
771
782
|
end
|
772
|
-
assert_equal [
|
783
|
+
assert_equal ["Grace OMalley", "Privateers Greed", "Buccaneers Servant"].to_set, @pirate.reload.public_send(@association_name).map(&:name).to_set
|
773
784
|
end
|
774
785
|
|
775
786
|
def test_should_be_possible_to_destroy_a_record
|
776
|
-
[
|
777
|
-
record = @pirate.reload.
|
778
|
-
@pirate.
|
779
|
-
@alternate_params[association_getter].merge(
|
787
|
+
["1", 1, "true", true].each do |true_variable|
|
788
|
+
record = @pirate.reload.public_send(@association_name).create!(name: "Grace OMalley")
|
789
|
+
@pirate.public_send(association_setter,
|
790
|
+
@alternate_params[association_getter].merge("baz" => { :id => record.id, "_destroy" => true_variable })
|
780
791
|
)
|
781
792
|
|
782
|
-
assert_difference(
|
793
|
+
assert_difference("@pirate.public_send(@association_name).count", -1) do
|
783
794
|
@pirate.save
|
784
795
|
end
|
785
796
|
end
|
786
797
|
end
|
787
798
|
|
788
799
|
def test_should_not_destroy_the_associated_model_with_a_non_truthy_argument
|
789
|
-
[nil,
|
790
|
-
@alternate_params[association_getter][
|
791
|
-
assert_no_difference(
|
800
|
+
[nil, "", "0", 0, "false", false].each do |false_variable|
|
801
|
+
@alternate_params[association_getter]["foo"]["_destroy"] = false_variable
|
802
|
+
assert_no_difference("@pirate.public_send(@association_name).count") do
|
792
803
|
@pirate.update(@alternate_params)
|
793
804
|
end
|
794
805
|
end
|
795
806
|
end
|
796
807
|
|
797
808
|
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
|
798
|
-
assert_no_difference(
|
799
|
-
@pirate.
|
809
|
+
assert_no_difference("@pirate.public_send(@association_name).count") do
|
810
|
+
@pirate.public_send(association_setter, @alternate_params[association_getter].merge("baz" => { :id => @child_1.id, "_destroy" => true }))
|
800
811
|
end
|
801
|
-
assert_difference(
|
812
|
+
assert_difference("@pirate.public_send(@association_name).count", -1) { @pirate.save }
|
802
813
|
end
|
803
814
|
|
804
815
|
def test_should_automatically_enable_autosave_on_the_association
|
@@ -806,48 +817,47 @@ module NestedAttributesOnACollectionAssociationTests
|
|
806
817
|
end
|
807
818
|
|
808
819
|
def test_validate_presence_of_parent_works_with_inverse_of
|
809
|
-
|
810
|
-
assert_equal :
|
811
|
-
assert_equal :interests, Interest.reflect_on_association(:
|
820
|
+
Human.accepts_nested_attributes_for(:interests)
|
821
|
+
assert_equal :human, Human.reflect_on_association(:interests).options[:inverse_of]
|
822
|
+
assert_equal :interests, Interest.reflect_on_association(:human).options[:inverse_of]
|
812
823
|
|
813
824
|
repair_validations(Interest) do
|
814
|
-
Interest.validates_presence_of(:
|
815
|
-
assert_difference
|
816
|
-
assert_difference
|
817
|
-
|
818
|
-
:
|
819
|
-
assert_equal 2,
|
825
|
+
Interest.validates_presence_of(:human)
|
826
|
+
assert_difference "Human.count" do
|
827
|
+
assert_difference "Interest.count", 2 do
|
828
|
+
human = Human.create!(name: "John",
|
829
|
+
interests_attributes: [{ topic: "Cars" }, { topic: "Sports" }])
|
830
|
+
assert_equal 2, human.interests.count
|
820
831
|
end
|
821
832
|
end
|
822
833
|
end
|
823
834
|
end
|
824
835
|
|
825
836
|
def test_can_use_symbols_as_object_identifier
|
826
|
-
@pirate.attributes = { :
|
837
|
+
@pirate.attributes = { parrots_attributes: { foo: { name: "Lovely Day" }, bar: { name: "Blown Away" } } }
|
827
838
|
assert_nothing_raised { @pirate.save! }
|
828
839
|
end
|
829
840
|
|
830
841
|
def test_numeric_column_changes_from_zero_to_no_empty_string
|
831
|
-
|
842
|
+
Human.accepts_nested_attributes_for(:interests)
|
832
843
|
|
833
844
|
repair_validations(Interest) do
|
834
845
|
Interest.validates_numericality_of(:zine_id)
|
835
|
-
|
836
|
-
interest =
|
846
|
+
human = Human.create(name: "John")
|
847
|
+
interest = human.interests.create(topic: "bar", zine_id: 0)
|
837
848
|
assert interest.save
|
838
|
-
|
849
|
+
assert_not human.update(interests_attributes: { id: interest.id, zine_id: "foo" })
|
839
850
|
end
|
840
851
|
end
|
841
852
|
|
842
853
|
private
|
854
|
+
def association_setter
|
855
|
+
@association_setter ||= "#{@association_name}_attributes=".to_sym
|
856
|
+
end
|
843
857
|
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
def association_getter
|
849
|
-
@association_getter ||= "#{@association_name}_attributes".to_sym
|
850
|
-
end
|
858
|
+
def association_getter
|
859
|
+
@association_getter ||= "#{@association_name}_attributes".to_sym
|
860
|
+
end
|
851
861
|
end
|
852
862
|
|
853
863
|
class TestNestedAttributesOnAHasManyAssociation < ActiveRecord::TestCase
|
@@ -855,16 +865,16 @@ class TestNestedAttributesOnAHasManyAssociation < ActiveRecord::TestCase
|
|
855
865
|
@association_type = :has_many
|
856
866
|
@association_name = :birds
|
857
867
|
|
858
|
-
@pirate = Pirate.create!(:
|
859
|
-
@pirate.birds.create!(:
|
860
|
-
@pirate.birds.create!(:
|
868
|
+
@pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
869
|
+
@pirate.birds.create!(name: "Posideons Killer")
|
870
|
+
@pirate.birds.create!(name: "Killer bandita Dionne")
|
861
871
|
|
862
872
|
@child_1, @child_2 = @pirate.birds
|
863
873
|
|
864
874
|
@alternate_params = {
|
865
|
-
:
|
866
|
-
|
867
|
-
|
875
|
+
birds_attributes: {
|
876
|
+
"foo" => { id: @child_1.id, name: "Grace OMalley" },
|
877
|
+
"bar" => { id: @child_2.id, name: "Privateers Greed" }
|
868
878
|
}
|
869
879
|
}
|
870
880
|
end
|
@@ -877,16 +887,16 @@ class TestNestedAttributesOnAHasAndBelongsToManyAssociation < ActiveRecord::Test
|
|
877
887
|
@association_type = :has_and_belongs_to_many
|
878
888
|
@association_name = :parrots
|
879
889
|
|
880
|
-
@pirate = Pirate.create!(:
|
881
|
-
@pirate.parrots.create!(:
|
882
|
-
@pirate.parrots.create!(:
|
890
|
+
@pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
891
|
+
@pirate.parrots.create!(name: "Posideons Killer")
|
892
|
+
@pirate.parrots.create!(name: "Killer bandita Dionne")
|
883
893
|
|
884
894
|
@child_1, @child_2 = @pirate.parrots
|
885
895
|
|
886
896
|
@alternate_params = {
|
887
|
-
:
|
888
|
-
|
889
|
-
|
897
|
+
parrots_attributes: {
|
898
|
+
"foo" => { id: @child_1.id, name: "Grace OMalley" },
|
899
|
+
"bar" => { id: @child_2.id, name: "Privateers Greed" }
|
890
900
|
}
|
891
901
|
}
|
892
902
|
end
|
@@ -896,33 +906,33 @@ end
|
|
896
906
|
|
897
907
|
module NestedAttributesLimitTests
|
898
908
|
def teardown
|
899
|
-
Pirate.accepts_nested_attributes_for :parrots, :
|
909
|
+
Pirate.accepts_nested_attributes_for :parrots, allow_destroy: true, reject_if: proc(&:empty?)
|
900
910
|
end
|
901
911
|
|
902
912
|
def test_limit_with_less_records
|
903
|
-
@pirate.attributes = { :
|
904
|
-
assert_difference(
|
913
|
+
@pirate.attributes = { parrots_attributes: { "foo" => { name: "Big Big Love" } } }
|
914
|
+
assert_difference("Parrot.count") { @pirate.save! }
|
905
915
|
end
|
906
916
|
|
907
917
|
def test_limit_with_number_exact_records
|
908
|
-
@pirate.attributes = { :
|
909
|
-
assert_difference(
|
918
|
+
@pirate.attributes = { parrots_attributes: { "foo" => { name: "Lovely Day" }, "bar" => { name: "Blown Away" } } }
|
919
|
+
assert_difference("Parrot.count", 2) { @pirate.save! }
|
910
920
|
end
|
911
921
|
|
912
922
|
def test_limit_with_exceeding_records
|
913
923
|
assert_raises(ActiveRecord::NestedAttributes::TooManyRecords) do
|
914
|
-
@pirate.attributes = { :
|
915
|
-
|
916
|
-
|
924
|
+
@pirate.attributes = { parrots_attributes: { "foo" => { name: "Lovely Day" },
|
925
|
+
"bar" => { name: "Blown Away" },
|
926
|
+
"car" => { name: "The Happening" } } }
|
917
927
|
end
|
918
928
|
end
|
919
929
|
end
|
920
930
|
|
921
931
|
class TestNestedAttributesLimitNumeric < ActiveRecord::TestCase
|
922
932
|
def setup
|
923
|
-
Pirate.accepts_nested_attributes_for :parrots, :
|
933
|
+
Pirate.accepts_nested_attributes_for :parrots, limit: 2
|
924
934
|
|
925
|
-
@pirate = Pirate.create!(:
|
935
|
+
@pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
926
936
|
end
|
927
937
|
|
928
938
|
include NestedAttributesLimitTests
|
@@ -930,9 +940,9 @@ end
|
|
930
940
|
|
931
941
|
class TestNestedAttributesLimitSymbol < ActiveRecord::TestCase
|
932
942
|
def setup
|
933
|
-
Pirate.accepts_nested_attributes_for :parrots, :
|
943
|
+
Pirate.accepts_nested_attributes_for :parrots, limit: :parrots_limit
|
934
944
|
|
935
|
-
@pirate = Pirate.create!(:
|
945
|
+
@pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?", parrots_limit: 2)
|
936
946
|
end
|
937
947
|
|
938
948
|
include NestedAttributesLimitTests
|
@@ -940,9 +950,9 @@ end
|
|
940
950
|
|
941
951
|
class TestNestedAttributesLimitProc < ActiveRecord::TestCase
|
942
952
|
def setup
|
943
|
-
Pirate.accepts_nested_attributes_for :parrots, :
|
953
|
+
Pirate.accepts_nested_attributes_for :parrots, limit: proc { 2 }
|
944
954
|
|
945
|
-
@pirate = Pirate.create!(:
|
955
|
+
@pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
946
956
|
end
|
947
957
|
|
948
958
|
include NestedAttributesLimitTests
|
@@ -952,45 +962,44 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase
|
|
952
962
|
fixtures :owners, :pets
|
953
963
|
|
954
964
|
def setup
|
955
|
-
Owner.accepts_nested_attributes_for :pets, :
|
965
|
+
Owner.accepts_nested_attributes_for :pets, allow_destroy: true
|
956
966
|
|
957
967
|
@owner = owners(:ashley)
|
958
968
|
@pet1, @pet2 = pets(:chew), pets(:mochi)
|
959
969
|
|
960
970
|
@params = {
|
961
|
-
:
|
962
|
-
|
963
|
-
|
971
|
+
pets_attributes: {
|
972
|
+
"0" => { id: @pet1.id, name: "Foo" },
|
973
|
+
"1" => { id: @pet2.id, name: "Bar" }
|
964
974
|
}
|
965
975
|
}
|
966
976
|
end
|
967
977
|
|
968
978
|
def test_should_update_existing_records_with_non_standard_primary_key
|
969
979
|
@owner.update(@params)
|
970
|
-
assert_equal [
|
980
|
+
assert_equal ["Foo", "Bar"], @owner.pets.map(&:name)
|
971
981
|
end
|
972
982
|
|
973
983
|
def test_attr_accessor_of_child_should_be_value_provided_during_update
|
974
984
|
@owner = owners(:ashley)
|
975
985
|
@pet1 = pets(:chew)
|
976
|
-
attributes = {:
|
977
|
-
:
|
978
|
-
:
|
979
|
-
:
|
986
|
+
attributes = { pets_attributes: { "1" => { id: @pet1.id,
|
987
|
+
name: "Foo2",
|
988
|
+
current_user: "John",
|
989
|
+
_destroy: true } } }
|
980
990
|
@owner.update(attributes)
|
981
|
-
assert_equal
|
991
|
+
assert_equal "John", Pet.after_destroy_output
|
982
992
|
end
|
983
|
-
|
984
993
|
end
|
985
994
|
|
986
995
|
class TestHasOneAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveRecord::TestCase
|
987
996
|
self.use_transactional_tests = false unless supports_savepoints?
|
988
997
|
|
989
998
|
def setup
|
990
|
-
@pirate = Pirate.create!(:
|
991
|
-
@ship = @pirate.create_ship(:
|
992
|
-
@part = @ship.parts.create!(:
|
993
|
-
@trinket = @part.trinkets.create!(:
|
999
|
+
@pirate = Pirate.create!(catchphrase: "My baby takes tha mornin' train!")
|
1000
|
+
@ship = @pirate.create_ship(name: "The good ship Dollypop")
|
1001
|
+
@part = @ship.parts.create!(name: "Mast")
|
1002
|
+
@trinket = @part.trinkets.create!(name: "Necklace")
|
994
1003
|
end
|
995
1004
|
|
996
1005
|
test "when great-grandchild changed in memory, saving parent should save great-grandchild" do
|
@@ -1000,25 +1009,25 @@ class TestHasOneAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveRe
|
|
1000
1009
|
end
|
1001
1010
|
|
1002
1011
|
test "when great-grandchild changed via attributes, saving parent should save great-grandchild" do
|
1003
|
-
@pirate.attributes = {:
|
1012
|
+
@pirate.attributes = { ship_attributes: { id: @ship.id, parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "changed" }] }] } }
|
1004
1013
|
@pirate.save
|
1005
1014
|
assert_equal "changed", @trinket.reload.name
|
1006
1015
|
end
|
1007
1016
|
|
1008
1017
|
test "when great-grandchild marked_for_destruction via attributes, saving parent should destroy great-grandchild" do
|
1009
|
-
@pirate.attributes = {:
|
1010
|
-
assert_difference(
|
1018
|
+
@pirate.attributes = { ship_attributes: { id: @ship.id, parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, _destroy: true }] }] } }
|
1019
|
+
assert_difference("@part.trinkets.count", -1) { @pirate.save }
|
1011
1020
|
end
|
1012
1021
|
|
1013
1022
|
test "when great-grandchild added via attributes, saving parent should create great-grandchild" do
|
1014
|
-
@pirate.attributes = {:
|
1015
|
-
assert_difference(
|
1023
|
+
@pirate.attributes = { ship_attributes: { id: @ship.id, parts_attributes: [{ id: @part.id, trinkets_attributes: [{ name: "created" }] }] } }
|
1024
|
+
assert_difference("@part.trinkets.count", 1) { @pirate.save }
|
1016
1025
|
end
|
1017
1026
|
|
1018
1027
|
test "when extra records exist for associations, validate (which calls nested_records_changed_for_autosave?) should not load them up" do
|
1019
1028
|
@trinket.name = "changed"
|
1020
|
-
Ship.create!(:
|
1021
|
-
ShipPart.create!(:
|
1029
|
+
Ship.create!(pirate: @pirate, name: "The Black Rock")
|
1030
|
+
ShipPart.create!(ship: @ship, name: "Stern")
|
1022
1031
|
assert_no_queries { @pirate.valid? }
|
1023
1032
|
end
|
1024
1033
|
end
|
@@ -1027,27 +1036,27 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR
|
|
1027
1036
|
self.use_transactional_tests = false unless supports_savepoints?
|
1028
1037
|
|
1029
1038
|
def setup
|
1030
|
-
@ship = Ship.create!(:
|
1031
|
-
@part = @ship.parts.create!(:
|
1032
|
-
@trinket = @part.trinkets.create!(:
|
1039
|
+
@ship = Ship.create!(name: "The good ship Dollypop")
|
1040
|
+
@part = @ship.parts.create!(name: "Mast")
|
1041
|
+
@trinket = @part.trinkets.create!(name: "Necklace")
|
1033
1042
|
end
|
1034
1043
|
|
1035
1044
|
test "if association is not loaded and association record is saved and then in memory record attributes should be saved" do
|
1036
|
-
@ship.parts_attributes=[{:
|
1045
|
+
@ship.parts_attributes = [{ id: @part.id, name: "Deck" }]
|
1037
1046
|
assert_equal 1, @ship.association(:parts).target.size
|
1038
|
-
assert_equal
|
1047
|
+
assert_equal "Deck", @ship.parts[0].name
|
1039
1048
|
end
|
1040
1049
|
|
1041
1050
|
test "if association is not loaded and child doesn't change and I am saving a grandchild then in memory record should be used" do
|
1042
|
-
@ship.parts_attributes=[{:
|
1051
|
+
@ship.parts_attributes = [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "Ruby" }] }]
|
1043
1052
|
assert_equal 1, @ship.association(:parts).target.size
|
1044
|
-
assert_equal
|
1053
|
+
assert_equal "Mast", @ship.parts[0].name
|
1045
1054
|
assert_no_difference("@ship.parts[0].association(:trinkets).target.size") do
|
1046
1055
|
@ship.parts[0].association(:trinkets).target.size
|
1047
1056
|
end
|
1048
|
-
assert_equal
|
1057
|
+
assert_equal "Ruby", @ship.parts[0].trinkets[0].name
|
1049
1058
|
@ship.save
|
1050
|
-
assert_equal
|
1059
|
+
assert_equal "Ruby", @ship.parts[0].trinkets[0].name
|
1051
1060
|
end
|
1052
1061
|
|
1053
1062
|
test "when grandchild changed in memory, saving parent should save grandchild" do
|
@@ -1057,25 +1066,25 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR
|
|
1057
1066
|
end
|
1058
1067
|
|
1059
1068
|
test "when grandchild changed via attributes, saving parent should save grandchild" do
|
1060
|
-
@ship.attributes = {:
|
1069
|
+
@ship.attributes = { parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "changed" }] }] }
|
1061
1070
|
@ship.save
|
1062
1071
|
assert_equal "changed", @trinket.reload.name
|
1063
1072
|
end
|
1064
1073
|
|
1065
1074
|
test "when grandchild marked_for_destruction via attributes, saving parent should destroy grandchild" do
|
1066
|
-
@ship.attributes = {:
|
1067
|
-
assert_difference(
|
1075
|
+
@ship.attributes = { parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, _destroy: true }] }] }
|
1076
|
+
assert_difference("@part.trinkets.count", -1) { @ship.save }
|
1068
1077
|
end
|
1069
1078
|
|
1070
1079
|
test "when grandchild added via attributes, saving parent should create grandchild" do
|
1071
|
-
@ship.attributes = {:
|
1072
|
-
assert_difference(
|
1080
|
+
@ship.attributes = { parts_attributes: [{ id: @part.id, trinkets_attributes: [{ name: "created" }] }] }
|
1081
|
+
assert_difference("@part.trinkets.count", 1) { @ship.save }
|
1073
1082
|
end
|
1074
1083
|
|
1075
1084
|
test "when extra records exist for associations, validate (which calls nested_records_changed_for_autosave?) should not load them up" do
|
1076
1085
|
@trinket.name = "changed"
|
1077
|
-
Ship.create!(:
|
1078
|
-
ShipPart.create!(:
|
1086
|
+
Ship.create!(name: "The Black Rock")
|
1087
|
+
ShipPart.create!(ship: @ship, name: "Stern")
|
1079
1088
|
assert_no_queries { @ship.valid? }
|
1080
1089
|
end
|
1081
1090
|
|
@@ -1092,7 +1101,19 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR
|
|
1092
1101
|
test "nested singular associations are validated" do
|
1093
1102
|
part = ShipPart.new(name: "Stern", ship_attributes: { name: nil })
|
1094
1103
|
|
1095
|
-
|
1104
|
+
assert_not_predicate part, :valid?
|
1096
1105
|
assert_equal ["Ship name can't be blank"], part.errors.full_messages
|
1097
1106
|
end
|
1098
1107
|
end
|
1108
|
+
|
1109
|
+
class TestNestedAttributesWithExtend < ActiveRecord::TestCase
|
1110
|
+
setup do
|
1111
|
+
Pirate.accepts_nested_attributes_for :treasures
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
def test_extend_affects_nested_attributes
|
1115
|
+
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
|
1116
|
+
pirate.treasures_attributes = [{ id: nil }]
|
1117
|
+
assert_equal "from extension", pirate.treasures[0].name
|
1118
|
+
end
|
1119
|
+
end
|