ibm_db 5.2.0-x86-mingw32 → 5.4.0-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.
Files changed (625) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/README +1 -1
  5. data/debug.log +1 -0
  6. data/ext/Makefile +28 -24
  7. data/ext/ibm_db.c +66 -65
  8. data/ext/ibm_db.o +0 -0
  9. data/ext/ibm_db.so +0 -0
  10. data/ext/mkmf.log +26 -24
  11. data/ext/ruby_ibm_db_cli.c +1 -0
  12. data/ext/ruby_ibm_db_cli.o +0 -0
  13. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1520 -1282
  14. data/lib/ibm_db.so +1 -0
  15. data/lib/mswin32/ibm_db.rb +3 -1
  16. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  17. data/lib/mswin32/rb3x/i386/ruby31/ibm_db.so +0 -0
  18. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  19. data/test/activejob/destroy_association_async_test.rb +305 -0
  20. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  21. data/test/activejob/helper.rb +15 -0
  22. data/test/assets/schema_dump_5_1.yml +345 -0
  23. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  24. data/test/cases/adapter_test.rb +432 -218
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  26. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  28. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  31. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  32. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  33. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  34. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  35. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  36. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  37. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  38. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  39. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  40. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  41. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  42. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  43. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  44. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  45. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  46. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  47. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  48. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  49. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  50. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  51. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  52. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  53. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  54. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  55. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  56. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  57. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  58. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  59. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  60. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  61. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  62. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  63. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  64. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  65. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  66. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  67. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  68. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  69. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  70. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  71. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  72. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  73. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  74. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  75. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  76. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  77. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  78. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  79. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  80. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  81. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  82. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  83. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  84. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  85. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  86. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  87. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  88. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  89. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  90. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  91. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  92. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  93. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  94. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  95. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  96. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  97. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  98. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  99. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  100. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  101. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  102. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  103. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  104. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  105. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  106. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  107. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  108. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  109. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  110. data/test/cases/aggregations_test.rb +14 -12
  111. data/test/cases/annotate_test.rb +46 -0
  112. data/test/cases/ar_schema_test.rb +153 -86
  113. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  114. data/test/cases/arel/attributes/math_test.rb +83 -0
  115. data/test/cases/arel/attributes_test.rb +27 -0
  116. data/test/cases/arel/collectors/bind_test.rb +40 -0
  117. data/test/cases/arel/collectors/composite_test.rb +47 -0
  118. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  119. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  120. data/test/cases/arel/crud_test.rb +65 -0
  121. data/test/cases/arel/delete_manager_test.rb +53 -0
  122. data/test/cases/arel/factory_methods_test.rb +46 -0
  123. data/test/cases/arel/helper.rb +45 -0
  124. data/test/cases/arel/insert_manager_test.rb +241 -0
  125. data/test/cases/arel/nodes/and_test.rb +30 -0
  126. data/test/cases/arel/nodes/as_test.rb +36 -0
  127. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  128. data/test/cases/arel/nodes/bin_test.rb +35 -0
  129. data/test/cases/arel/nodes/binary_test.rb +29 -0
  130. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  131. data/test/cases/arel/nodes/case_test.rb +96 -0
  132. data/test/cases/arel/nodes/casted_test.rb +18 -0
  133. data/test/cases/arel/nodes/comment_test.rb +22 -0
  134. data/test/cases/arel/nodes/count_test.rb +35 -0
  135. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  136. data/test/cases/arel/nodes/descending_test.rb +46 -0
  137. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  138. data/test/cases/arel/nodes/equality_test.rb +62 -0
  139. data/test/cases/arel/nodes/extract_test.rb +43 -0
  140. data/test/cases/arel/nodes/false_test.rb +21 -0
  141. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  142. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  143. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  144. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  145. data/test/cases/arel/nodes/node_test.rb +22 -0
  146. data/test/cases/arel/nodes/not_test.rb +31 -0
  147. data/test/cases/arel/nodes/or_test.rb +36 -0
  148. data/test/cases/arel/nodes/over_test.rb +69 -0
  149. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  150. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  151. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  152. data/test/cases/arel/nodes/sum_test.rb +35 -0
  153. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  154. data/test/cases/arel/nodes/true_test.rb +21 -0
  155. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  156. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  157. data/test/cases/arel/nodes/window_test.rb +81 -0
  158. data/test/cases/arel/nodes_test.rb +34 -0
  159. data/test/cases/arel/select_manager_test.rb +1238 -0
  160. data/test/cases/arel/support/fake_record.rb +135 -0
  161. data/test/cases/arel/table_test.rb +216 -0
  162. data/test/cases/arel/update_manager_test.rb +126 -0
  163. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  164. data/test/cases/arel/visitors/dot_test.rb +90 -0
  165. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  166. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  167. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  168. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  169. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  170. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  171. data/test/cases/associations/callbacks_test.rb +56 -38
  172. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  173. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  174. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  175. data/test/cases/associations/eager_singularization_test.rb +21 -21
  176. data/test/cases/associations/eager_test.rb +559 -415
  177. data/test/cases/associations/extension_test.rb +18 -12
  178. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  179. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  180. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  181. data/test/cases/associations/has_one_associations_test.rb +294 -129
  182. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  183. data/test/cases/associations/inner_join_association_test.rb +114 -38
  184. data/test/cases/associations/inverse_associations_test.rb +606 -398
  185. data/test/cases/associations/join_model_test.rb +158 -148
  186. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  187. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  188. data/test/cases/associations/required_test.rb +35 -10
  189. data/test/cases/associations_test.rb +241 -110
  190. data/test/cases/attribute_methods/read_test.rb +11 -11
  191. data/test/cases/attribute_methods_test.rb +413 -298
  192. data/test/cases/attributes_test.rb +145 -27
  193. data/test/cases/autosave_association_test.rb +681 -436
  194. data/test/cases/base_prevent_writes_test.rb +229 -0
  195. data/test/cases/base_test.rb +599 -542
  196. data/test/cases/batches_test.rb +288 -82
  197. data/test/cases/binary_test.rb +26 -31
  198. data/test/cases/bind_parameter_test.rb +194 -21
  199. data/test/cases/boolean_test.rb +52 -0
  200. data/test/cases/cache_key_test.rb +110 -5
  201. data/test/cases/calculations_test.rb +740 -177
  202. data/test/cases/callbacks_test.rb +74 -207
  203. data/test/cases/clone_test.rb +15 -10
  204. data/test/cases/coders/json_test.rb +2 -0
  205. data/test/cases/coders/yaml_column_test.rb +16 -13
  206. data/test/cases/collection_cache_key_test.rb +177 -20
  207. data/test/cases/column_alias_test.rb +9 -7
  208. data/test/cases/column_definition_test.rb +10 -68
  209. data/test/cases/comment_test.rb +166 -107
  210. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  211. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  212. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  213. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  214. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  215. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  216. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  217. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  218. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  219. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  220. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  221. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  222. data/test/cases/connection_management_test.rb +13 -11
  223. data/test/cases/connection_pool_test.rb +316 -83
  224. data/test/cases/core_test.rb +82 -58
  225. data/test/cases/counter_cache_test.rb +204 -50
  226. data/test/cases/custom_locking_test.rb +5 -3
  227. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  228. data/test/cases/database_configurations/resolver_test.rb +150 -0
  229. data/test/cases/database_configurations_test.rb +145 -0
  230. data/test/cases/database_selector_test.rb +296 -0
  231. data/test/cases/database_statements_test.rb +18 -16
  232. data/test/cases/date_test.rb +8 -16
  233. data/test/cases/date_time_precision_test.rb +100 -78
  234. data/test/cases/date_time_test.rb +23 -8
  235. data/test/cases/defaults_test.rb +106 -71
  236. data/test/cases/delegated_type_test.rb +57 -0
  237. data/test/cases/dirty_test.rb +419 -223
  238. data/test/cases/disconnected_test.rb +6 -6
  239. data/test/cases/dup_test.rb +54 -27
  240. data/test/cases/enum_test.rb +461 -82
  241. data/test/cases/errors_test.rb +7 -7
  242. data/test/cases/explain_subscriber_test.rb +17 -15
  243. data/test/cases/explain_test.rb +11 -19
  244. data/test/cases/filter_attributes_test.rb +153 -0
  245. data/test/cases/finder_respond_to_test.rb +14 -14
  246. data/test/cases/finder_test.rb +669 -287
  247. data/test/cases/fixture_set/file_test.rb +34 -38
  248. data/test/cases/fixtures_test.rb +833 -176
  249. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  250. data/test/cases/habtm_destroy_order_test.rb +25 -25
  251. data/test/cases/helper.rb +78 -49
  252. data/test/cases/hot_compatibility_test.rb +33 -32
  253. data/test/cases/i18n_test.rb +18 -17
  254. data/test/cases/inheritance_test.rb +180 -115
  255. data/test/cases/insert_all_test.rb +489 -0
  256. data/test/cases/instrumentation_test.rb +101 -0
  257. data/test/cases/integration_test.rb +119 -31
  258. data/test/cases/invalid_connection_test.rb +18 -16
  259. data/test/cases/invertible_migration_test.rb +183 -43
  260. data/test/cases/json_attribute_test.rb +35 -0
  261. data/test/cases/json_serialization_test.rb +57 -58
  262. data/test/cases/json_shared_test_cases.rb +290 -0
  263. data/test/cases/locking_test.rb +413 -119
  264. data/test/cases/log_subscriber_test.rb +68 -26
  265. data/test/cases/marshal_serialization_test.rb +39 -0
  266. data/test/cases/migration/change_schema_test.rb +118 -72
  267. data/test/cases/migration/change_table_test.rb +138 -30
  268. data/test/cases/migration/check_constraint_test.rb +162 -0
  269. data/test/cases/migration/column_attributes_test.rb +45 -35
  270. data/test/cases/migration/column_positioning_test.rb +18 -6
  271. data/test/cases/migration/columns_test.rb +93 -77
  272. data/test/cases/migration/command_recorder_test.rb +121 -34
  273. data/test/cases/migration/compatibility_test.rb +578 -23
  274. data/test/cases/migration/create_join_table_test.rb +35 -25
  275. data/test/cases/migration/foreign_key_test.rb +503 -284
  276. data/test/cases/migration/helper.rb +4 -3
  277. data/test/cases/migration/index_test.rb +119 -70
  278. data/test/cases/migration/logger_test.rb +9 -6
  279. data/test/cases/migration/pending_migrations_test.rb +88 -34
  280. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  281. data/test/cases/migration/references_index_test.rb +38 -19
  282. data/test/cases/migration/references_statements_test.rb +15 -14
  283. data/test/cases/migration/rename_table_test.rb +53 -30
  284. data/test/cases/migration_test.rb +637 -269
  285. data/test/cases/migrator_test.rb +191 -135
  286. data/test/cases/mixin_test.rb +7 -11
  287. data/test/cases/modules_test.rb +36 -34
  288. data/test/cases/multi_db_migrator_test.rb +223 -0
  289. data/test/cases/multiparameter_attributes_test.rb +60 -33
  290. data/test/cases/multiple_db_test.rb +16 -22
  291. data/test/cases/nested_attributes_test.rb +341 -320
  292. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  293. data/test/cases/null_relation_test.rb +84 -0
  294. data/test/cases/numeric_data_test.rb +93 -0
  295. data/test/cases/persistence_test.rb +361 -269
  296. data/test/cases/pooled_connections_test.rb +18 -26
  297. data/test/cases/prepared_statement_status_test.rb +48 -0
  298. data/test/cases/primary_keys_test.rb +210 -104
  299. data/test/cases/query_cache_test.rb +610 -141
  300. data/test/cases/quoting_test.rb +132 -31
  301. data/test/cases/readonly_test.rb +49 -48
  302. data/test/cases/reaper_test.rb +146 -32
  303. data/test/cases/reflection_test.rb +167 -156
  304. data/test/cases/relation/delegation_test.rb +49 -36
  305. data/test/cases/relation/delete_all_test.rb +117 -0
  306. data/test/cases/relation/merging_test.rb +319 -42
  307. data/test/cases/relation/mutation_test.rb +55 -93
  308. data/test/cases/relation/or_test.rb +129 -29
  309. data/test/cases/relation/predicate_builder_test.rb +21 -6
  310. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  311. data/test/cases/relation/select_test.rb +67 -0
  312. data/test/cases/relation/update_all_test.rb +317 -0
  313. data/test/cases/relation/where_chain_test.rb +68 -32
  314. data/test/cases/relation/where_clause_test.rb +136 -61
  315. data/test/cases/relation/where_test.rb +155 -48
  316. data/test/cases/relation_test.rb +266 -112
  317. data/test/cases/relations_test.rb +969 -744
  318. data/test/cases/reload_models_test.rb +13 -9
  319. data/test/cases/reserved_word_test.rb +141 -0
  320. data/test/cases/result_test.rb +68 -17
  321. data/test/cases/sanitize_test.rb +87 -71
  322. data/test/cases/schema_dumper_test.rb +221 -128
  323. data/test/cases/schema_loading_test.rb +3 -2
  324. data/test/cases/scoping/default_scoping_test.rb +185 -144
  325. data/test/cases/scoping/named_scoping_test.rb +177 -89
  326. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  327. data/test/cases/secure_token_test.rb +18 -3
  328. data/test/cases/serialization_test.rb +30 -28
  329. data/test/cases/serialized_attribute_test.rb +133 -42
  330. data/test/cases/signed_id_test.rb +168 -0
  331. data/test/cases/statement_cache_test.rb +41 -24
  332. data/test/cases/statement_invalid_test.rb +42 -0
  333. data/test/cases/store_test.rb +180 -55
  334. data/test/cases/strict_loading_test.rb +473 -0
  335. data/test/cases/suppressor_test.rb +26 -12
  336. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  337. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  338. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  339. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  340. data/test/cases/test_case.rb +51 -40
  341. data/test/cases/test_databases_test.rb +79 -0
  342. data/test/cases/test_fixtures_test.rb +79 -19
  343. data/test/cases/time_precision_test.rb +98 -76
  344. data/test/cases/timestamp_test.rb +102 -99
  345. data/test/cases/touch_later_test.rb +12 -10
  346. data/test/cases/transaction_callbacks_test.rb +344 -90
  347. data/test/cases/transaction_isolation_test.rb +12 -12
  348. data/test/cases/transactions_test.rb +612 -162
  349. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  350. data/test/cases/type/date_time_test.rb +4 -2
  351. data/test/cases/type/integer_test.rb +4 -2
  352. data/test/cases/type/string_test.rb +10 -8
  353. data/test/cases/type/time_test.rb +28 -0
  354. data/test/cases/type/type_map_test.rb +29 -28
  355. data/test/cases/type/unsigned_integer_test.rb +19 -0
  356. data/test/cases/type_test.rb +2 -0
  357. data/test/cases/types_test.rb +3 -1
  358. data/test/cases/unconnected_test.rb +14 -1
  359. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  360. data/test/cases/validations/absence_validation_test.rb +19 -17
  361. data/test/cases/validations/association_validation_test.rb +30 -28
  362. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  363. data/test/cases/validations/i18n_validation_test.rb +22 -21
  364. data/test/cases/validations/length_validation_test.rb +34 -33
  365. data/test/cases/validations/numericality_validation_test.rb +181 -0
  366. data/test/cases/validations/presence_validation_test.rb +21 -19
  367. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  368. data/test/cases/validations_repair_helper.rb +2 -0
  369. data/test/cases/validations_test.rb +61 -26
  370. data/test/cases/view_test.rb +122 -116
  371. data/test/cases/yaml_serialization_test.rb +79 -34
  372. data/test/config.example.yml +19 -19
  373. data/test/config.rb +3 -1
  374. data/test/config.yml +16 -6
  375. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  376. data/test/fixtures/author_addresses.yml +1 -8
  377. data/test/fixtures/authors.yml +1 -7
  378. data/test/fixtures/binaries.yml +4 -0
  379. data/test/fixtures/books.yml +9 -2
  380. data/test/fixtures/categories_posts.yml +3 -0
  381. data/test/fixtures/citations.yml +5 -0
  382. data/test/fixtures/comments.yml +7 -0
  383. data/test/fixtures/companies.yml +5 -0
  384. data/test/fixtures/computers.yml +2 -0
  385. data/test/fixtures/customers.yml +10 -1
  386. data/test/fixtures/developers.yml +1 -1
  387. data/test/fixtures/essays.yml +10 -0
  388. data/test/fixtures/faces.yml +3 -3
  389. data/test/fixtures/humans.yml +5 -0
  390. data/test/fixtures/interests.yml +7 -7
  391. data/test/fixtures/memberships.yml +7 -0
  392. data/test/fixtures/minimalistics.yml +3 -0
  393. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  394. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  395. data/test/fixtures/naked/yml/parrots.yml +1 -0
  396. data/test/fixtures/other_books.yml +26 -0
  397. data/test/fixtures/other_posts.yml +1 -0
  398. data/test/fixtures/parrots.yml +7 -1
  399. data/test/fixtures/pirates.yml +3 -0
  400. data/test/fixtures/posts.yml +11 -3
  401. data/test/fixtures/readers.yml +6 -0
  402. data/test/fixtures/reserved_words/values.yml +2 -2
  403. data/test/fixtures/sponsors.yml +3 -0
  404. data/test/fixtures/strict_zines.yml +2 -0
  405. data/test/fixtures/subscribers.yml +1 -1
  406. data/test/fixtures/tasks.yml +1 -1
  407. data/test/fixtures/warehouse-things.yml +3 -0
  408. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  409. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  410. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  411. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  412. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  413. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  414. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  415. data/test/migrations/rename/1_we_need_things.rb +2 -0
  416. data/test/migrations/rename/2_rename_things.rb +2 -0
  417. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  418. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  419. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  420. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  421. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  422. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  423. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  424. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  425. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  426. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  427. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  428. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  429. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  430. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  431. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  432. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  433. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  434. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  435. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  436. data/test/models/account.rb +46 -0
  437. data/test/models/admin/account.rb +3 -1
  438. data/test/models/admin/randomly_named_c1.rb +2 -0
  439. data/test/models/admin/user.rb +16 -8
  440. data/test/models/admin.rb +4 -2
  441. data/test/models/aircraft.rb +3 -1
  442. data/test/models/arunit2_model.rb +2 -0
  443. data/test/models/author.rb +153 -102
  444. data/test/models/auto_id.rb +2 -0
  445. data/test/models/autoloadable/extra_firm.rb +2 -0
  446. data/test/models/binary.rb +3 -1
  447. data/test/models/binary_field.rb +6 -0
  448. data/test/models/bird.rb +13 -1
  449. data/test/models/book.rb +14 -4
  450. data/test/models/book_destroy_async.rb +24 -0
  451. data/test/models/boolean.rb +5 -0
  452. data/test/models/bulb.rb +13 -4
  453. data/test/models/cake_designer.rb +2 -0
  454. data/test/models/car.rb +17 -10
  455. data/test/models/carrier.rb +2 -0
  456. data/test/models/cart.rb +5 -0
  457. data/test/models/cat.rb +2 -0
  458. data/test/models/categorization.rb +8 -6
  459. data/test/models/category.rb +28 -16
  460. data/test/models/chef.rb +2 -0
  461. data/test/models/citation.rb +5 -1
  462. data/test/models/club.rb +13 -10
  463. data/test/models/college.rb +4 -2
  464. data/test/models/column.rb +2 -0
  465. data/test/models/column_name.rb +2 -0
  466. data/test/models/comment.rb +32 -10
  467. data/test/models/company.rb +102 -106
  468. data/test/models/company_in_module.rb +27 -26
  469. data/test/models/computer.rb +3 -1
  470. data/test/models/contact.rb +15 -13
  471. data/test/models/content.rb +5 -3
  472. data/test/models/contract.rb +21 -3
  473. data/test/models/country.rb +2 -4
  474. data/test/models/course.rb +3 -1
  475. data/test/models/customer.rb +10 -8
  476. data/test/models/customer_carrier.rb +2 -0
  477. data/test/models/dashboard.rb +2 -0
  478. data/test/models/default.rb +2 -0
  479. data/test/models/department.rb +2 -0
  480. data/test/models/destroy_async_parent.rb +15 -0
  481. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  482. data/test/models/developer.rb +152 -85
  483. data/test/models/dl_keyed_belongs_to.rb +13 -0
  484. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  485. data/test/models/dl_keyed_has_many.rb +5 -0
  486. data/test/models/dl_keyed_has_many_through.rb +5 -0
  487. data/test/models/dl_keyed_has_one.rb +5 -0
  488. data/test/models/dl_keyed_join.rb +10 -0
  489. data/test/models/dog.rb +2 -0
  490. data/test/models/dog_lover.rb +2 -0
  491. data/test/models/doubloon.rb +3 -1
  492. data/test/models/drink_designer.rb +17 -0
  493. data/test/models/edge.rb +4 -2
  494. data/test/models/electron.rb +2 -0
  495. data/test/models/engine.rb +3 -2
  496. data/test/models/entrant.rb +2 -0
  497. data/test/models/entry.rb +5 -0
  498. data/test/models/essay.rb +6 -3
  499. data/test/models/essay_destroy_async.rb +12 -0
  500. data/test/models/event.rb +3 -1
  501. data/test/models/eye.rb +5 -3
  502. data/test/models/face.rb +14 -6
  503. data/test/models/family.rb +6 -0
  504. data/test/models/family_tree.rb +6 -0
  505. data/test/models/friendship.rb +5 -3
  506. data/test/models/frog.rb +8 -0
  507. data/test/models/guid.rb +3 -1
  508. data/test/models/guitar.rb +2 -0
  509. data/test/models/hotel.rb +5 -3
  510. data/test/models/human.rb +39 -0
  511. data/test/models/image.rb +3 -1
  512. data/test/models/interest.rb +14 -3
  513. data/test/models/invoice.rb +4 -2
  514. data/test/models/item.rb +3 -1
  515. data/test/models/job.rb +5 -3
  516. data/test/models/joke.rb +4 -2
  517. data/test/models/keyboard.rb +3 -1
  518. data/test/models/legacy_thing.rb +2 -0
  519. data/test/models/lesson.rb +2 -0
  520. data/test/models/line_item.rb +3 -1
  521. data/test/models/liquid.rb +2 -0
  522. data/test/models/matey.rb +3 -1
  523. data/test/models/measurement.rb +4 -0
  524. data/test/models/member.rb +23 -20
  525. data/test/models/member_detail.rb +3 -0
  526. data/test/models/member_type.rb +2 -0
  527. data/test/models/membership.rb +4 -1
  528. data/test/models/mentor.rb +3 -1
  529. data/test/models/message.rb +5 -0
  530. data/test/models/minimalistic.rb +2 -0
  531. data/test/models/minivan.rb +3 -2
  532. data/test/models/mixed_case_monkey.rb +3 -1
  533. data/test/models/molecule.rb +2 -0
  534. data/test/models/mouse.rb +6 -0
  535. data/test/models/movie.rb +2 -0
  536. data/test/models/node.rb +4 -2
  537. data/test/models/non_primary_key.rb +2 -0
  538. data/test/models/notification.rb +2 -0
  539. data/test/models/numeric_data.rb +12 -0
  540. data/test/models/order.rb +4 -2
  541. data/test/models/organization.rb +9 -7
  542. data/test/models/other_dog.rb +3 -1
  543. data/test/models/owner.rb +6 -4
  544. data/test/models/parrot.rb +12 -4
  545. data/test/models/person.rb +59 -54
  546. data/test/models/personal_legacy_thing.rb +3 -1
  547. data/test/models/pet.rb +4 -2
  548. data/test/models/pet_treasure.rb +2 -0
  549. data/test/models/pirate.rb +67 -43
  550. data/test/models/possession.rb +3 -1
  551. data/test/models/post.rb +184 -86
  552. data/test/models/price_estimate.rb +11 -1
  553. data/test/models/professor.rb +3 -1
  554. data/test/models/project.rb +14 -12
  555. data/test/models/publisher/article.rb +2 -0
  556. data/test/models/publisher/magazine.rb +2 -0
  557. data/test/models/publisher.rb +2 -0
  558. data/test/models/randomly_named_c1.rb +2 -0
  559. data/test/models/rating.rb +5 -1
  560. data/test/models/reader.rb +7 -5
  561. data/test/models/recipe.rb +2 -0
  562. data/test/models/record.rb +2 -0
  563. data/test/models/reference.rb +6 -3
  564. data/test/models/reply.rb +39 -21
  565. data/test/models/room.rb +6 -0
  566. data/test/models/section.rb +6 -0
  567. data/test/models/seminar.rb +6 -0
  568. data/test/models/session.rb +6 -0
  569. data/test/models/ship.rb +12 -9
  570. data/test/models/ship_part.rb +5 -3
  571. data/test/models/shop.rb +4 -2
  572. data/test/models/shop_account.rb +2 -0
  573. data/test/models/speedometer.rb +2 -0
  574. data/test/models/sponsor.rb +8 -5
  575. data/test/models/squeak.rb +6 -0
  576. data/test/models/strict_zine.rb +7 -0
  577. data/test/models/string_key_object.rb +2 -0
  578. data/test/models/student.rb +2 -0
  579. data/test/models/subscriber.rb +4 -2
  580. data/test/models/subscription.rb +5 -1
  581. data/test/models/tag.rb +6 -3
  582. data/test/models/tagging.rb +13 -6
  583. data/test/models/task.rb +2 -0
  584. data/test/models/topic.rb +54 -19
  585. data/test/models/toy.rb +4 -0
  586. data/test/models/traffic_light.rb +2 -0
  587. data/test/models/treasure.rb +5 -3
  588. data/test/models/treaty.rb +2 -4
  589. data/test/models/tree.rb +2 -0
  590. data/test/models/tuning_peg.rb +2 -0
  591. data/test/models/tyre.rb +2 -0
  592. data/test/models/user.rb +12 -4
  593. data/test/models/uuid_child.rb +2 -0
  594. data/test/models/uuid_item.rb +2 -0
  595. data/test/models/uuid_parent.rb +2 -0
  596. data/test/models/vegetables.rb +12 -3
  597. data/test/models/vertex.rb +6 -4
  598. data/test/models/warehouse_thing.rb +2 -0
  599. data/test/models/wheel.rb +3 -1
  600. data/test/models/without_table.rb +3 -1
  601. data/test/models/zine.rb +3 -1
  602. data/test/schema/mysql2_specific_schema.rb +49 -35
  603. data/test/schema/oracle_specific_schema.rb +13 -15
  604. data/test/schema/postgresql_specific_schema.rb +51 -40
  605. data/test/schema/schema.rb +334 -154
  606. data/test/schema/sqlite_specific_schema.rb +9 -16
  607. data/test/support/config.rb +26 -26
  608. data/test/support/connection.rb +14 -8
  609. data/test/support/connection_helper.rb +3 -1
  610. data/test/support/ddl_helper.rb +2 -0
  611. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  618. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  619. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  620. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  621. data/test/support/schema_dumping_helper.rb +2 -0
  622. data/test/support/stubs/strong_parameters.rb +40 -0
  623. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  624. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  625. metadata +192 -14
@@ -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/man"
10
+ require "models/human"
9
11
  require "models/interest"
10
12
  require "models/owner"
11
13
  require "models/pet"
12
- require 'active_support/hash_with_indifferent_access'
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, :allow_destroy => true, :reject_if => proc(&:empty?)
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!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
34
- pirate.birds_with_reject_all_blank_attributes = [{:name => '', :color => '', :_destroy => '0'}]
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
- assert pirate.birds_with_reject_all_blank.empty?
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!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
42
- pirate.birds_with_reject_all_blank_attributes = [{:name => '', :color => ''}]
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
- assert pirate.birds_with_reject_all_blank.empty?
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!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
50
- pirate.birds_with_reject_all_blank_attributes = [{:name => 'Tweetie', :color => ''}]
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 'Tweetie', pirate.birds_with_reject_all_blank.first.name
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(:ship_attributes => { :sail => true })
68
+ Pirate.new(ship_attributes: { sail: true })
67
69
  end
68
- assert_equal "unknown attribute 'sail' for Ship.", exception.message
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: 'Nights Dirty Lightning')
77
+ ship = pirate.create_ship(name: "Nights Dirty Lightning")
76
78
 
77
- pirate.update(ship_attributes: { '_destroy' => true, :id => ship.id })
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!(:name => 'Nights Dirty Lightning')
84
- assert !ship._destroy
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, :reject_if => :new_record?
92
+ Pirate.accepts_nested_attributes_for :ship, reject_if: :new_record?
91
93
 
92
- pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
93
- pirate.ship_attributes = { :name => 'Black Pearl' }
94
- assert_no_difference('Ship.count') { pirate.save! }
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, :reject_if => :reject_empty_ships_on_create
100
+ Pirate.accepts_nested_attributes_for :ship, reject_if: :reject_empty_ships_on_create
99
101
 
100
- pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
101
- pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
102
- assert_no_difference('Ship.count') { pirate.save! }
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 = { :name => 'Red Pearl', :_reject_me_if_new => true }
107
- assert_difference('Ship.count') { pirate.save! }
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, :reject_if => proc {|attributes| attributes[:name].blank? }
113
+ Pirate.accepts_nested_attributes_for :ship, reject_if: proc { |attributes| attributes[:name].blank? }
112
114
 
113
- pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
114
- pirate.ship_attributes = { :name => 'Hello Pearl' }
115
- assert_difference('Ship.count') { pirate.save! }
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, :reject_if => proc {|attributes| true }
120
- pirate = Pirate.new(catchphrase: "Stop wastin' me time")
121
- ship = pirate.create_ship(name: 's1')
122
- pirate.update({ship_attributes: { name: 's2', id: ship.id } })
123
- assert_equal 's1', ship.reload.name
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: 'Ship 1' }
130
- assert_equal ship_built_first.object_id, pirate.ship.object_id
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: 'Ship 1', pirate_id: pirate.id + 1 }
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
- Man.accepts_nested_attributes_for :interests, :reject_if => proc {|attributes| true }
142
- man = Man.create(name: "John")
143
- interest = man.interests.create(topic: 'photography')
144
- man.update({interests_attributes: { topic: 'gardening', id: interest.id } })
145
- assert_equal 'photography', interest.reload.topic
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
- Man.accepts_nested_attributes_for :interests, :reject_if => proc {|attributes| true }, :allow_destroy => true
150
- man = Man.create(name: "Jon")
151
- interest = man.interests.create(topic: 'the ladies')
152
- man.update({interests_attributes: { _destroy: "1", id: interest.id } })
153
- assert man.reload.interests.empty?
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
- Man.accepts_nested_attributes_for(:interests)
171
- man = Man.create(name: 'John')
172
- interest = man.interests.create(topic: 'photography')
173
- man.update({interests_attributes: {topic: 'gardening', id: interest.id}})
174
- assert_equal 'gardening', interest.reload.topic
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, :reject_if => proc {|attributes| attributes[:id].blank? }
181
+ Pirate.accepts_nested_attributes_for :ship, reject_if: proc { |attributes| attributes[:id].blank? }
180
182
 
181
- pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
182
- pirate.ship_attributes = { :id => "" }
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
- Man.accepts_nested_attributes_for(:interests)
188
- man = Man.create(:name => "John")
189
- interest = man.interests.create :topic => 'gardening'
190
- man = Man.find man.id
191
- man.interests_attributes = [{:id => interest.id, :topic => 'gardening'}]
192
- assert_equal man.interests.first.topic, man.interests[0].topic
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(:color => "blue"))
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 = { :name => "James" }
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 = { :name => "James" }
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!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
223
- @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning')
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(:name => 'pearl', :looter_attributes => {:catchphrase => "Arrr"})
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 = { :name => 'Davy Jones Gold Dagger' }
253
+ @pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger" }
240
254
 
241
- assert !@pirate.ship.persisted?
242
- assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
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 = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
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 = { :name => 'Davy Jones Gold Dagger' }
274
+ @pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger" }
261
275
 
262
- assert !@pirate.ship.persisted?
263
- assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
264
- assert_equal 'Nights Dirty Lightning', @ship.name
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 = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
282
+ @pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger", _destroy: "1" }
269
283
 
270
284
  assert_equal @ship, @pirate.ship
271
- assert_equal 'Nights Dirty Lightning', @pirate.ship.name
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 = { :id => @ship.id, :name => 'Davy Jones Gold Dagger' }
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 'Davy Jones Gold Dagger', @pirate.ship.name
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 = { :id => 1234567890 }
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 = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' }
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 'Davy Jones Gold Dagger', @pirate.ship.name
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, 'ABC1X') do
297
- @pirate.ship_attributes = { :id => @ship.id, :name => 'Davy Jones Gold Dagger' }
310
+ @ship.stub(:id, "ABC1X") do
311
+ @pirate.ship_attributes = { id: @ship.id, name: "Davy Jones Gold Dagger" }
298
312
 
299
- assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
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, '1', true, 'true'].each do |truth|
307
- ship = @pirate.reload.create_ship(name: 'Mister Pablo')
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, '0', 0, 'false', false].each do |not_truth|
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, :allow_destroy => false, :reject_if => proc(&:empty?)
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: '1' })
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, :allow_destroy => true, :reject_if => proc(&:empty?)
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(:id => @ship.id, :name => 'Davy Jones Gold Dagger')
348
+ @pirate.ship_attributes = ActiveSupport::HashWithIndifferentAccess.new(id: @ship.id, name: "Davy Jones Gold Dagger")
335
349
 
336
- assert @pirate.ship.persisted?
337
- assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
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({ catchphrase: 'Arr', ship_attributes: { id: @ship.id, name: 'Mister Pablo' } })
355
+ @pirate.update(catchphrase: "Arr", ship_attributes: { id: @ship.id, name: "Mister Pablo" })
342
356
  @pirate.reload
343
357
 
344
- assert_equal 'Arr', @pirate.catchphrase
345
- assert_equal 'Mister Pablo', @pirate.ship.name
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 = { :ship_attributes => { :id => @ship.id, :_destroy => '1' } }
363
+ @pirate.attributes = { ship_attributes: { id: @ship.id, _destroy: "1" } }
350
364
 
351
- assert !@pirate.ship.destroyed?
352
- assert @pirate.ship.marked_for_destruction?
365
+ assert_not_predicate @pirate.ship, :destroyed?
366
+ assert_predicate @pirate.ship, :marked_for_destruction?
353
367
 
354
368
  @pirate.save
355
369
 
356
- assert @pirate.ship.destroyed?
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: 'Mayflower' })
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: 'Mayflower' })
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: 'Nights Dirty Lightning')
392
+ @ship = @pirate.create_update_only_ship(name: "Nights Dirty Lightning")
379
393
 
380
- @pirate.update(update_only_ship_attributes: { name: 'Mayflower' })
394
+ @pirate.update(update_only_ship_attributes: { name: "Mayflower" })
381
395
 
382
- assert_equal 'Mayflower', @ship.reload.name
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: 'Nights Dirty Lightning')
402
+ @ship = @pirate.create_update_only_ship(name: "Nights Dirty Lightning")
389
403
 
390
- @pirate.update(update_only_ship_attributes: { name: 'Mayflower', id: @ship.id })
404
+ @pirate.update(update_only_ship_attributes: { name: "Mayflower", id: @ship.id })
391
405
 
392
- assert_equal 'Mayflower', @ship.reload.name
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, :update_only => true, :allow_destroy => true
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: 'Nights Dirty Lightning')
413
+ @ship = @pirate.create_update_only_ship(name: "Nights Dirty Lightning")
400
414
 
401
- @pirate.update(update_only_ship_attributes: { name: 'Mayflower', id: @ship.id, _destroy: true })
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, :update_only => true, :allow_destroy => false
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(:name => 'Nights Dirty Lightning')
414
- @pirate = @ship.build_pirate(:catchphrase => 'Aye')
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 = { :catchphrase => 'Arr' }
437
+ @ship.reload.pirate_attributes = { catchphrase: "Arr" }
425
438
 
426
- assert !@ship.pirate.persisted?
427
- assert_equal 'Arr', @ship.pirate.catchphrase
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 = { :catchphrase => 'Arr', :_destroy => '1' }
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 = { :catchphrase => 'Arr' }
458
+ @ship.reload.pirate_attributes = { catchphrase: "Arr" }
446
459
 
447
- assert !@ship.pirate.persisted?
448
- assert_equal 'Arr', @ship.pirate.catchphrase
449
- assert_equal 'Aye', @pirate.catchphrase
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 = { :catchphrase => 'Arr', :_destroy => '1' }
466
+ @ship.reload.pirate_attributes = { catchphrase: "Arr", _destroy: "1" }
454
467
 
455
468
  assert_equal @pirate, @ship.pirate
456
- assert_equal 'Aye', @ship.pirate.catchphrase
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 = { :id => @pirate.id, :catchphrase => 'Arr' }
473
+ @ship.reload.pirate_attributes = { id: @pirate.id, catchphrase: "Arr" }
461
474
 
462
475
  assert_equal @pirate, @ship.pirate
463
- assert_equal 'Arr', @ship.pirate.catchphrase
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 = { :id => 1234567890 }
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 = { 'id' => @pirate.id, 'catchphrase' => 'Arr' }
487
+ @ship.reload.pirate_attributes = { "id" => @pirate.id, "catchphrase" => "Arr" }
475
488
 
476
489
  assert_equal @pirate, @ship.pirate
477
- assert_equal 'Arr', @ship.pirate.catchphrase
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, 'ABC1X') do
482
- @ship.pirate_attributes = { :id => @pirate.id, :catchphrase => 'Arr' }
494
+ @pirate.stub(:id, "ABC1X") do
495
+ @ship.pirate_attributes = { id: @pirate.id, catchphrase: "Arr" }
483
496
 
484
- assert_equal 'Arr', @ship.pirate.catchphrase
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, '1', true, 'true'].each do |truth|
491
- pirate = @ship.reload.create_pirate(catchphrase: 'Arr')
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, '0', 0, 'false', false].each do |not_truth|
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, :allow_destroy => false, :reject_if => proc(&:empty?)
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: '1' })
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, :allow_destroy => true, :reject_if => proc(&:empty?)
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({ name: 'Mister Pablo', pirate_attributes: { catchphrase: 'Arr' } })
541
+ @ship.update(name: "Mister Pablo", pirate_attributes: { catchphrase: "Arr" })
529
542
  @ship.reload
530
543
 
531
- assert_equal 'Mister Pablo', @ship.name
532
- assert_equal 'Arr', @ship.pirate.catchphrase
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 = { :pirate_attributes => { :id => pirate.id, '_destroy' => true } }
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 = { :update_only_pirate_attributes => { :catchphrase => 'Arr' } }
563
+ @ship.reload.attributes = { update_only_pirate_attributes: { catchphrase: "Arr" } }
551
564
 
552
- assert !@ship.update_only_pirate.persisted?
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: 'Aye')
570
+ @pirate = @ship.create_update_only_pirate(catchphrase: "Aye")
558
571
 
559
- @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr' })
560
- assert_equal 'Arr', @pirate.reload.catchphrase
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: 'Aye')
579
+ @pirate = @ship.create_update_only_pirate(catchphrase: "Aye")
567
580
 
568
- @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr', id: @pirate.id })
581
+ @ship.update(update_only_pirate_attributes: { catchphrase: "Arr", id: @pirate.id })
569
582
 
570
- assert_equal 'Arr', @pirate.reload.catchphrase
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, :update_only => true, :allow_destroy => true
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: 'Aye')
590
+ @pirate = @ship.create_update_only_pirate(catchphrase: "Aye")
578
591
 
579
- @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr', id: @pirate.id, _destroy: true })
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, :update_only => true, :allow_destroy => false
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
- assert_equal "unknown attribute 'peg_leg' for Parrot.", exception.message
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 => 'Arr',
602
- association_getter => { 'foo' => { :name => 'Grace OMalley' } }
603
- })
613
+ pirate = Pirate.create!(
614
+ :catchphrase => "Arr",
615
+ association_getter => { "foo" => { name: "Grace OMalley" } })
604
616
 
605
- assert_equal 1, pirate.reload.send(@association_name).count
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 ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
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.send(association_setter, @alternate_params[association_getter].values)
627
+ @pirate.public_send(association_setter, @alternate_params[association_getter].values)
616
628
  @pirate.save
617
- assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
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.send(association_setter, ActiveSupport::HashWithIndifferentAccess.new('foo' => ActiveSupport::HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley')))
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 'Grace OMalley', @child_1.reload.name
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 'Grace OMalley', @pirate.send(@association_name).first.name
629
- assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
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.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }])
635
- assert ! @pirate.send(@association_name).loaded?
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
- assert ! @pirate.send(@association_name).loaded?
639
- assert_equal 'Grace OMalley', @child_1.reload.name
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.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }])
645
- assert_equal 'Grace OMalley', @pirate.send(@association_name).send(:load_target).find { |r| r.id == @child_1.id }.name
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.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }])
651
- assert_equal @child_1.id, @pirate.send(@association_name).send(:load_target).first.id
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: 'Grace OMalley')
657
- @pirate.send(@association_name) << record
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.send(@association_name).last.update!(name: 'Polly')
660
- assert_equal 'Polly', @pirate.send(@association_name).send(:load_target).last.name
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.send(association_setter, [{ :id => @child_1.id, :_destroy => '1' }])
666
- assert @pirate.send(@association_name).send(:load_target).find { |r| r.id == @child_1.id }.marked_for_destruction?
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, 'ABC1X') do
671
- @child_2.stub(:id, 'ABC2X') do
672
-
682
+ @child_1.stub(:id, "ABC1X") do
683
+ @child_2.stub(:id, "ABC2X") do
673
684
  @pirate.attributes = {
674
685
  association_getter => [
675
- { :id => @child_1.id, :name => 'Grace OMalley' },
676
- { :id => @child_2.id, :name => 'Privateers Greed' }
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 ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name]
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 => [{ :id => 1234567890 }] }
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: 'Ahoy!'
694
- other_child = other_pirate.send(@association_name).create! name: 'Buccaneers Servant'
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.send(@association_name).destroy_all
714
+ @pirate.public_send(@association_name).destroy_all
704
715
  @pirate.reload.attributes = {
705
- association_getter => { 'foo' => { :name => 'Grace OMalley' }, 'bar' => { :name => 'Privateers Greed' }}
716
+ association_getter => { "foo" => { name: "Grace OMalley" }, "bar" => { name: "Privateers Greed" } }
706
717
  }
707
718
 
708
- assert !@pirate.send(@association_name).first.persisted?
709
- assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
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
- assert !@pirate.send(@association_name).last.persisted?
712
- assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
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.send(association_setter, { 'foo' => { '_destroy' => '0' }})
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.send(@association_name).destroy_all
733
+ @pirate.public_send(@association_name).destroy_all
723
734
  @pirate.reload.attributes = {
724
735
  association_getter => {
725
- 'foo' => { :name => 'Grace OMalley' },
726
- 'bar' => { :name => 'Privateers Greed', '_destroy' => '1' }
736
+ "foo" => { name: "Grace OMalley" },
737
+ "bar" => { :name => "Privateers Greed", "_destroy" => "1" }
727
738
  }
728
739
  }
729
740
 
730
- assert_equal 1, @pirate.send(@association_name).length
731
- assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
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]['baz'] = {}
736
- assert_no_difference("@pirate.send(@association_name).count") do
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['123726353'] = { :name => 'Grace OMalley' }
744
- attributes['2'] = { :name => 'Privateers Greed' } # 2 is lower then 123726353
745
- @pirate.send(association_setter, attributes)
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 ['Posideons Killer', 'Killer bandita Dionne', 'Privateers Greed', 'Grace OMalley'].to_set, @pirate.send(@association_name).map(&:name).to_set
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.send(association_setter, {}) }
752
- assert_nothing_raised { @pirate.send(association_setter, Hash.new) }
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.send(association_setter, "foo")
766
+ @pirate.public_send(association_setter, "foo")
756
767
  end
757
- assert_equal 'Hash or Array expected, got String ("foo")', exception.message
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: 'Arr',
762
- association_getter => { 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' }})
772
+ @pirate.update(catchphrase: "Arr",
773
+ association_getter => { "foo" => { id: @child_1.id, name: "Grace OMalley" } })
763
774
 
764
- assert_equal 'Grace OMalley', @child_1.reload.name
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]['baz'] = { name: 'Buccaneers Servant' }
769
- assert_difference('@pirate.send(@association_name).count', +1) do
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 ['Grace OMalley', 'Privateers Greed', 'Buccaneers Servant'].to_set, @pirate.reload.send(@association_name).map(&:name).to_set
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
- ['1', 1, 'true', true].each do |true_variable|
777
- record = @pirate.reload.send(@association_name).create!(:name => 'Grace OMalley')
778
- @pirate.send(association_setter,
779
- @alternate_params[association_getter].merge('baz' => { :id => record.id, '_destroy' => true_variable })
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('@pirate.send(@association_name).count', -1) do
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, '', '0', 0, 'false', false].each do |false_variable|
790
- @alternate_params[association_getter]['foo']['_destroy'] = false_variable
791
- assert_no_difference('@pirate.send(@association_name).count') do
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('@pirate.send(@association_name).count') do
799
- @pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_destroy' => true }))
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('@pirate.send(@association_name).count', -1) { @pirate.save }
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
- Man.accepts_nested_attributes_for(:interests)
810
- assert_equal :man, Man.reflect_on_association(:interests).options[:inverse_of]
811
- assert_equal :interests, Interest.reflect_on_association(:man).options[:inverse_of]
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(:man)
815
- assert_difference 'Man.count' do
816
- assert_difference 'Interest.count', 2 do
817
- man = Man.create!(:name => 'John',
818
- :interests_attributes => [{:topic=>'Cars'}, {:topic=>'Sports'}])
819
- assert_equal 2, man.interests.count
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 = { :parrots_attributes => { :foo => { :name => 'Lovely Day' }, :bar => { :name => 'Blown Away' } } }
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
- Man.accepts_nested_attributes_for(:interests)
842
+ Human.accepts_nested_attributes_for(:interests)
832
843
 
833
844
  repair_validations(Interest) do
834
845
  Interest.validates_numericality_of(:zine_id)
835
- man = Man.create(name: 'John')
836
- interest = man.interests.create(topic: 'bar', zine_id: 0)
846
+ human = Human.create(name: "John")
847
+ interest = human.interests.create(topic: "bar", zine_id: 0)
837
848
  assert interest.save
838
- assert !man.update({interests_attributes: { id: interest.id, zine_id: 'foo' }})
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
- def association_setter
845
- @association_setter ||= "#{@association_name}_attributes=".to_sym
846
- end
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!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
859
- @pirate.birds.create!(:name => 'Posideons Killer')
860
- @pirate.birds.create!(:name => 'Killer bandita Dionne')
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
- :birds_attributes => {
866
- 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' },
867
- 'bar' => { :id => @child_2.id, :name => 'Privateers Greed' }
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!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
881
- @pirate.parrots.create!(:name => 'Posideons Killer')
882
- @pirate.parrots.create!(:name => 'Killer bandita Dionne')
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
- :parrots_attributes => {
888
- 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' },
889
- 'bar' => { :id => @child_2.id, :name => 'Privateers Greed' }
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, :allow_destroy => true, :reject_if => proc(&:empty?)
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 = { :parrots_attributes => { 'foo' => { :name => 'Big Big Love' } } }
904
- assert_difference('Parrot.count') { @pirate.save! }
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 = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' }, 'bar' => { :name => 'Blown Away' } } }
909
- assert_difference('Parrot.count', 2) { @pirate.save! }
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 = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' },
915
- 'bar' => { :name => 'Blown Away' },
916
- 'car' => { :name => 'The Happening' }} }
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, :limit => 2
933
+ Pirate.accepts_nested_attributes_for :parrots, limit: 2
924
934
 
925
- @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
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, :limit => :parrots_limit
943
+ Pirate.accepts_nested_attributes_for :parrots, limit: :parrots_limit
934
944
 
935
- @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?", :parrots_limit => 2)
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, :limit => proc { 2 }
953
+ Pirate.accepts_nested_attributes_for :parrots, limit: proc { 2 }
944
954
 
945
- @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
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, :allow_destroy => true
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
- :pets_attributes => {
962
- '0' => { :id => @pet1.id, :name => 'Foo' },
963
- '1' => { :id => @pet2.id, :name => 'Bar' }
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 ['Foo', 'Bar'], @owner.pets.map(&:name)
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 = {:pets_attributes => { "1"=> { :id => @pet1.id,
977
- :name => "Foo2",
978
- :current_user => "John",
979
- :_destroy=>true }}}
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 'John', Pet.after_destroy_output
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!(:catchphrase => "My baby takes tha mornin' train!")
991
- @ship = @pirate.create_ship(:name => "The good ship Dollypop")
992
- @part = @ship.parts.create!(:name => "Mast")
993
- @trinket = @part.trinkets.create!(:name => "Necklace")
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 = {:ship_attributes => {:id => @ship.id, :parts_attributes => [{:id => @part.id, :trinkets_attributes => [{:id => @trinket.id, :name => "changed"}]}]}}
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 = {:ship_attributes => {:id => @ship.id, :parts_attributes => [{:id => @part.id, :trinkets_attributes => [{:id => @trinket.id, :_destroy => true}]}]}}
1010
- assert_difference('@part.trinkets.count', -1) { @pirate.save }
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 = {:ship_attributes => {:id => @ship.id, :parts_attributes => [{:id => @part.id, :trinkets_attributes => [{:name => "created"}]}]}}
1015
- assert_difference('@part.trinkets.count', 1) { @pirate.save }
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!(:pirate => @pirate, :name => "The Black Rock")
1021
- ShipPart.create!(:ship => @ship, :name => "Stern")
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!(:name => "The good ship Dollypop")
1031
- @part = @ship.parts.create!(:name => "Mast")
1032
- @trinket = @part.trinkets.create!(:name => "Necklace")
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=[{:id => @part.id,:name =>'Deck'}]
1045
+ @ship.parts_attributes = [{ id: @part.id, name: "Deck" }]
1037
1046
  assert_equal 1, @ship.association(:parts).target.size
1038
- assert_equal 'Deck', @ship.parts[0].name
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=[{:id => @part.id,:trinkets_attributes =>[{:id => @trinket.id, :name => 'Ruby'}]}]
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 'Mast', @ship.parts[0].name
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 'Ruby', @ship.parts[0].trinkets[0].name
1057
+ assert_equal "Ruby", @ship.parts[0].trinkets[0].name
1049
1058
  @ship.save
1050
- assert_equal 'Ruby', @ship.parts[0].trinkets[0].name
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 = {:parts_attributes => [{:id => @part.id, :trinkets_attributes => [{:id => @trinket.id, :name => "changed"}]}]}
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 = {:parts_attributes => [{:id => @part.id, :trinkets_attributes => [{:id => @trinket.id, :_destroy => true}]}]}
1067
- assert_difference('@part.trinkets.count', -1) { @ship.save }
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 = {:parts_attributes => [{:id => @part.id, :trinkets_attributes => [{:name => "created"}]}]}
1072
- assert_difference('@part.trinkets.count', 1) { @ship.save }
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!(:name => "The Black Rock")
1078
- ShipPart.create!(:ship => @ship, :name => "Stern")
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
- assert_not part.valid?
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