ibm_db 5.2.0-x86-mingw32 → 5.4.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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,61 +1,63 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cases/helper"
2
- require 'models/developer'
3
- require 'models/computer'
4
- require 'models/project'
5
- require 'models/company'
6
- require 'models/contract'
7
- require 'models/topic'
8
- require 'models/reply'
9
- require 'models/category'
10
- require 'models/image'
11
- require 'models/post'
12
- require 'models/author'
13
- require 'models/essay'
14
- require 'models/comment'
15
- require 'models/person'
16
- require 'models/reader'
17
- require 'models/tagging'
18
- require 'models/tag'
19
- require 'models/invoice'
20
- require 'models/line_item'
21
- require 'models/car'
22
- require 'models/bulb'
23
- require 'models/engine'
24
- require 'models/categorization'
25
- require 'models/minivan'
26
- require 'models/speedometer'
27
- require 'models/reference'
28
- require 'models/job'
29
- require 'models/college'
30
- require 'models/student'
31
- require 'models/pirate'
32
- require 'models/ship'
33
- require 'models/ship_part'
34
- require 'models/treasure'
35
- require 'models/parrot'
36
- require 'models/tyre'
37
- require 'models/subscriber'
38
- require 'models/subscription'
39
- require 'models/zine'
40
- require 'models/interest'
4
+ require "models/developer"
5
+ require "models/computer"
6
+ require "models/project"
7
+ require "models/company"
8
+ require "models/contract"
9
+ require "models/topic"
10
+ require "models/reply"
11
+ require "models/category"
12
+ require "models/image"
13
+ require "models/post"
14
+ require "models/author"
15
+ require "models/essay"
16
+ require "models/comment"
17
+ require "models/person"
18
+ require "models/reader"
19
+ require "models/tagging"
20
+ require "models/tag"
21
+ require "models/invoice"
22
+ require "models/line_item"
23
+ require "models/car"
24
+ require "models/bulb"
25
+ require "models/engine"
26
+ require "models/categorization"
27
+ require "models/minivan"
28
+ require "models/speedometer"
29
+ require "models/reference"
30
+ require "models/job"
31
+ require "models/college"
32
+ require "models/student"
33
+ require "models/pirate"
34
+ require "models/ship"
35
+ require "models/ship_part"
36
+ require "models/treasure"
37
+ require "models/parrot"
38
+ require "models/tyre"
39
+ require "models/subscriber"
40
+ require "models/subscription"
41
+ require "models/zine"
42
+ require "models/interest"
41
43
 
42
44
  class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
43
- fixtures :authors, :posts, :comments
45
+ fixtures :authors, :author_addresses, :posts, :comments
44
46
 
45
47
  def test_should_generate_valid_sql
46
48
  author = authors(:david)
47
49
  # this can fail on adapters which require ORDER BY expressions to be included in the SELECT expression
48
50
  # if the reorder clauses are not correctly handled
49
- assert author.posts_with_comments_sorted_by_comment_id.where('comments.id > 0').reorder('posts.comments_count DESC', 'posts.tags_count DESC').last
51
+ assert author.posts_with_comments_sorted_by_comment_id.where("comments.id > 0").reorder("posts.comments_count": :desc, "posts.tags_count": :desc).last
50
52
  end
51
53
  end
52
54
 
53
55
  class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
54
- fixtures :authors, :essays, :subscribers, :subscriptions, :people
56
+ fixtures :authors, :author_addresses, :essays, :subscribers, :subscriptions, :people
55
57
 
56
58
  def test_custom_primary_key_on_new_record_should_fetch_with_query
57
- subscriber = Subscriber.new(nick: 'webster132')
58
- assert !subscriber.subscriptions.loaded?
59
+ subscriber = Subscriber.new(nick: "webster132")
60
+ assert_not_predicate subscriber.subscriptions, :loaded?
59
61
 
60
62
  assert_queries 1 do
61
63
  assert_equal 2, subscriber.subscriptions.size
@@ -65,8 +67,8 @@ class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
65
67
  end
66
68
 
67
69
  def test_association_primary_key_on_new_record_should_fetch_with_query
68
- author = Author.new(:name => "David")
69
- assert !author.essays.loaded?
70
+ author = Author.new(name: "David")
71
+ assert_not_predicate author.essays, :loaded?
70
72
 
71
73
  assert_queries 1 do
72
74
  assert_equal 1, author.essays.size
@@ -95,13 +97,13 @@ class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
95
97
  david = people(:david)
96
98
 
97
99
  assert_equal ["A Modest Proposal"], david.essays.map(&:name)
98
- david.essays = [Essay.create!(name: "Remote Work" )]
100
+ david.essays = [Essay.create!(name: "Remote Work")]
99
101
  assert_equal ["Remote Work"], david.essays.map(&:name)
100
102
  end
101
103
 
102
104
  def test_blank_custom_primary_key_on_new_record_should_not_run_queries
103
105
  author = Author.new
104
- assert !author.essays.loaded?
106
+ assert_not_predicate author.essays, :loaded?
105
107
 
106
108
  assert_queries 0 do
107
109
  assert_equal 0, author.essays.size
@@ -111,8 +113,8 @@ end
111
113
 
112
114
  class HasManyAssociationsTest < ActiveRecord::TestCase
113
115
  fixtures :accounts, :categories, :companies, :developers, :projects,
114
- :developers_projects, :topics, :authors, :comments,
115
- :posts, :readers, :taggings, :cars, :jobs, :tags,
116
+ :developers_projects, :topics, :authors, :author_addresses, :comments,
117
+ :posts, :readers, :taggings, :cars, :tags,
116
118
  :categorizations, :zines, :interests
117
119
 
118
120
  def setup
@@ -127,14 +129,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
127
129
 
128
130
  def test_anonymous_has_many
129
131
  developer = Class.new(ActiveRecord::Base) {
130
- self.table_name = 'developers'
132
+ self.table_name = "developers"
131
133
  dev = self
132
134
 
133
135
  developer_project = Class.new(ActiveRecord::Base) {
134
- self.table_name = 'developers_projects'
135
- belongs_to :developer, :anonymous_class => dev
136
+ self.table_name = "developers_projects"
137
+ belongs_to :developer, anonymous_class: dev
136
138
  }
137
- has_many :developer_projects, :anonymous_class => developer_project, :foreign_key => 'developer_id'
139
+ has_many :developer_projects, anonymous_class: developer_project, foreign_key: "developer_id"
138
140
  }
139
141
  dev = developer.first
140
142
  named = Developer.find(dev.id)
@@ -146,20 +148,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
146
148
  def test_default_scope_on_relations_is_not_cached
147
149
  counter = 0
148
150
  posts = Class.new(ActiveRecord::Base) {
149
- self.table_name = 'posts'
150
- self.inheritance_column = 'not_there'
151
+ self.table_name = "posts"
152
+ self.inheritance_column = "not_there"
151
153
  post = self
152
154
 
153
155
  comments = Class.new(ActiveRecord::Base) {
154
- self.table_name = 'comments'
155
- self.inheritance_column = 'not_there'
156
- belongs_to :post, :anonymous_class => post
156
+ self.table_name = "comments"
157
+ self.inheritance_column = "not_there"
158
+ belongs_to :post, anonymous_class: post
157
159
  default_scope -> {
158
160
  counter += 1
159
- where("id = :inc", :inc => counter)
161
+ where("id = :inc", inc: counter)
160
162
  }
161
163
  }
162
- has_many :comments, :anonymous_class => comments, :foreign_key => 'post_id'
164
+ has_many :comments, anonymous_class: comments, foreign_key: "post_id"
163
165
  }
164
166
  assert_equal 0, counter
165
167
  post = posts.first
@@ -170,15 +172,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
170
172
  end
171
173
 
172
174
  def test_has_many_build_with_options
173
- college = College.create(name: 'UFMT')
174
- Student.create(active: true, college_id: college.id, name: 'Sarah')
175
+ college = College.create(name: "UFMT")
176
+ Student.create(active: true, college_id: college.id, name: "Sarah")
175
177
 
176
178
  assert_equal college.students, Student.where(active: true, college_id: college.id)
177
179
  end
178
180
 
179
181
  def test_add_record_to_collection_should_change_its_updated_at
180
- ship = Ship.create(name: 'dauntless')
181
- part = ShipPart.create(name: 'cockpit')
182
+ ship = Ship.create(name: "dauntless")
183
+ part = ShipPart.create(name: "cockpit")
182
184
  updated_at = part.updated_at
183
185
 
184
186
  travel(1.second) do
@@ -192,80 +194,131 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
192
194
  def test_clear_collection_should_not_change_updated_at
193
195
  # GH#17161: .clear calls delete_all (and returns the association),
194
196
  # which is intended to not touch associated objects's updated_at field
195
- ship = Ship.create(name: 'dauntless')
196
- part = ShipPart.create(name: 'cockpit', ship_id: ship.id)
197
+ ship = Ship.create(name: "dauntless")
198
+ part = ShipPart.create(name: "cockpit", ship_id: ship.id)
197
199
 
198
200
  ship.parts.clear
199
201
  part.reload
200
202
 
201
- assert_equal nil, part.ship
202
- assert !part.updated_at_changed?
203
+ assert_nil part.ship
204
+ assert_not_predicate part, :updated_at_changed?
203
205
  end
204
206
 
205
207
  def test_create_from_association_should_respect_default_scope
206
- car = Car.create(:name => 'honda')
207
- assert_equal 'honda', car.name
208
+ car = Car.create(name: "honda")
209
+ assert_equal "honda", car.name
208
210
 
209
211
  bulb = Bulb.create
210
- assert_equal 'defaulty', bulb.name
212
+ assert_equal "defaulty", bulb.name
211
213
 
212
214
  bulb = car.bulbs.build
213
- assert_equal 'defaulty', bulb.name
215
+ assert_equal "defaulty", bulb.name
214
216
 
215
217
  bulb = car.bulbs.create
216
- assert_equal 'defaulty', bulb.name
218
+ assert_equal "defaulty", bulb.name
219
+
220
+ bulb = car.bulbs.create!
221
+ assert_equal "defaulty", bulb.name
217
222
  end
218
223
 
219
224
  def test_build_and_create_from_association_should_respect_passed_attributes_over_default_scope
220
- car = Car.create(name: 'honda')
225
+ car = Car.create(name: "honda")
226
+
227
+ bulb = car.bulbs.where(name: "exotic").build
228
+ assert_equal "exotic", bulb.name
229
+ assert_nil bulb.count_after_create
230
+
231
+ bulb = car.bulbs.where(name: "exotic").create
232
+ assert_equal "exotic", bulb.name
233
+ assert_equal 1, bulb.count_after_create
234
+
235
+ bulb = car.bulbs.where(name: "exotic").create!
236
+ assert_equal "exotic", bulb.name
237
+ assert_equal 2, bulb.count_after_create
238
+
239
+ bulb = car.bulbs.build(name: "exotic")
240
+ assert_equal "exotic", bulb.name
221
241
 
222
- bulb = car.bulbs.build(name: 'exotic')
223
- assert_equal 'exotic', bulb.name
242
+ bulb = car.bulbs.create(name: "exotic")
243
+ assert_equal "exotic", bulb.name
224
244
 
225
- bulb = car.bulbs.create(name: 'exotic')
226
- assert_equal 'exotic', bulb.name
245
+ bulb = car.bulbs.create!(name: "exotic")
246
+ assert_equal "exotic", bulb.name
227
247
 
228
248
  bulb = car.awesome_bulbs.build(frickinawesome: false)
229
249
  assert_equal false, bulb.frickinawesome
230
250
 
231
251
  bulb = car.awesome_bulbs.create(frickinawesome: false)
232
252
  assert_equal false, bulb.frickinawesome
253
+
254
+ bulb = car.awesome_bulbs.create!(frickinawesome: false)
255
+ assert_equal false, bulb.frickinawesome
256
+ end
257
+
258
+ def test_build_and_create_from_association_should_respect_unscope_over_default_scope
259
+ car = Car.create(name: "honda")
260
+
261
+ bulb = car.bulbs.unscope(where: :name).build
262
+ assert_nil bulb.name
263
+
264
+ bulb = car.bulbs.unscope(where: :name).create
265
+ assert_nil bulb.name
266
+
267
+ bulb = car.bulbs.unscope(where: :name).create!
268
+ assert_nil bulb.name
269
+
270
+ bulb = car.awesome_bulbs.unscope(where: :frickinawesome).build
271
+ assert_equal false, bulb.frickinawesome
272
+
273
+ bulb = car.awesome_bulbs.unscope(where: :frickinawesome).create
274
+ assert_equal false, bulb.frickinawesome
275
+
276
+ bulb = car.awesome_bulbs.unscope(where: :frickinawesome).create!
277
+ assert_equal false, bulb.frickinawesome
233
278
  end
234
279
 
235
280
  def test_build_from_association_should_respect_scope
236
281
  author = Author.new
237
282
 
238
283
  post = author.thinking_posts.build
239
- assert_equal 'So I was thinking', post.title
284
+ assert_equal "So I was thinking", post.title
240
285
  end
241
286
 
242
287
  def test_create_from_association_with_nil_values_should_work
243
- car = Car.create(:name => 'honda')
288
+ car = Car.create(name: "honda")
244
289
 
245
290
  bulb = car.bulbs.new(nil)
246
- assert_equal 'defaulty', bulb.name
291
+ assert_equal "defaulty", bulb.name
247
292
 
248
293
  bulb = car.bulbs.build(nil)
249
- assert_equal 'defaulty', bulb.name
294
+ assert_equal "defaulty", bulb.name
250
295
 
251
296
  bulb = car.bulbs.create(nil)
252
- assert_equal 'defaulty', bulb.name
297
+ assert_equal "defaulty", bulb.name
298
+ end
299
+
300
+ def test_build_from_association_sets_inverse_instance
301
+ car = Car.new(name: "honda")
302
+
303
+ bulb = car.bulbs.build
304
+ assert_equal car, bulb.car
253
305
  end
254
306
 
255
307
  def test_do_not_call_callbacks_for_delete_all
256
- car = Car.create(:name => 'honda')
308
+ car = Car.create(name: "honda")
257
309
  car.funky_bulbs.create!
258
- assert_nothing_raised { car.reload.funky_bulbs.delete_all }
259
- assert_equal 0, Bulb.count, "bulbs should have been deleted using :delete_all strategy"
310
+ assert_equal 1, car.funky_bulbs.count
311
+ assert_equal 1, car.reload.funky_bulbs.delete_all
312
+ assert_equal 0, car.funky_bulbs.count, "bulbs should have been deleted using :delete_all strategy"
260
313
  end
261
314
 
262
315
  def test_delete_all_on_association_is_the_same_as_not_loaded
263
316
  author = authors :david
264
- author.thinking_posts.create!(:body => "test")
317
+ author.thinking_posts.create!(body: "test")
265
318
  author.reload
266
319
  expected_sql = capture_sql { author.thinking_posts.delete_all }
267
320
 
268
- author.thinking_posts.create!(:body => "test")
321
+ author.thinking_posts.create!(body: "test")
269
322
  author.reload
270
323
  author.thinking_posts.inspect
271
324
  loaded_sql = capture_sql { author.thinking_posts.delete_all }
@@ -274,17 +327,25 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
274
327
 
275
328
  def test_delete_all_on_association_with_nil_dependency_is_the_same_as_not_loaded
276
329
  author = authors :david
277
- author.posts.create!(:title => "test", :body => "body")
330
+ author.posts.create!(title: "test", body: "body")
278
331
  author.reload
279
332
  expected_sql = capture_sql { author.posts.delete_all }
280
333
 
281
- author.posts.create!(:title => "test", :body => "body")
334
+ author.posts.create!(title: "test", body: "body")
282
335
  author.reload
283
336
  author.posts.to_a
284
337
  loaded_sql = capture_sql { author.posts.delete_all }
285
338
  assert_equal(expected_sql, loaded_sql)
286
339
  end
287
340
 
341
+ def test_delete_all_on_association_clears_scope
342
+ author = Author.create!(name: "Gannon")
343
+ posts = author.posts
344
+ posts.create!(title: "test", body: "body")
345
+ posts.delete_all
346
+ assert_nil posts.first
347
+ end
348
+
288
349
  def test_building_the_associated_object_with_implicit_sti_base_class
289
350
  firm = DependentFirm.new
290
351
  company = firm.companies.build
@@ -293,55 +354,99 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
293
354
 
294
355
  def test_building_the_associated_object_with_explicit_sti_base_class
295
356
  firm = DependentFirm.new
296
- company = firm.companies.build(:type => "Company")
357
+ company = firm.companies.build(type: "Company")
297
358
  assert_kind_of Company, company, "Expected #{company.class} to be a Company"
298
359
  end
299
360
 
300
361
  def test_building_the_associated_object_with_sti_subclass
301
362
  firm = DependentFirm.new
302
- company = firm.companies.build(:type => "Client")
363
+ company = firm.companies.build(type: "Client")
303
364
  assert_kind_of Client, company, "Expected #{company.class} to be a Client"
304
365
  end
305
366
 
306
367
  def test_building_the_associated_object_with_an_invalid_type
307
368
  firm = DependentFirm.new
308
- assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Invalid") }
369
+ assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(type: "Invalid") }
309
370
  end
310
371
 
311
372
  def test_building_the_associated_object_with_an_unrelated_type
312
373
  firm = DependentFirm.new
313
- assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Account") }
374
+ assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(type: "Account") }
375
+ end
376
+
377
+ test "build the association with an array" do
378
+ speedometer = Speedometer.new(speedometer_id: "a")
379
+ data = [{ name: "first" }, { name: "second" }]
380
+ speedometer.minivans.where(color: "blue").build(data)
381
+
382
+ assert_equal 2, speedometer.minivans.size
383
+ assert speedometer.save
384
+
385
+ speedometer.reload
386
+
387
+ assert_equal ["first", "second"], speedometer.minivans.map(&:name)
388
+ assert_equal ["blue", "blue"], speedometer.minivans.map(&:color)
314
389
  end
315
390
 
316
- test "building the association with an array" do
391
+ test "new the association with an array" do
317
392
  speedometer = Speedometer.new(speedometer_id: "a")
318
- data = [{name: "first"}, {name: "second"}]
319
- speedometer.minivans.build(data)
393
+ data = [{ name: "first" }, { name: "second" }]
394
+ speedometer.minivans.where(color: "blue").new(data)
320
395
 
321
396
  assert_equal 2, speedometer.minivans.size
322
397
  assert speedometer.save
323
- assert_equal ["first", "second"], speedometer.reload.minivans.map(&:name)
398
+
399
+ speedometer.reload
400
+
401
+ assert_equal ["first", "second"], speedometer.minivans.map(&:name)
402
+ assert_equal ["blue", "blue"], speedometer.minivans.map(&:color)
403
+ end
404
+
405
+ test "create the association with an array" do
406
+ speedometer = Speedometer.create!(speedometer_id: "a")
407
+ data = [{ name: "first" }, { name: "second" }]
408
+ speedometer.minivans.where(color: "blue").create(data)
409
+
410
+ assert_equal 2, speedometer.minivans.size
411
+
412
+ speedometer.reload
413
+
414
+ assert_equal ["first", "second"], speedometer.minivans.map(&:name)
415
+ assert_equal ["blue", "blue"], speedometer.minivans.map(&:color)
416
+ end
417
+
418
+ test "create! the association with an array" do
419
+ speedometer = Speedometer.create!(speedometer_id: "a")
420
+ data = [{ name: "first" }, { name: "second" }]
421
+ speedometer.minivans.where(color: "blue").create!(data)
422
+
423
+ assert_equal 2, speedometer.minivans.size
424
+
425
+ speedometer.reload
426
+
427
+ assert_equal ["first", "second"], speedometer.minivans.map(&:name)
428
+ assert_equal ["blue", "blue"], speedometer.minivans.map(&:color)
324
429
  end
325
430
 
326
431
  def test_association_keys_bypass_attribute_protection
327
- car = Car.create(:name => 'honda')
432
+ car = Car.create(name: "honda")
328
433
 
329
434
  bulb = car.bulbs.new
330
435
  assert_equal car.id, bulb.car_id
331
436
 
332
- bulb = car.bulbs.new :car_id => car.id + 1
437
+ bulb = car.bulbs.new car_id: car.id + 1
333
438
  assert_equal car.id, bulb.car_id
334
439
 
335
440
  bulb = car.bulbs.build
336
441
  assert_equal car.id, bulb.car_id
337
442
 
338
- bulb = car.bulbs.build :car_id => car.id + 1
443
+ bulb = car.bulbs.build car_id: car.id + 1
339
444
  assert_equal car.id, bulb.car_id
340
445
 
341
446
  bulb = car.bulbs.create
342
447
  assert_equal car.id, bulb.car_id
343
448
 
344
- bulb = car.bulbs.create :car_id => car.id + 1
449
+ bulb = car.bulbs.create car_id: car.id + 1
345
450
  assert_equal car.id, bulb.car_id
346
451
  end
347
452
 
@@ -351,22 +456,43 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
351
456
  line_item = invoice.line_items.new
352
457
  assert_equal invoice.id, line_item.invoice_id
353
458
 
354
- line_item = invoice.line_items.new :invoice_id => invoice.id + 1
459
+ line_item = invoice.line_items.new invoice_id: invoice.id + 1
355
460
  assert_equal invoice.id, line_item.invoice_id
356
461
 
357
462
  line_item = invoice.line_items.build
358
463
  assert_equal invoice.id, line_item.invoice_id
359
464
 
360
- line_item = invoice.line_items.build :invoice_id => invoice.id + 1
465
+ line_item = invoice.line_items.build invoice_id: invoice.id + 1
361
466
  assert_equal invoice.id, line_item.invoice_id
362
467
 
363
468
  line_item = invoice.line_items.create
364
469
  assert_equal invoice.id, line_item.invoice_id
365
470
 
366
- line_item = invoice.line_items.create :invoice_id => invoice.id + 1
471
+ line_item = invoice.line_items.create invoice_id: invoice.id + 1
367
472
  assert_equal invoice.id, line_item.invoice_id
368
473
  end
369
474
 
475
+ class SpecialAuthor < ActiveRecord::Base
476
+ self.table_name = "authors"
477
+ has_many :books, class_name: "SpecialBook", foreign_key: :author_id
478
+ end
479
+
480
+ class SpecialBook < ActiveRecord::Base
481
+ self.table_name = "books"
482
+
483
+ belongs_to :author
484
+ enum last_read: { unread: 0, reading: 2, read: 3, forgotten: nil }
485
+ end
486
+
487
+ def test_association_enum_works_properly
488
+ author = SpecialAuthor.create!(name: "Test")
489
+ book = SpecialBook.create!(last_read: "reading")
490
+ author.books << book
491
+
492
+ assert_equal "reading", book.last_read
493
+ assert_not_equal 0, SpecialAuthor.joins(:books).where(books: { last_read: "reading" }).count
494
+ end
495
+
370
496
  # When creating objects on the association, we must not do it within a scope (even though it
371
497
  # would be convenient), because this would cause that scope to be applied to any callbacks etc.
372
498
  def test_build_and_create_should_not_happen_within_scope
@@ -384,64 +510,100 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
384
510
  end
385
511
 
386
512
  def test_no_sql_should_be_fired_if_association_already_loaded
387
- Car.create(:name => 'honda')
513
+ Car.create(name: "honda")
388
514
  bulbs = Car.first.bulbs
389
515
  bulbs.to_a # to load all instances of bulbs
390
516
 
391
517
  assert_no_queries do
392
518
  bulbs.first()
393
- bulbs.first({})
394
519
  end
395
520
 
396
521
  assert_no_queries do
397
522
  bulbs.second()
398
- bulbs.second({})
399
523
  end
400
524
 
401
525
  assert_no_queries do
402
526
  bulbs.third()
403
- bulbs.third({})
404
527
  end
405
528
 
406
529
  assert_no_queries do
407
530
  bulbs.fourth()
408
- bulbs.fourth({})
409
531
  end
410
532
 
411
533
  assert_no_queries do
412
534
  bulbs.fifth()
413
- bulbs.fifth({})
414
535
  end
415
536
 
416
537
  assert_no_queries do
417
538
  bulbs.forty_two()
418
- bulbs.forty_two({})
419
539
  end
420
540
 
421
541
  assert_no_queries do
422
542
  bulbs.third_to_last()
423
- bulbs.third_to_last({})
424
543
  end
425
544
 
426
545
  assert_no_queries do
427
546
  bulbs.second_to_last()
428
- bulbs.second_to_last({})
429
547
  end
430
548
 
431
549
  assert_no_queries do
432
550
  bulbs.last()
433
- bulbs.last({})
551
+ end
552
+ end
553
+
554
+ def test_finder_method_with_dirty_target
555
+ company = companies(:first_firm)
556
+ new_clients = []
557
+
558
+ assert_queries(0) do
559
+ new_clients << company.clients_of_firm.build(name: "Another Client")
560
+ new_clients << company.clients_of_firm.build(name: "Another Client II")
561
+ new_clients << company.clients_of_firm.build(name: "Another Client III")
562
+ end
563
+
564
+ assert_not_predicate company.clients_of_firm, :loaded?
565
+ assert_queries(1) do
566
+ assert_same new_clients[0], company.clients_of_firm.third
567
+ assert_same new_clients[1], company.clients_of_firm.fourth
568
+ assert_same new_clients[2], company.clients_of_firm.fifth
569
+ assert_same new_clients[0], company.clients_of_firm.third_to_last
570
+ assert_same new_clients[1], company.clients_of_firm.second_to_last
571
+ assert_same new_clients[2], company.clients_of_firm.last
572
+ end
573
+ end
574
+
575
+ def test_finder_bang_method_with_dirty_target
576
+ company = companies(:first_firm)
577
+ new_clients = []
578
+
579
+ assert_queries(0) do
580
+ new_clients << company.clients_of_firm.build(name: "Another Client")
581
+ new_clients << company.clients_of_firm.build(name: "Another Client II")
582
+ new_clients << company.clients_of_firm.build(name: "Another Client III")
583
+ end
584
+
585
+ assert_not_predicate company.clients_of_firm, :loaded?
586
+ assert_queries(1) do
587
+ assert_same new_clients[0], company.clients_of_firm.third!
588
+ assert_same new_clients[1], company.clients_of_firm.fourth!
589
+ assert_same new_clients[2], company.clients_of_firm.fifth!
590
+ assert_same new_clients[0], company.clients_of_firm.third_to_last!
591
+ assert_same new_clients[1], company.clients_of_firm.second_to_last!
592
+ assert_same new_clients[2], company.clients_of_firm.last!
434
593
  end
435
594
  end
436
595
 
437
596
  def test_create_resets_cached_counters
438
- person = Person.create!(:first_name => 'tenderlove')
597
+ Reader.delete_all
598
+
599
+ person = Person.create!(first_name: "tenderlove")
600
+
439
601
  post = Post.first
440
602
 
441
603
  assert_equal [], person.readers
442
604
  assert_nil person.readers.find_by_post_id(post.id)
443
605
 
444
- person.readers.create(:post_id => post.id)
606
+ person.readers.create(post_id: post.id)
445
607
 
446
608
  assert_equal 1, person.readers.count
447
609
  assert_equal 1, person.readers.length
@@ -451,43 +613,34 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
451
613
 
452
614
  def test_update_all_respects_association_scope
453
615
  person = Person.new
454
- person.first_name = 'Naruto'
616
+ person.first_name = "Naruto"
455
617
  person.references << Reference.new
456
- person.id = 10
457
- person.references
458
618
  person.save!
459
619
  assert_equal 1, person.references.update_all(favourite: true)
460
620
  end
461
621
 
462
622
  def test_exists_respects_association_scope
463
623
  person = Person.new
464
- person.first_name = 'Sasuke'
624
+ person.first_name = "Sasuke"
465
625
  person.references << Reference.new
466
- person.id = 10
467
- person.references
468
626
  person.save!
469
627
  assert_predicate person.references, :exists?
470
628
  end
471
629
 
472
- def force_signal37_to_load_all_clients_of_firm
473
- companies(:first_firm).clients_of_firm.each {|f| }
474
- end
475
-
476
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
477
630
  def test_counting_with_counter_sql
478
- assert_equal 3, Firm.all.merge!(:order => "id").first.clients.count
631
+ assert_equal 3, Firm.first.clients.count
479
632
  end
480
633
 
481
634
  def test_counting
482
- assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count
635
+ assert_equal 3, Firm.first.plain_clients.count
483
636
  end
484
637
 
485
638
  def test_counting_with_single_hash
486
- assert_equal 1, Firm.all.merge!(:order => "id").first.plain_clients.where(:name => "Microsoft").count
639
+ assert_equal 1, Firm.first.plain_clients.where(name: "Microsoft").count
487
640
  end
488
641
 
489
642
  def test_counting_with_column_name_and_hash
490
- assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
643
+ assert_equal 3, Firm.first.plain_clients.count(:name)
491
644
  end
492
645
 
493
646
  def test_counting_with_association_limit
@@ -497,11 +650,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
497
650
  end
498
651
 
499
652
  def test_finding
500
- assert_equal 3, Firm.all.merge!(:order => "id").first.clients.length
653
+ assert_equal 3, Firm.first.clients.length
501
654
  end
502
655
 
503
656
  def test_finding_array_compatibility
504
- assert_equal 3, Firm.order(:id).find{|f| f.id > 0}.clients.length
657
+ assert_equal 3, Firm.order(:id).find { |f| f.id > 0 }.clients.length
505
658
  end
506
659
 
507
660
  def test_find_many_with_merged_options
@@ -511,13 +664,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
511
664
  end
512
665
 
513
666
  def test_find_should_append_to_association_order
514
- ordered_clients = companies(:first_firm).clients_sorted_desc.order('companies.id')
515
- assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
667
+ ordered_clients = companies(:first_firm).clients_sorted_desc.order("companies.id")
668
+ assert_equal ["id DESC", "companies.id"], ordered_clients.order_values
516
669
  end
517
670
 
518
671
  def test_dynamic_find_should_respect_association_order
519
672
  assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
520
- assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
673
+ assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type("Client")
521
674
  end
522
675
 
523
676
  def test_taking
@@ -537,16 +690,28 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
537
690
  end
538
691
 
539
692
  def test_taking_with_a_number
693
+ klass = Class.new(Author) do
694
+ has_many :posts, -> { order(:id) }
695
+
696
+ def self.name
697
+ "Author"
698
+ end
699
+ end
700
+
540
701
  # taking from unloaded Relation
541
- bob = Author.find(authors(:bob).id)
702
+ bob = klass.find(authors(:bob).id)
703
+ new_post = bob.posts.build
704
+ assert_not_predicate bob.posts, :loaded?
542
705
  assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
543
- bob = Author.find(authors(:bob).id)
544
706
  assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
707
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob), new_post], bob.posts.take(3)
545
708
 
546
709
  # taking from loaded Relation
547
- bob.posts.to_a
548
- assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
549
- assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
710
+ bob.posts.load
711
+ assert_predicate bob.posts, :loaded?
712
+ assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
713
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
714
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob), new_post], bob.posts.take(3)
550
715
  end
551
716
 
552
717
  def test_taking_with_inverse_of
@@ -565,27 +730,27 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
565
730
  end
566
731
 
567
732
  def test_finding_default_orders
568
- assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients.first.name
733
+ assert_equal "Summit", Firm.first.clients.first.name
569
734
  end
570
735
 
571
736
  def test_finding_with_different_class_name_and_order
572
- assert_equal "Apex", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
737
+ assert_equal "Apex", Firm.first.clients_sorted_desc.first.name
573
738
  end
574
739
 
575
740
  def test_finding_with_foreign_key
576
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_of_firm.first.name
741
+ assert_equal "Microsoft", Firm.first.clients_of_firm.first.name
577
742
  end
578
743
 
579
744
  def test_finding_with_condition
580
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms.first.name
745
+ assert_equal "Microsoft", Firm.first.clients_like_ms.first.name
581
746
  end
582
747
 
583
748
  def test_finding_with_condition_hash
584
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
749
+ assert_equal "Microsoft", Firm.first.clients_like_ms_with_hash_conditions.first.name
585
750
  end
586
751
 
587
752
  def test_finding_using_primary_key
588
- assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients_using_primary_key.first.name
753
+ assert_equal "Summit", Firm.first.clients_using_primary_key.first.name
589
754
  end
590
755
 
591
756
  def test_update_all_on_association_accessed_before_save
@@ -608,7 +773,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
608
773
  end
609
774
 
610
775
  def test_find_ids
611
- firm = Firm.all.merge!(:order => "id").first
776
+ firm = Firm.first
612
777
 
613
778
  assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
614
779
 
@@ -628,7 +793,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
628
793
  end
629
794
 
630
795
  def test_find_one_message_on_primary_key
631
- firm = Firm.all.merge!(order: "id").first
796
+ firm = Firm.first
632
797
 
633
798
  e = assert_raises(ActiveRecord::RecordNotFound) do
634
799
  firm.clients.find(0)
@@ -642,6 +807,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
642
807
  def test_find_ids_and_inverse_of
643
808
  force_signal37_to_load_all_clients_of_firm
644
809
 
810
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
811
+
645
812
  firm = companies(:first_firm)
646
813
  client = firm.clients_of_firm.find(3)
647
814
  assert_kind_of Client, client
@@ -652,7 +819,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
652
819
  end
653
820
 
654
821
  def test_find_all
655
- firm = Firm.all.merge!(:order => "id").first
822
+ firm = Firm.first
656
823
  assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
657
824
  assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
658
825
  end
@@ -660,67 +827,143 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
660
827
  def test_find_each
661
828
  firm = companies(:first_firm)
662
829
 
663
- assert ! firm.clients.loaded?
830
+ assert_not_predicate firm.clients, :loaded?
664
831
 
665
832
  assert_queries(4) do
666
- firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
833
+ firm.clients.find_each(batch_size: 1) { |c| assert_equal firm.id, c.firm_id }
667
834
  end
668
835
 
669
- assert ! firm.clients.loaded?
836
+ assert_not_predicate firm.clients, :loaded?
670
837
  end
671
838
 
672
839
  def test_find_each_with_conditions
673
840
  firm = companies(:first_firm)
674
841
 
675
842
  assert_queries(2) do
676
- firm.clients.where(name: 'Microsoft').find_each(batch_size: 1) do |c|
843
+ firm.clients.where(name: "Microsoft").find_each(batch_size: 1) do |c|
677
844
  assert_equal firm.id, c.firm_id
678
845
  assert_equal "Microsoft", c.name
679
846
  end
680
847
  end
681
848
 
682
- assert ! firm.clients.loaded?
849
+ assert_not_predicate firm.clients, :loaded?
683
850
  end
684
851
 
685
852
  def test_find_in_batches
686
853
  firm = companies(:first_firm)
687
854
 
688
- assert ! firm.clients.loaded?
855
+ assert_not_predicate firm.clients, :loaded?
689
856
 
690
857
  assert_queries(2) do
691
- firm.clients.find_in_batches(:batch_size => 2) do |clients|
692
- clients.each {|c| assert_equal firm.id, c.firm_id }
858
+ firm.clients.find_in_batches(batch_size: 2) do |clients|
859
+ clients.each { |c| assert_equal firm.id, c.firm_id }
693
860
  end
694
861
  end
695
862
 
696
- assert ! firm.clients.loaded?
863
+ assert_not_predicate firm.clients, :loaded?
697
864
  end
698
865
 
699
866
  def test_find_all_sanitized
700
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
701
- firm = Firm.all.merge!(:order => "id").first
867
+ firm = Firm.first
702
868
  summit = firm.clients.where("name = 'Summit'").to_a
703
869
  assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
704
- assert_equal summit, firm.clients.where("name = :name", { :name => "Summit" }).to_a
870
+ assert_equal summit, firm.clients.where("name = :name", name: "Summit").to_a
705
871
  end
706
872
 
707
873
  def test_find_first
708
- firm = Firm.all.merge!(:order => "id").first
874
+ firm = Firm.first
709
875
  client2 = Client.find(2)
710
876
  assert_equal firm.clients.first, firm.clients.order("id").first
711
877
  assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first
712
878
  end
713
879
 
714
880
  def test_find_first_sanitized
715
- firm = Firm.all.merge!(:order => "id").first
881
+ firm = Firm.first
716
882
  client2 = Client.find(2)
717
- assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
718
- assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
883
+ assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = ?", "Client").first
884
+ assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = :type", type: "Client").first
885
+ end
886
+
887
+ def test_find_first_after_reset_scope
888
+ firm = Firm.first
889
+ collection = firm.clients
890
+
891
+ original_object = collection.first
892
+ assert_same original_object, collection.first, "Expected second call to #first to cache the same object"
893
+
894
+ # It should return a different object, since the association has been reloaded
895
+ assert_not_same original_object, firm.clients.first, "Expected #first to return a new object"
896
+ end
897
+
898
+ def test_find_first_after_reset
899
+ firm = Firm.first
900
+ collection = firm.clients
901
+
902
+ original_object = collection.first
903
+ assert_same original_object, collection.first, "Expected second call to #first to cache the same object"
904
+ collection.reset
905
+
906
+ # It should return a different object, since the association has been reloaded
907
+ assert_not_same original_object, collection.first, "Expected #first after #reset to return a new object"
908
+ end
909
+
910
+ def test_find_first_after_reload
911
+ firm = Firm.first
912
+ collection = firm.clients
913
+
914
+ original_object = collection.first
915
+ assert_same original_object, collection.first, "Expected second call to #first to cache the same object"
916
+ collection.reload
917
+
918
+ # It should return a different object, since the association has been reloaded
919
+ assert_not_same original_object, collection.first, "Expected #first after #reload to return a new object"
920
+ end
921
+
922
+ def test_reload_with_query_cache
923
+ connection = ActiveRecord::Base.connection
924
+ connection.enable_query_cache!
925
+ connection.clear_query_cache
926
+
927
+ # Populate the cache with a query
928
+ firm = Firm.first
929
+ # Populate the cache with a second query
930
+ firm.clients.load
931
+
932
+ assert_equal 2, connection.query_cache.size
933
+
934
+ # Clear the cache and fetch the clients again, populating the cache with a query
935
+ assert_queries(1) { firm.clients.reload }
936
+ # This query is cached, so it shouldn't make a real SQL query
937
+ assert_queries(0) { firm.clients.load }
938
+
939
+ assert_equal 1, connection.query_cache.size
940
+ ensure
941
+ ActiveRecord::Base.connection.disable_query_cache!
942
+ end
943
+
944
+ def test_reloading_unloaded_associations_with_query_cache
945
+ connection = ActiveRecord::Base.connection
946
+ connection.enable_query_cache!
947
+ connection.clear_query_cache
948
+
949
+ firm = Firm.create!(name: "firm name")
950
+ client = firm.clients.create!(name: "client name")
951
+ firm.clients.to_a # add request to cache
952
+
953
+ connection.uncached do
954
+ client.update!(name: "new client name")
955
+ end
956
+
957
+ firm = Firm.find(firm.id)
958
+
959
+ assert_equal [client.name], firm.clients.reload.map(&:name)
960
+ ensure
961
+ ActiveRecord::Base.connection.disable_query_cache!
719
962
  end
720
963
 
721
964
  def test_find_all_with_include_and_conditions
722
965
  assert_nothing_raised do
723
- Developer.all.merge!(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).to_a
966
+ Developer.all.merge!(joins: :audit_logs, where: { "audit_logs.message" => nil, :name => "Smith" }).to_a
724
967
  end
725
968
  end
726
969
 
@@ -730,8 +973,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
730
973
  end
731
974
 
732
975
  def test_find_grouped
733
- all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
734
- grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
976
+ all_clients_of_firm1 = Client.all.merge!(where: "firm_id = 1").to_a
977
+ grouped_clients_of_firm1 = Client.all.merge!(where: "firm_id = 1", group: "firm_id", select: "firm_id, count(id) as clients_count").to_a
735
978
  assert_equal 3, all_clients_of_firm1.size
736
979
  assert_equal 1, grouped_clients_of_firm1.size
737
980
  end
@@ -744,7 +987,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
744
987
  end
745
988
 
746
989
  def test_find_scoped_grouped_having
747
- assert_equal 1, authors(:david).popular_grouped_posts.length
990
+ assert_equal 2, authors(:david).popular_grouped_posts.length
748
991
  assert_equal 0, authors(:mary).popular_grouped_posts.length
749
992
  end
750
993
 
@@ -753,19 +996,28 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
753
996
  end
754
997
 
755
998
  def test_select_query_method
756
- assert_equal ['id', 'body'], posts(:welcome).comments.select(:id, :body).first.attributes.keys
999
+ assert_equal ["id", "body"], posts(:welcome).comments.select(:id, :body).first.attributes.keys
757
1000
  end
758
1001
 
759
1002
  def test_select_with_block
760
1003
  assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
761
1004
  end
762
1005
 
1006
+ def test_select_with_block_and_dirty_target
1007
+ assert_equal 2, posts(:welcome).comments.select { true }.size
1008
+ posts(:welcome).comments.build
1009
+ assert_equal 3, posts(:welcome).comments.select { true }.size
1010
+ end
1011
+
763
1012
  def test_select_without_foreign_key
764
1013
  assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit
765
1014
  end
766
1015
 
767
1016
  def test_adding
768
1017
  force_signal37_to_load_all_clients_of_firm
1018
+
1019
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1020
+
769
1021
  natural = Client.new("name" => "Natural Company")
770
1022
  companies(:first_firm).clients_of_firm << natural
771
1023
  assert_equal 3, companies(:first_firm).clients_of_firm.size # checking via the collection
@@ -776,7 +1028,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
776
1028
  def test_adding_using_create
777
1029
  first_firm = companies(:first_firm)
778
1030
  assert_equal 3, first_firm.plain_clients.size
779
- first_firm.plain_clients.create(:name => "Natural Company")
1031
+ first_firm.plain_clients.create(name: "Natural Company")
780
1032
  assert_equal 4, first_firm.plain_clients.length
781
1033
  assert_equal 4, first_firm.plain_clients.size
782
1034
  end
@@ -784,7 +1036,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
784
1036
  def test_create_with_bang_on_has_many_when_parent_is_new_raises
785
1037
  error = assert_raise(ActiveRecord::RecordNotSaved) do
786
1038
  firm = Firm.new
787
- firm.plain_clients.create! :name=>"Whoever"
1039
+ firm.plain_clients.create! name: "Whoever"
788
1040
  end
789
1041
 
790
1042
  assert_equal "You cannot call create unless the parent is saved", error.message
@@ -793,7 +1045,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
793
1045
  def test_regular_create_on_has_many_when_parent_is_new_raises
794
1046
  error = assert_raise(ActiveRecord::RecordNotSaved) do
795
1047
  firm = Firm.new
796
- firm.plain_clients.create :name=>"Whoever"
1048
+ firm.plain_clients.create name: "Whoever"
797
1049
  end
798
1050
 
799
1051
  assert_equal "You cannot call create unless the parent is saved", error.message
@@ -801,7 +1053,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
801
1053
 
802
1054
  def test_create_with_bang_on_has_many_raises_when_record_not_saved
803
1055
  assert_raise(ActiveRecord::RecordInvalid) do
804
- firm = Firm.all.merge!(:order => "id").first
1056
+ firm = Firm.first
805
1057
  firm.plain_clients.create!
806
1058
  end
807
1059
  end
@@ -822,26 +1074,30 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
822
1074
 
823
1075
  def test_adding_a_collection
824
1076
  force_signal37_to_load_all_clients_of_firm
825
- companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
1077
+
1078
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1079
+
1080
+ result = companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
826
1081
  assert_equal 4, companies(:first_firm).clients_of_firm.size
827
1082
  assert_equal 4, companies(:first_firm).clients_of_firm.reload.size
1083
+ assert_equal companies(:first_firm).clients_of_firm, result
828
1084
  end
829
1085
 
830
1086
  def test_transactions_when_adding_to_persisted
831
- good = Client.new(:name => "Good")
832
- bad = Client.new(:name => "Bad", :raise_on_save => true)
1087
+ good = Client.new(name: "Good")
1088
+ bad = Client.new(name: "Bad", raise_on_save: true)
833
1089
 
834
1090
  begin
835
1091
  companies(:first_firm).clients_of_firm.concat(good, bad)
836
1092
  rescue Client::RaisedOnSave
837
1093
  end
838
1094
 
839
- assert !companies(:first_firm).clients_of_firm.reload.include?(good)
1095
+ assert_not_includes companies(:first_firm).clients_of_firm.reload, good
840
1096
  end
841
1097
 
842
1098
  def test_transactions_when_adding_to_new_record
843
- assert_no_queries(ignore_none: false) do
844
- firm = Firm.new
1099
+ firm = Firm.new
1100
+ assert_queries(0) do
845
1101
  firm.clients_of_firm.concat(Client.new("name" => "Natural Company"))
846
1102
  end
847
1103
  end
@@ -855,21 +1111,23 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
855
1111
 
856
1112
  def test_new_aliased_to_build
857
1113
  company = companies(:first_firm)
858
- new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.new("name" => "Another Client") }
859
- assert !company.clients_of_firm.loaded?
1114
+
1115
+ new_client = assert_queries(0) { company.clients_of_firm.new("name" => "Another Client") }
1116
+ assert_not_predicate company.clients_of_firm, :loaded?
860
1117
 
861
1118
  assert_equal "Another Client", new_client.name
862
- assert !new_client.persisted?
1119
+ assert_not_predicate new_client, :persisted?
863
1120
  assert_equal new_client, company.clients_of_firm.last
864
1121
  end
865
1122
 
866
1123
  def test_build
867
1124
  company = companies(:first_firm)
868
- new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
869
- assert !company.clients_of_firm.loaded?
1125
+
1126
+ new_client = assert_queries(0) { company.clients_of_firm.build("name" => "Another Client") }
1127
+ assert_not_predicate company.clients_of_firm, :loaded?
870
1128
 
871
1129
  assert_equal "Another Client", new_client.name
872
- assert !new_client.persisted?
1130
+ assert_not_predicate new_client, :persisted?
873
1131
  assert_equal new_client, company.clients_of_firm.last
874
1132
  end
875
1133
 
@@ -878,13 +1136,34 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
878
1136
  company.clients_of_firm.build("name" => "Another Client")
879
1137
  company.clients_of_firm.build("name" => "Yet Another Client")
880
1138
  assert_equal 4, company.clients_of_firm.size
1139
+ assert_equal 4, company.clients_of_firm.uniq.size
881
1140
  end
882
1141
 
883
1142
  def test_collection_not_empty_after_building
884
1143
  company = companies(:first_firm)
885
- assert_predicate company.contracts, :empty?
1144
+ assert_empty company.contracts
886
1145
  company.contracts.build
887
- assert_not_predicate company.contracts, :empty?
1146
+ assert_not_empty company.contracts
1147
+ end
1148
+
1149
+ def test_collection_size_with_dirty_target
1150
+ post = posts(:thinking)
1151
+ assert_equal [], post.reader_ids
1152
+ assert_equal 0, post.readers.size
1153
+ post.readers.reset
1154
+ post.readers.build
1155
+ assert_equal [nil], post.reader_ids
1156
+ assert_equal 1, post.readers.size
1157
+ end
1158
+
1159
+ def test_collection_empty_with_dirty_target
1160
+ post = posts(:thinking)
1161
+ assert_equal [], post.reader_ids
1162
+ assert_empty post.readers
1163
+ post.readers.reset
1164
+ post.readers.build
1165
+ assert_equal [nil], post.reader_ids
1166
+ assert_not_empty post.readers
888
1167
  end
889
1168
 
890
1169
  def test_collection_size_twice_for_regressions
@@ -901,24 +1180,24 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
901
1180
 
902
1181
  def test_build_many
903
1182
  company = companies(:first_firm)
904
- new_clients = assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
1183
+
1184
+ new_clients = assert_queries(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
905
1185
  assert_equal 2, new_clients.size
906
1186
  end
907
1187
 
908
1188
  def test_build_followed_by_save_does_not_load_target
909
1189
  companies(:first_firm).clients_of_firm.build("name" => "Another Client")
910
1190
  assert companies(:first_firm).save
911
- assert !companies(:first_firm).clients_of_firm.loaded?
1191
+ assert_not_predicate companies(:first_firm).clients_of_firm, :loaded?
912
1192
  end
913
1193
 
914
1194
  def test_build_without_loading_association
915
1195
  first_topic = topics(:first)
916
- Reply.column_names
917
1196
 
918
1197
  assert_equal 1, first_topic.replies.length
919
1198
 
920
- assert_no_queries do
921
- first_topic.replies.build(:title => "Not saved", :content => "Superstars")
1199
+ assert_queries(0) do
1200
+ first_topic.replies.build(title: "Not saved", content: "Superstars")
922
1201
  assert_equal 2, first_topic.replies.size
923
1202
  end
924
1203
 
@@ -927,18 +1206,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
927
1206
 
928
1207
  def test_build_via_block
929
1208
  company = companies(:first_firm)
930
- new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
931
- assert !company.clients_of_firm.loaded?
1209
+
1210
+ new_client = assert_queries(0) { company.clients_of_firm.build { |client| client.name = "Another Client" } }
1211
+ assert_not_predicate company.clients_of_firm, :loaded?
932
1212
 
933
1213
  assert_equal "Another Client", new_client.name
934
- assert !new_client.persisted?
1214
+ assert_not_predicate new_client, :persisted?
935
1215
  assert_equal new_client, company.clients_of_firm.last
936
1216
  end
937
1217
 
938
1218
  def test_build_many_via_block
939
1219
  company = companies(:first_firm)
940
- new_clients = assert_no_queries(ignore_none: false) do
941
- company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
1220
+
1221
+ new_clients = assert_queries(0) do
1222
+ company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) do |client|
942
1223
  client.name = "changed"
943
1224
  end
944
1225
  end
@@ -949,15 +1230,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
949
1230
  end
950
1231
 
951
1232
  def test_create_without_loading_association
952
- first_firm = companies(:first_firm)
953
- Firm.column_names
954
- Client.column_names
1233
+ first_firm = companies(:first_firm)
955
1234
 
956
1235
  assert_equal 2, first_firm.clients_of_firm.size
957
1236
  first_firm.clients_of_firm.reset
958
1237
 
959
1238
  assert_queries(1) do
960
- first_firm.clients_of_firm.create(:name => "Superstars")
1239
+ first_firm.clients_of_firm.create(name: "Superstars")
961
1240
  end
962
1241
 
963
1242
  assert_equal 3, first_firm.clients_of_firm.size
@@ -965,25 +1244,31 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
965
1244
 
966
1245
  def test_create
967
1246
  force_signal37_to_load_all_clients_of_firm
1247
+
1248
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1249
+
968
1250
  new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
969
- assert new_client.persisted?
1251
+ assert_predicate new_client, :persisted?
970
1252
  assert_equal new_client, companies(:first_firm).clients_of_firm.last
971
1253
  assert_equal new_client, companies(:first_firm).clients_of_firm.reload.last
972
1254
  end
973
1255
 
974
1256
  def test_create_many
975
- companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
1257
+ companies(:first_firm).clients_of_firm.create([{ "name" => "Another Client" }, { "name" => "Another Client II" }])
976
1258
  assert_equal 4, companies(:first_firm).clients_of_firm.reload.size
977
1259
  end
978
1260
 
979
1261
  def test_create_followed_by_save_does_not_load_target
980
1262
  companies(:first_firm).clients_of_firm.create("name" => "Another Client")
981
1263
  assert companies(:first_firm).save
982
- assert !companies(:first_firm).clients_of_firm.loaded?
1264
+ assert_not_predicate companies(:first_firm).clients_of_firm, :loaded?
983
1265
  end
984
1266
 
985
1267
  def test_deleting
986
1268
  force_signal37_to_load_all_clients_of_firm
1269
+
1270
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1271
+
987
1272
  companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
988
1273
  assert_equal 1, companies(:first_firm).clients_of_firm.size
989
1274
  assert_equal 1, companies(:first_firm).clients_of_firm.reload.size
@@ -1000,15 +1285,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1000
1285
  def test_has_many_without_counter_cache_option
1001
1286
  # Ship has a conventionally named `treasures_count` column, but the counter_cache
1002
1287
  # option is not given on the association.
1003
- ship = Ship.create(name: 'Countless', treasures_count: 10)
1288
+ ship = Ship.create!(name: "Countless", treasures_count: 10)
1004
1289
 
1005
- assert_not Ship.reflect_on_association(:treasures).has_cached_counter?
1290
+ assert_not_predicate Ship.reflect_on_association(:treasures), :has_cached_counter?
1006
1291
 
1007
1292
  # Count should come from sql count() of treasures rather than treasures_count attribute
1008
1293
  assert_equal ship.treasures.size, 0
1009
1294
 
1010
1295
  assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
1011
- ship.treasures.create(name: 'Gold')
1296
+ ship.treasures.create(name: "Gold")
1012
1297
  end
1013
1298
 
1014
1299
  assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
@@ -1055,6 +1340,38 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1055
1340
  assert_equal 2, topic.reload.replies.size
1056
1341
  end
1057
1342
 
1343
+ def test_counter_cache_updates_in_memory_after_update_with_inverse_of_disabled
1344
+ topic = Topic.create!(title: "Zoom-zoom-zoom")
1345
+
1346
+ assert_equal 0, topic.replies_count
1347
+
1348
+ reply1 = Reply.create!(title: "re: zoom", content: "speedy quick!")
1349
+ reply2 = Reply.create!(title: "re: zoom 2", content: "OMG lol!")
1350
+
1351
+ assert_queries(4) do
1352
+ topic.replies << [reply1, reply2]
1353
+ end
1354
+
1355
+ assert_equal 2, topic.replies_count
1356
+ assert_equal 2, topic.reload.replies_count
1357
+ end
1358
+
1359
+ def test_counter_cache_updates_in_memory_after_update_with_inverse_of_enabled
1360
+ category = Category.create!(name: "Counter Cache")
1361
+
1362
+ assert_nil category.categorizations_count
1363
+
1364
+ categorization1 = Categorization.create!
1365
+ categorization2 = Categorization.create!
1366
+
1367
+ assert_queries(4) do
1368
+ category.categorizations << [categorization1, categorization2]
1369
+ end
1370
+
1371
+ assert_equal 2, category.categorizations_count
1372
+ assert_equal 2, category.reload.categorizations_count
1373
+ end
1374
+
1058
1375
  def test_pushing_association_updates_counter_cache
1059
1376
  topic = Topic.order("id ASC").first
1060
1377
  reply = Reply.create!
@@ -1092,8 +1409,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1092
1409
 
1093
1410
  def test_calling_empty_with_counter_cache
1094
1411
  post = posts(:welcome)
1095
- assert_queries(0) do
1096
- assert_not post.comments.empty?
1412
+ assert_no_queries do
1413
+ assert_not_empty post.comments
1097
1414
  end
1098
1415
  end
1099
1416
 
@@ -1105,20 +1422,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1105
1422
  end
1106
1423
  end
1107
1424
 
1108
- def test_calling_update_attributes_on_id_changes_the_counter_cache
1425
+ def test_calling_update_on_id_changes_the_counter_cache
1109
1426
  topic = Topic.order("id ASC").first
1110
1427
  original_count = topic.replies.to_a.size
1111
1428
  assert_equal original_count, topic.replies_count
1112
1429
 
1113
1430
  first_reply = topic.replies.first
1114
- first_reply.update_attributes(:parent_id => nil)
1431
+ first_reply.update(parent_id: nil)
1115
1432
  assert_equal original_count - 1, topic.reload.replies_count
1116
1433
 
1117
- first_reply.update_attributes(:parent_id => topic.id)
1434
+ first_reply.update(parent_id: topic.id)
1118
1435
  assert_equal original_count, topic.reload.replies_count
1119
1436
  end
1120
1437
 
1121
- def test_calling_update_attributes_changing_ids_doesnt_change_counter_cache
1438
+ def test_calling_update_changing_ids_doesnt_change_counter_cache
1122
1439
  topic1 = Topic.find(1)
1123
1440
  topic2 = Topic.find(3)
1124
1441
  original_count1 = topic1.replies.to_a.size
@@ -1127,17 +1444,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1127
1444
  reply1 = topic1.replies.first
1128
1445
  reply2 = topic2.replies.first
1129
1446
 
1130
- reply1.update_attributes(:parent_id => topic2.id)
1447
+ reply1.update(parent_id: topic2.id)
1131
1448
  assert_equal original_count1 - 1, topic1.reload.replies_count
1132
1449
  assert_equal original_count2 + 1, topic2.reload.replies_count
1133
1450
 
1134
- reply2.update_attributes(:parent_id => topic1.id)
1451
+ reply2.update(parent_id: topic1.id)
1135
1452
  assert_equal original_count1, topic1.reload.replies_count
1136
1453
  assert_equal original_count2, topic2.reload.replies_count
1137
1454
  end
1138
1455
 
1139
1456
  def test_deleting_a_collection
1140
1457
  force_signal37_to_load_all_clients_of_firm
1458
+
1459
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1460
+
1141
1461
  companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1142
1462
  assert_equal 3, companies(:first_firm).clients_of_firm.size
1143
1463
  companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1], companies(:first_firm).clients_of_firm[2]])
@@ -1147,17 +1467,23 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1147
1467
 
1148
1468
  def test_delete_all
1149
1469
  force_signal37_to_load_all_clients_of_firm
1470
+
1471
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1472
+
1150
1473
  companies(:first_firm).dependent_clients_of_firm.create("name" => "Another Client")
1151
1474
  clients = companies(:first_firm).dependent_clients_of_firm.to_a
1152
1475
  assert_equal 3, clients.count
1153
1476
 
1154
1477
  assert_difference "Client.count", -(clients.count) do
1155
- companies(:first_firm).dependent_clients_of_firm.delete_all
1478
+ assert_equal clients.count, companies(:first_firm).dependent_clients_of_firm.delete_all
1156
1479
  end
1157
1480
  end
1158
1481
 
1159
1482
  def test_delete_all_with_not_yet_loaded_association_collection
1160
1483
  force_signal37_to_load_all_clients_of_firm
1484
+
1485
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1486
+
1161
1487
  companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1162
1488
  assert_equal 3, companies(:first_firm).clients_of_firm.size
1163
1489
  companies(:first_firm).clients_of_firm.reset
@@ -1167,8 +1493,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1167
1493
  end
1168
1494
 
1169
1495
  def test_transaction_when_deleting_persisted
1170
- good = Client.new(:name => "Good")
1171
- bad = Client.new(:name => "Bad", :raise_on_destroy => true)
1496
+ good = Client.new(name: "Good")
1497
+ bad = Client.new(name: "Bad", raise_on_destroy: true)
1172
1498
 
1173
1499
  companies(:first_firm).clients_of_firm = [good, bad]
1174
1500
 
@@ -1181,8 +1507,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1181
1507
  end
1182
1508
 
1183
1509
  def test_transaction_when_deleting_new_record
1184
- assert_no_queries(ignore_none: false) do
1185
- firm = Firm.new
1510
+ firm = Firm.new
1511
+ assert_queries(0) do
1186
1512
  client = Client.new("name" => "New Client")
1187
1513
  firm.clients_of_firm << client
1188
1514
  firm.clients_of_firm.destroy(client)
@@ -1209,7 +1535,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1209
1535
  def test_clearing_updates_counter_cache
1210
1536
  topic = Topic.first
1211
1537
 
1212
- assert_difference 'topic.reload.replies_count', -1 do
1538
+ assert_difference "topic.reload.replies_count", -1 do
1213
1539
  topic.replies.clear
1214
1540
  end
1215
1541
  end
@@ -1218,7 +1544,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1218
1544
  car = Car.first
1219
1545
  car.engines.create!
1220
1546
 
1221
- assert_difference 'car.reload.engines_count', -1 do
1547
+ assert_difference "car.reload.engines_count", -1 do
1222
1548
  car.engines.clear
1223
1549
  end
1224
1550
  end
@@ -1243,10 +1569,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1243
1569
  def test_delete_all_with_option_delete_all
1244
1570
  firm = companies(:first_firm)
1245
1571
  client_id = firm.dependent_clients_of_firm.first.id
1246
- firm.dependent_clients_of_firm.delete_all(:delete_all)
1572
+ count = firm.dependent_clients_of_firm.count
1573
+ assert_equal count, firm.dependent_clients_of_firm.delete_all(:delete_all)
1247
1574
  assert_nil Client.find_by_id(client_id)
1248
1575
  end
1249
1576
 
1577
+ def test_delete_all_with_option_nullify
1578
+ firm = companies(:first_firm)
1579
+ client_id = firm.dependent_clients_of_firm.first.id
1580
+ count = firm.dependent_clients_of_firm.count
1581
+ assert_equal firm, Client.find(client_id).firm
1582
+ assert_equal count, firm.dependent_clients_of_firm.delete_all(:nullify)
1583
+ assert_nil Client.find(client_id).firm
1584
+ end
1585
+
1250
1586
  def test_delete_all_accepts_limited_parameters
1251
1587
  firm = companies(:first_firm)
1252
1588
  assert_raise(ArgumentError) do
@@ -1276,8 +1612,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1276
1612
 
1277
1613
  def test_dependent_association_respects_optional_conditions_on_delete
1278
1614
  firm = companies(:odegy)
1279
- Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1280
- Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1615
+ Client.create(client_of: firm.id, name: "BigShot Inc.")
1616
+ Client.create(client_of: firm.id, name: "SmallTime Inc.")
1281
1617
  # only one of two clients is included in the association due to the :conditions key
1282
1618
  assert_equal 2, Client.where(client_of: firm.id).size
1283
1619
  assert_equal 1, firm.dependent_conditional_clients_of_firm.size
@@ -1288,8 +1624,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1288
1624
 
1289
1625
  def test_dependent_association_respects_optional_sanitized_conditions_on_delete
1290
1626
  firm = companies(:odegy)
1291
- Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1292
- Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1627
+ Client.create(client_of: firm.id, name: "BigShot Inc.")
1628
+ Client.create(client_of: firm.id, name: "SmallTime Inc.")
1293
1629
  # only one of two clients is included in the association due to the :conditions key
1294
1630
  assert_equal 2, Client.where(client_of: firm.id).size
1295
1631
  assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
@@ -1300,11 +1636,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1300
1636
 
1301
1637
  def test_dependent_association_respects_optional_hash_conditions_on_delete
1302
1638
  firm = companies(:odegy)
1303
- Client.create(:client_of => firm.id, :name => "BigShot Inc.")
1304
- Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
1639
+ Client.create(client_of: firm.id, name: "BigShot Inc.")
1640
+ Client.create(client_of: firm.id, name: "SmallTime Inc.")
1305
1641
  # only one of two clients is included in the association due to the :conditions key
1306
1642
  assert_equal 2, Client.where(client_of: firm.id).size
1307
- assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
1643
+ assert_equal 1, firm.dependent_hash_conditional_clients_of_firm.size
1308
1644
  firm.destroy
1309
1645
  # only the correctly associated client should have been deleted
1310
1646
  assert_equal 1, Client.where(client_of: firm.id).size
@@ -1326,13 +1662,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1326
1662
  def test_creation_respects_hash_condition
1327
1663
  ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
1328
1664
 
1329
- assert ms_client.save
1330
- assert_equal 'Microsoft', ms_client.name
1665
+ assert ms_client.save
1666
+ assert_equal "Microsoft", ms_client.name
1331
1667
 
1332
1668
  another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
1333
1669
 
1334
- assert another_ms_client.persisted?
1335
- assert_equal 'Microsoft', another_ms_client.name
1670
+ assert_predicate another_ms_client, :persisted?
1671
+ assert_equal "Microsoft", another_ms_client.name
1336
1672
  end
1337
1673
 
1338
1674
  def test_clearing_without_initial_access
@@ -1346,7 +1682,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1346
1682
 
1347
1683
  def test_deleting_a_item_which_is_not_in_the_collection
1348
1684
  force_signal37_to_load_all_clients_of_firm
1349
- summit = Client.find_by_name('Summit')
1685
+
1686
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1687
+
1688
+ summit = Client.find_by_name("Summit")
1350
1689
  companies(:first_firm).clients_of_firm.delete(summit)
1351
1690
  assert_equal 2, companies(:first_firm).clients_of_firm.size
1352
1691
  assert_equal 2, companies(:first_firm).clients_of_firm.reload.size
@@ -1356,7 +1695,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1356
1695
  def test_deleting_by_integer_id
1357
1696
  david = Developer.find(1)
1358
1697
 
1359
- assert_difference 'david.projects.count', -1 do
1698
+ assert_difference "david.projects.count", -1 do
1360
1699
  assert_equal 1, david.projects.delete(1).size
1361
1700
  end
1362
1701
 
@@ -1366,8 +1705,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1366
1705
  def test_deleting_by_string_id
1367
1706
  david = Developer.find(1)
1368
1707
 
1369
- assert_difference 'david.projects.count', -1 do
1370
- assert_equal 1, david.projects.delete('1').size
1708
+ assert_difference "david.projects.count", -1 do
1709
+ assert_equal 1, david.projects.delete("1").size
1371
1710
  end
1372
1711
 
1373
1712
  assert_equal 1, david.projects.size
@@ -1382,6 +1721,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1382
1721
  def test_destroying
1383
1722
  force_signal37_to_load_all_clients_of_firm
1384
1723
 
1724
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1725
+
1385
1726
  assert_difference "Client.count", -1 do
1386
1727
  companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
1387
1728
  end
@@ -1393,6 +1734,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1393
1734
  def test_destroying_by_integer_id
1394
1735
  force_signal37_to_load_all_clients_of_firm
1395
1736
 
1737
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1738
+
1396
1739
  assert_difference "Client.count", -1 do
1397
1740
  companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id)
1398
1741
  end
@@ -1404,6 +1747,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1404
1747
  def test_destroying_by_string_id
1405
1748
  force_signal37_to_load_all_clients_of_firm
1406
1749
 
1750
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1751
+
1407
1752
  assert_difference "Client.count", -1 do
1408
1753
  companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id.to_s)
1409
1754
  end
@@ -1414,6 +1759,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1414
1759
 
1415
1760
  def test_destroying_a_collection
1416
1761
  force_signal37_to_load_all_clients_of_firm
1762
+
1763
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1764
+
1417
1765
  companies(:first_firm).clients_of_firm.create("name" => "Another Client")
1418
1766
  assert_equal 3, companies(:first_firm).clients_of_firm.size
1419
1767
 
@@ -1427,8 +1775,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1427
1775
 
1428
1776
  def test_destroy_all
1429
1777
  force_signal37_to_load_all_clients_of_firm
1778
+
1779
+ assert_predicate companies(:first_firm).clients_of_firm, :loaded?
1780
+
1430
1781
  clients = companies(:first_firm).clients_of_firm.to_a
1431
- assert !clients.empty?, "37signals has clients after load"
1782
+ assert_not clients.empty?, "37signals has clients after load"
1432
1783
  destroyed = companies(:first_firm).clients_of_firm.destroy_all
1433
1784
  assert_equal clients.sort_by(&:id), destroyed.sort_by(&:id)
1434
1785
  assert destroyed.all?(&:frozen?), "destroyed clients should be frozen"
@@ -1436,21 +1787,52 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1436
1787
  assert companies(:first_firm).clients_of_firm.reload.empty?, "37signals has no clients after destroy all and refresh"
1437
1788
  end
1438
1789
 
1790
+ def test_destroy_all_on_association_clears_scope
1791
+ author = Author.create!(name: "Gannon")
1792
+ posts = author.posts
1793
+ posts.create!(title: "test", body: "body")
1794
+ posts.destroy_all
1795
+ assert_nil posts.first
1796
+ end
1797
+
1798
+ def test_destroy_all_on_desynced_counter_cache_association
1799
+ category = categories(:general)
1800
+ assert_operator category.categorizations.count, :>, 0
1801
+
1802
+ category.categorizations.destroy_all
1803
+ assert_equal 0, category.categorizations.count
1804
+ end
1805
+
1806
+ def test_destroy_on_association_clears_scope
1807
+ author = Author.create!(name: "Gannon")
1808
+ posts = author.posts
1809
+ post = posts.create!(title: "test", body: "body")
1810
+ posts.destroy(post)
1811
+ assert_nil posts.first
1812
+ end
1813
+
1814
+ def test_delete_on_association_clears_scope
1815
+ author = Author.create!(name: "Gannon")
1816
+ posts = author.posts
1817
+ post = posts.create!(title: "test", body: "body")
1818
+ posts.delete(post)
1819
+ assert_nil posts.first
1820
+ end
1821
+
1439
1822
  def test_dependence
1440
1823
  firm = companies(:first_firm)
1441
1824
  assert_equal 3, firm.clients.size
1442
1825
  firm.destroy
1443
- assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
1826
+ assert_empty Client.all.merge!(where: "firm_id=#{firm.id}").to_a
1444
1827
  end
1445
1828
 
1446
1829
  def test_dependence_for_associations_with_hash_condition
1447
1830
  david = authors(:david)
1448
- assert_difference('Post.count', -1) { assert david.destroy }
1831
+ assert_difference("Post.count", -1) { assert david.destroy }
1449
1832
  end
1450
1833
 
1451
1834
  def test_destroy_dependent_when_deleted_from_association
1452
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
1453
- firm = Firm.all.merge!(:order => "id").first
1835
+ firm = Firm.first
1454
1836
  assert_equal 3, firm.clients.size
1455
1837
 
1456
1838
  client = firm.clients.first
@@ -1477,7 +1859,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1477
1859
 
1478
1860
  firm.destroy rescue "do nothing"
1479
1861
 
1480
- assert_equal 3, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
1862
+ assert_equal 3, Client.all.merge!(where: "firm_id=#{firm.id}").to_a.size
1481
1863
  end
1482
1864
 
1483
1865
  def test_dependence_on_account
@@ -1491,7 +1873,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1491
1873
 
1492
1874
  core = companies(:rails_core)
1493
1875
  assert_equal accounts(:rails_core_account), core.account
1494
- assert_equal companies(:leetsoft, :jadedpixel), core.companies
1876
+ assert_equal companies(:leetsoft, :jadedpixel).sort_by(&:id), core.companies.sort_by(&:id)
1495
1877
  core.destroy
1496
1878
  assert_nil accounts(:rails_core_account).reload.firm_id
1497
1879
  assert_nil companies(:leetsoft).reload.client_of
@@ -1500,66 +1882,62 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1500
1882
  assert_equal num_accounts, Account.count
1501
1883
  end
1502
1884
 
1503
- def test_restrict_with_exception
1504
- firm = RestrictedWithExceptionFirm.create!(:name => 'restrict')
1505
- firm.companies.create(:name => 'child')
1506
-
1507
- assert !firm.companies.empty?
1508
- assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
1509
- assert RestrictedWithExceptionFirm.exists?(:name => 'restrict')
1510
- assert firm.companies.exists?(:name => 'child')
1511
- end
1512
-
1513
- def test_restrict_with_error_is_deprecated_using_key_many
1514
- I18n.backend = I18n::Backend::Simple.new
1515
- I18n.backend.store_translations :en, activerecord: { errors: { messages: { restrict_dependent_destroy: { many: 'message for deprecated key' } } } }
1885
+ def test_depends_and_nullify_on_polymorphic_assoc
1886
+ author = PersonWithPolymorphicDependentNullifyComments.create!(first_name: "Laertis")
1887
+ comment = posts(:welcome).comments.first
1888
+ comment.author = author
1889
+ comment.save!
1516
1890
 
1517
- firm = RestrictedWithErrorFirm.create!(name: 'restrict')
1518
- firm.companies.create(name: 'child')
1891
+ assert_equal comment.author_id, author.id
1892
+ assert_equal comment.author_type, author.class.name
1519
1893
 
1520
- assert !firm.companies.empty?
1894
+ author.destroy
1895
+ comment.reload
1521
1896
 
1522
- assert_deprecated { firm.destroy }
1897
+ assert_nil comment.author_id
1898
+ assert_nil comment.author_type
1899
+ end
1523
1900
 
1524
- assert !firm.errors.empty?
1901
+ def test_restrict_with_exception
1902
+ firm = RestrictedWithExceptionFirm.create!(name: "restrict")
1903
+ firm.companies.create(name: "child")
1525
1904
 
1526
- assert_equal 'message for deprecated key', firm.errors[:base].first
1527
- assert RestrictedWithErrorFirm.exists?(name: 'restrict')
1528
- assert firm.companies.exists?(name: 'child')
1529
- ensure
1530
- I18n.backend.reload!
1905
+ assert_not_empty firm.companies
1906
+ assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
1907
+ assert RestrictedWithExceptionFirm.exists?(name: "restrict")
1908
+ assert firm.companies.exists?(name: "child")
1531
1909
  end
1532
1910
 
1533
1911
  def test_restrict_with_error
1534
- firm = RestrictedWithErrorFirm.create!(:name => 'restrict')
1535
- firm.companies.create(:name => 'child')
1912
+ firm = RestrictedWithErrorFirm.create!(name: "restrict")
1913
+ firm.companies.create(name: "child")
1536
1914
 
1537
- assert !firm.companies.empty?
1915
+ assert_not_empty firm.companies
1538
1916
 
1539
1917
  firm.destroy
1540
1918
 
1541
- assert !firm.errors.empty?
1919
+ assert_not_empty firm.errors
1542
1920
 
1543
1921
  assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first
1544
- assert RestrictedWithErrorFirm.exists?(:name => 'restrict')
1545
- assert firm.companies.exists?(:name => 'child')
1922
+ assert RestrictedWithErrorFirm.exists?(name: "restrict")
1923
+ assert firm.companies.exists?(name: "child")
1546
1924
  end
1547
1925
 
1548
1926
  def test_restrict_with_error_with_locale
1549
1927
  I18n.backend = I18n::Backend::Simple.new
1550
- I18n.backend.store_translations 'en', activerecord: {attributes: {restricted_with_error_firm: {companies: 'client companies'}}}
1551
- firm = RestrictedWithErrorFirm.create!(name: 'restrict')
1552
- firm.companies.create(name: 'child')
1928
+ I18n.backend.store_translations "en", activerecord: { attributes: { restricted_with_error_firm: { companies: "client companies" } } }
1929
+ firm = RestrictedWithErrorFirm.create!(name: "restrict")
1930
+ firm.companies.create(name: "child")
1553
1931
 
1554
- assert !firm.companies.empty?
1932
+ assert_not_empty firm.companies
1555
1933
 
1556
1934
  firm.destroy
1557
1935
 
1558
- assert !firm.errors.empty?
1936
+ assert_not_empty firm.errors
1559
1937
 
1560
1938
  assert_equal "Cannot delete record because dependent client companies exist", firm.errors[:base].first
1561
- assert RestrictedWithErrorFirm.exists?(name: 'restrict')
1562
- assert firm.companies.exists?(name: 'child')
1939
+ assert RestrictedWithErrorFirm.exists?(name: "restrict")
1940
+ assert firm.companies.exists?(name: "child")
1563
1941
  ensure
1564
1942
  I18n.backend.reload!
1565
1943
  end
@@ -1569,10 +1947,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1569
1947
  end
1570
1948
 
1571
1949
  def test_included_in_collection_for_new_records
1572
- client = Client.create(:name => 'Persisted')
1950
+ client = Client.create(name: "Persisted")
1573
1951
  assert_nil client.client_of
1574
1952
  assert_equal false, Firm.new.clients_of_firm.include?(client),
1575
- 'includes a client that does not belong to any firm'
1953
+ "includes a client that does not belong to any firm"
1576
1954
  end
1577
1955
 
1578
1956
  def test_adding_array_and_collection
@@ -1580,7 +1958,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1580
1958
  end
1581
1959
 
1582
1960
  def test_replace_with_less
1583
- firm = Firm.all.merge!(:order => "id").first
1961
+ firm = Firm.first
1584
1962
  firm.clients = [companies(:first_client)]
1585
1963
  assert firm.save, "Could not save firm"
1586
1964
  firm.reload
@@ -1594,7 +1972,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1594
1972
  end
1595
1973
 
1596
1974
  def test_replace_with_new
1597
- firm = Firm.all.merge!(:order => "id").first
1975
+ firm = Firm.first
1598
1976
  firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
1599
1977
  firm.save
1600
1978
  firm.reload
@@ -1607,8 +1985,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1607
1985
  account = Account.new
1608
1986
  orig_accounts = firm.accounts.to_a
1609
1987
 
1610
- assert !account.valid?
1611
- assert !orig_accounts.empty?
1988
+ assert_not_predicate account, :valid?
1989
+ assert_not_empty orig_accounts
1612
1990
  error = assert_raise ActiveRecord::RecordNotSaved do
1613
1991
  firm.accounts = [account]
1614
1992
  end
@@ -1623,16 +2001,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1623
2001
  firm.clients = []
1624
2002
  firm.save
1625
2003
 
1626
- assert_queries(0, ignore_none: true) do
2004
+ assert_no_queries do
1627
2005
  firm.clients = []
1628
2006
  end
1629
2007
 
1630
- assert_equal [], firm.send('clients=', [])
2008
+ assert_equal [], firm.public_send("clients=", [])
1631
2009
  end
1632
2010
 
1633
2011
  def test_transactions_when_replacing_on_persisted
1634
- good = Client.new(:name => "Good")
1635
- bad = Client.new(:name => "Bad", :raise_on_save => true)
2012
+ good = Client.new(name: "Good")
2013
+ bad = Client.new(name: "Bad", raise_on_save: true)
1636
2014
 
1637
2015
  companies(:first_firm).clients_of_firm = [good]
1638
2016
 
@@ -1645,8 +2023,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1645
2023
  end
1646
2024
 
1647
2025
  def test_transactions_when_replacing_on_new_record
1648
- assert_no_queries(ignore_none: false) do
1649
- firm = Firm.new
2026
+ firm = Firm.new
2027
+ assert_queries(0) do
1650
2028
  firm.clients_of_firm = [Client.new("name" => "New Client")]
1651
2029
  end
1652
2030
  end
@@ -1658,7 +2036,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1658
2036
  def test_get_ids_for_loaded_associations
1659
2037
  company = companies(:first_firm)
1660
2038
  company.clients.reload
1661
- assert_queries(0) do
2039
+ assert_no_queries do
1662
2040
  company.client_ids
1663
2041
  company.client_ids
1664
2042
  end
@@ -1666,9 +2044,29 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1666
2044
 
1667
2045
  def test_get_ids_for_unloaded_associations_does_not_load_them
1668
2046
  company = companies(:first_firm)
1669
- assert !company.clients.loaded?
2047
+ assert_not_predicate company.clients, :loaded?
1670
2048
  assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], company.client_ids
1671
- assert !company.clients.loaded?
2049
+ assert_not_predicate company.clients, :loaded?
2050
+ end
2051
+
2052
+ def test_counter_cache_on_unloaded_association
2053
+ car = Car.create(name: "My AppliCar")
2054
+ assert_equal 0, car.engines.size
2055
+ end
2056
+
2057
+ def test_ids_reader_cache_not_used_for_size_when_association_is_dirty
2058
+ firm = Firm.create!(name: "Startup")
2059
+ assert_equal 0, firm.client_ids.size
2060
+ firm.clients.build
2061
+ assert_equal 1, firm.clients.size
2062
+ end
2063
+
2064
+ def test_ids_reader_cache_should_be_cleared_when_collection_is_deleted
2065
+ firm = companies(:first_firm)
2066
+ assert_equal [2, 3, 11], firm.client_ids
2067
+ client = firm.clients.first
2068
+ firm.clients.delete(client)
2069
+ assert_equal [3, 11], firm.client_ids
1672
2070
  end
1673
2071
 
1674
2072
  def test_get_ids_ignores_include_option
@@ -1680,9 +2078,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1680
2078
  end
1681
2079
 
1682
2080
  def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
1683
- Company.columns # Load schema information so we don't query below
1684
- Contract.columns # if running just this test.
1685
-
1686
2081
  company = Company.new
1687
2082
  assert_queries(0) do
1688
2083
  company.contract_ids
@@ -1695,7 +2090,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1695
2090
  contract_a = Contract.create!
1696
2091
  contract_b = Contract.create!
1697
2092
  Contract.create! # another contract
1698
- company = Company.new(:name => "Some Company")
2093
+ company = Company.new(name: "Some Company")
1699
2094
 
1700
2095
  company.contract_ids = [contract_a.id, contract_b.id]
1701
2096
  assert_equal [contract_a.id, contract_b.id], company.contract_ids
@@ -1707,8 +2102,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1707
2102
  end
1708
2103
 
1709
2104
  def test_assign_ids_ignoring_blanks
1710
- firm = Firm.create!(:name => 'Apple')
1711
- firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
2105
+ firm = Firm.create!(name: "Apple")
2106
+ firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, ""]
1712
2107
  firm.save!
1713
2108
 
1714
2109
  assert_equal 2, firm.clients.reload.size
@@ -1723,19 +2118,28 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1723
2118
  [
1724
2119
  lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
1725
2120
  lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
1726
- lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
2121
+ lambda { authors(:mary).comments << Comment.create!(body: "Yay", post_id: 424242) },
1727
2122
  lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
1728
- ].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
2123
+ ].each { |block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
2124
+ end
2125
+
2126
+ def test_associations_order_should_be_priority_over_throughs_order
2127
+ original = authors(:david)
2128
+ expected = [13, 12, 10, 9, 8, 7, 6, 5, 3, 2, 1]
2129
+ assert_equal expected, original.comments_desc.map(&:id)
2130
+ preloaded = Author.includes(:comments_desc).find(original.id)
2131
+ assert_equal expected, preloaded.comments_desc.map(&:id)
2132
+ assert_equal original.posts_sorted_by_id.first.comments.map(&:id), preloaded.posts_sorted_by_id.first.comments.map(&:id)
1729
2133
  end
1730
2134
 
1731
2135
  def test_dynamic_find_should_respect_association_order_for_through
1732
2136
  assert_equal Comment.find(10), authors(:david).comments_desc.where("comments.type = 'SpecialComment'").first
1733
- assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
2137
+ assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type("SpecialComment")
1734
2138
  end
1735
2139
 
1736
2140
  def test_has_many_through_respects_hash_conditions
1737
- assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
1738
- assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
2141
+ assert_equal authors(:david).hello_posts.sort_by(&:id), authors(:david).hello_posts_with_hash_conditions.sort_by(&:id)
2142
+ assert_equal authors(:david).hello_post_comments.sort_by(&:id), authors(:david).hello_post_comments_with_hash_conditions.sort_by(&:id)
1739
2143
  end
1740
2144
 
1741
2145
  def test_include_uses_array_include_after_loaded
@@ -1745,7 +2149,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1745
2149
  client = firm.clients.first
1746
2150
 
1747
2151
  assert_no_queries do
1748
- assert firm.clients.loaded?
2152
+ assert_predicate firm.clients, :loaded?
1749
2153
  assert_equal true, firm.clients.include?(client)
1750
2154
  end
1751
2155
  end
@@ -1755,18 +2159,18 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1755
2159
  client = firm.clients.first
1756
2160
 
1757
2161
  firm.reload
1758
- assert ! firm.clients.loaded?
2162
+ assert_not_predicate firm.clients, :loaded?
1759
2163
  assert_queries(1) do
1760
2164
  assert_equal true, firm.clients.include?(client)
1761
2165
  end
1762
- assert ! firm.clients.loaded?
2166
+ assert_not_predicate firm.clients, :loaded?
1763
2167
  end
1764
2168
 
1765
2169
  def test_include_returns_false_for_non_matching_record_to_verify_scoping
1766
2170
  firm = companies(:first_firm)
1767
- client = Client.create!(:name => 'Not Associated')
2171
+ client = Client.create!(name: "Not Associated")
1768
2172
 
1769
- assert ! firm.clients.loaded?
2173
+ assert_not_predicate firm.clients, :loaded?
1770
2174
  assert_equal false, firm.clients.include?(client)
1771
2175
  end
1772
2176
 
@@ -1775,15 +2179,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1775
2179
  firm.clients.first
1776
2180
  firm.clients.second
1777
2181
  firm.clients.last
1778
- assert !firm.clients.loaded?
2182
+ assert_not_predicate firm.clients, :loaded?
1779
2183
  end
1780
2184
 
1781
2185
  def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
1782
2186
  firm = companies(:first_firm)
1783
2187
  firm.clients.load_target
1784
- assert firm.clients.loaded?
2188
+ assert_predicate firm.clients, :loaded?
1785
2189
 
1786
- assert_no_queries(ignore_none: false) do
2190
+ assert_no_queries do
1787
2191
  firm.clients.first
1788
2192
  assert_equal 2, firm.clients.first(2).size
1789
2193
  firm.clients.last
@@ -1791,10 +2195,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1791
2195
  end
1792
2196
  end
1793
2197
 
1794
- def test_calling_first_or_last_on_existing_record_with_build_should_load_association
2198
+ def test_calling_first_nth_or_last_on_existing_record_with_build_should_load_association
1795
2199
  firm = companies(:first_firm)
1796
- firm.clients.build(:name => 'Foo')
1797
- assert !firm.clients.loaded?
2200
+ firm.clients.build(name: "Foo")
2201
+ assert_not_predicate firm.clients, :loaded?
1798
2202
 
1799
2203
  assert_queries 1 do
1800
2204
  firm.clients.first
@@ -1802,13 +2206,31 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1802
2206
  firm.clients.last
1803
2207
  end
1804
2208
 
1805
- assert firm.clients.loaded?
2209
+ assert_predicate firm.clients, :loaded?
2210
+
2211
+ author = Author.create!(name: "Carl")
2212
+ third = topics(:third)
2213
+ fourth = topics(:fourth).becomes(Topic)
2214
+
2215
+ new_topic = author.topics_without_type.build
2216
+
2217
+ assert_not_predicate author.topics_without_type, :loaded?
2218
+
2219
+ assert_queries(1) do
2220
+ if current_adapter?(:Mysql2Adapter, :SQLite3Adapter)
2221
+ assert_equal fourth, author.topics_without_type.first
2222
+ assert_equal third, author.topics_without_type.second
2223
+ end
2224
+ assert_equal new_topic, author.topics_without_type.last
2225
+ end
2226
+
2227
+ assert_predicate author.topics_without_type, :loaded?
1806
2228
  end
1807
2229
 
1808
2230
  def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_load_association
1809
2231
  firm = companies(:first_firm)
1810
- firm.clients.create(:name => 'Foo')
1811
- assert !firm.clients.loaded?
2232
+ firm.clients.create(name: "Foo")
2233
+ assert_not_predicate firm.clients, :loaded?
1812
2234
 
1813
2235
  assert_queries 3 do
1814
2236
  firm.clients.first
@@ -1816,7 +2238,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1816
2238
  firm.clients.last
1817
2239
  end
1818
2240
 
1819
- assert !firm.clients.loaded?
2241
+ assert_not_predicate firm.clients, :loaded?
1820
2242
  end
1821
2243
 
1822
2244
  def test_calling_first_nth_or_last_on_new_record_should_not_run_queries
@@ -1831,15 +2253,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1831
2253
 
1832
2254
  def test_calling_first_or_last_with_integer_on_association_should_not_load_association
1833
2255
  firm = companies(:first_firm)
1834
- firm.clients.create(:name => 'Foo')
1835
- assert !firm.clients.loaded?
2256
+ firm.clients.create(name: "Foo")
2257
+ assert_not_predicate firm.clients, :loaded?
1836
2258
 
1837
2259
  assert_queries 2 do
1838
2260
  firm.clients.first(2)
1839
2261
  firm.clients.last(2)
1840
2262
  end
1841
2263
 
1842
- assert !firm.clients.loaded?
2264
+ assert_not_predicate firm.clients, :loaded?
1843
2265
  end
1844
2266
 
1845
2267
  def test_calling_many_should_count_instead_of_loading_association
@@ -1847,37 +2269,38 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1847
2269
  assert_queries(1) do
1848
2270
  firm.clients.many? # use count query
1849
2271
  end
1850
- assert !firm.clients.loaded?
2272
+ assert_not_predicate firm.clients, :loaded?
1851
2273
  end
1852
2274
 
1853
2275
  def test_calling_many_on_loaded_association_should_not_use_query
1854
2276
  firm = companies(:first_firm)
1855
- firm.clients.collect # force load
2277
+ firm.clients.load # force load
1856
2278
  assert_no_queries { assert firm.clients.many? }
1857
2279
  end
1858
2280
 
1859
2281
  def test_calling_many_should_defer_to_collection_if_using_a_block
1860
2282
  firm = companies(:first_firm)
1861
2283
  assert_queries(1) do
1862
- firm.clients.expects(:size).never
1863
- firm.clients.many? { true }
2284
+ assert_not_called(firm.clients, :size) do
2285
+ firm.clients.many? { true }
2286
+ end
1864
2287
  end
1865
- assert firm.clients.loaded?
2288
+ assert_predicate firm.clients, :loaded?
1866
2289
  end
1867
2290
 
1868
2291
  def test_calling_many_should_return_false_if_none_or_one
1869
2292
  firm = companies(:another_firm)
1870
- assert !firm.clients_like_ms.many?
2293
+ assert_not_predicate firm.clients_like_ms, :many?
1871
2294
  assert_equal 0, firm.clients_like_ms.size
1872
2295
 
1873
2296
  firm = companies(:first_firm)
1874
- assert !firm.limited_clients.many?
2297
+ assert_not_predicate firm.limited_clients, :many?
1875
2298
  assert_equal 1, firm.limited_clients.size
1876
2299
  end
1877
2300
 
1878
2301
  def test_calling_many_should_return_true_if_more_than_one
1879
2302
  firm = companies(:first_firm)
1880
- assert firm.clients.many?
2303
+ assert_predicate firm.clients, :many?
1881
2304
  assert_equal 3, firm.clients.size
1882
2305
  end
1883
2306
 
@@ -1886,33 +2309,34 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1886
2309
  assert_queries(1) do
1887
2310
  firm.clients.none? # use count query
1888
2311
  end
1889
- assert !firm.clients.loaded?
2312
+ assert_not_predicate firm.clients, :loaded?
1890
2313
  end
1891
2314
 
1892
2315
  def test_calling_none_on_loaded_association_should_not_use_query
1893
2316
  firm = companies(:first_firm)
1894
- firm.clients.collect # force load
1895
- assert_no_queries { assert ! firm.clients.none? }
2317
+ firm.clients.load # force load
2318
+ assert_no_queries { assert_not firm.clients.none? }
1896
2319
  end
1897
2320
 
1898
2321
  def test_calling_none_should_defer_to_collection_if_using_a_block
1899
2322
  firm = companies(:first_firm)
1900
2323
  assert_queries(1) do
1901
- firm.clients.expects(:size).never
1902
- firm.clients.none? { true }
2324
+ assert_not_called(firm.clients, :size) do
2325
+ firm.clients.none? { true }
2326
+ end
1903
2327
  end
1904
- assert firm.clients.loaded?
2328
+ assert_predicate firm.clients, :loaded?
1905
2329
  end
1906
2330
 
1907
2331
  def test_calling_none_should_return_true_if_none
1908
2332
  firm = companies(:another_firm)
1909
- assert firm.clients_like_ms.none?
2333
+ assert_predicate firm.clients_like_ms, :none?
1910
2334
  assert_equal 0, firm.clients_like_ms.size
1911
2335
  end
1912
2336
 
1913
2337
  def test_calling_none_should_return_false_if_any
1914
2338
  firm = companies(:first_firm)
1915
- assert !firm.limited_clients.none?
2339
+ assert_not_predicate firm.limited_clients, :none?
1916
2340
  assert_equal 1, firm.limited_clients.size
1917
2341
  end
1918
2342
 
@@ -1921,39 +2345,40 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1921
2345
  assert_queries(1) do
1922
2346
  firm.clients.one? # use count query
1923
2347
  end
1924
- assert !firm.clients.loaded?
2348
+ assert_not_predicate firm.clients, :loaded?
1925
2349
  end
1926
2350
 
1927
2351
  def test_calling_one_on_loaded_association_should_not_use_query
1928
2352
  firm = companies(:first_firm)
1929
- firm.clients.collect # force load
1930
- assert_no_queries { assert ! firm.clients.one? }
2353
+ firm.clients.load # force load
2354
+ assert_no_queries { assert_not firm.clients.one? }
1931
2355
  end
1932
2356
 
1933
2357
  def test_calling_one_should_defer_to_collection_if_using_a_block
1934
2358
  firm = companies(:first_firm)
1935
2359
  assert_queries(1) do
1936
- firm.clients.expects(:size).never
1937
- firm.clients.one? { true }
2360
+ assert_not_called(firm.clients, :size) do
2361
+ firm.clients.one? { true }
2362
+ end
1938
2363
  end
1939
- assert firm.clients.loaded?
2364
+ assert_predicate firm.clients, :loaded?
1940
2365
  end
1941
2366
 
1942
2367
  def test_calling_one_should_return_false_if_zero
1943
2368
  firm = companies(:another_firm)
1944
- assert ! firm.clients_like_ms.one?
2369
+ assert_not_predicate firm.clients_like_ms, :one?
1945
2370
  assert_equal 0, firm.clients_like_ms.size
1946
2371
  end
1947
2372
 
1948
2373
  def test_calling_one_should_return_true_if_one
1949
2374
  firm = companies(:first_firm)
1950
- assert firm.limited_clients.one?
2375
+ assert_predicate firm.limited_clients, :one?
1951
2376
  assert_equal 1, firm.limited_clients.size
1952
2377
  end
1953
2378
 
1954
2379
  def test_calling_one_should_return_false_if_more_than_one
1955
2380
  firm = companies(:first_firm)
1956
- assert ! firm.clients.one?
2381
+ assert_not_predicate firm.clients, :one?
1957
2382
  assert_equal 3, firm.clients.size
1958
2383
  end
1959
2384
 
@@ -1961,13 +2386,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1961
2386
  old = ActiveRecord::Base.store_full_sti_class
1962
2387
  ActiveRecord::Base.store_full_sti_class = true
1963
2388
 
1964
- firm = Namespaced::Firm.create({ :name => 'Some Company' })
1965
- firm.clients.create({ :name => 'Some Client' })
2389
+ firm = Namespaced::Firm.create(name: "Some Company")
2390
+ firm.clients.create(name: "Some Client")
1966
2391
 
1967
2392
  stats = Namespaced::Firm.all.merge!(
1968
- :select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
1969
- :joins => :clients,
1970
- :group => "#{Namespaced::Firm.table_name}.id"
2393
+ select: "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
2394
+ joins: :clients,
2395
+ group: "#{Namespaced::Firm.table_name}.id"
1971
2396
  ).find firm.id
1972
2397
  assert_equal 1, stats.num_clients.to_i
1973
2398
  ensure
@@ -1975,9 +2400,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1975
2400
  end
1976
2401
 
1977
2402
  def test_association_proxy_transaction_method_starts_transaction_in_association_class
1978
- Comment.expects(:transaction)
1979
- Post.first.comments.transaction do
1980
- # nothing
2403
+ assert_called(Comment, :transaction) do
2404
+ Post.first.comments.transaction do
2405
+ # nothing
2406
+ end
1981
2407
  end
1982
2408
  end
1983
2409
 
@@ -1986,43 +2412,45 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
1986
2412
  assert_equal client_association.new.attributes, client_association.send(:new).attributes
1987
2413
  end
1988
2414
 
1989
- def test_respond_to_private_class_methods
1990
- client_association = companies(:first_firm).clients
1991
- assert !client_association.respond_to?(:private_method)
1992
- assert client_association.respond_to?(:private_method, true)
1993
- end
1994
-
1995
2415
  def test_creating_using_primary_key
1996
- firm = Firm.all.merge!(:order => "id").first
1997
- client = firm.clients_using_primary_key.create!(:name => 'test')
2416
+ firm = Firm.first
2417
+ client = firm.clients_using_primary_key.create!(name: "test")
1998
2418
  assert_equal firm.name, client.firm_name
1999
2419
  end
2000
2420
 
2001
2421
  def test_defining_has_many_association_with_delete_all_dependency_lazily_evaluates_target_class
2002
- ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
2003
- class_eval(<<-EOF, __FILE__, __LINE__ + 1)
2004
- class DeleteAllModel < ActiveRecord::Base
2005
- has_many :nonentities, :dependent => :delete_all
2006
- end
2007
- EOF
2422
+ assert_not_called_on_instance_of(
2423
+ ActiveRecord::Reflection::AssociationReflection,
2424
+ :class_name,
2425
+ ) do
2426
+ class_eval(<<-EOF, __FILE__, __LINE__ + 1)
2427
+ class DeleteAllModel < ActiveRecord::Base
2428
+ has_many :nonentities, :dependent => :delete_all
2429
+ end
2430
+ EOF
2431
+ end
2008
2432
  end
2009
2433
 
2010
2434
  def test_defining_has_many_association_with_nullify_dependency_lazily_evaluates_target_class
2011
- ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
2012
- class_eval(<<-EOF, __FILE__, __LINE__ + 1)
2013
- class NullifyModel < ActiveRecord::Base
2014
- has_many :nonentities, :dependent => :nullify
2015
- end
2016
- EOF
2435
+ assert_not_called_on_instance_of(
2436
+ ActiveRecord::Reflection::AssociationReflection,
2437
+ :class_name,
2438
+ ) do
2439
+ class_eval(<<-EOF, __FILE__, __LINE__ + 1)
2440
+ class NullifyModel < ActiveRecord::Base
2441
+ has_many :nonentities, :dependent => :nullify
2442
+ end
2443
+ EOF
2444
+ end
2017
2445
  end
2018
2446
 
2019
2447
  def test_attributes_are_being_set_when_initialized_from_has_many_association_with_where_clause
2020
- new_comment = posts(:welcome).comments.where(:body => "Some content").build
2448
+ new_comment = posts(:welcome).comments.where(body: "Some content").build
2021
2449
  assert_equal new_comment.body, "Some content"
2022
2450
  end
2023
2451
 
2024
2452
  def test_attributes_are_being_set_when_initialized_from_has_many_association_with_multiple_where_clauses
2025
- new_comment = posts(:welcome).comments.where(:body => "Some content").where(:type => 'SpecialComment').build
2453
+ new_comment = posts(:welcome).comments.where(body: "Some content").where(type: "SpecialComment").build
2026
2454
  assert_equal new_comment.body, "Some content"
2027
2455
  assert_equal new_comment.type, "SpecialComment"
2028
2456
  assert_equal new_comment.post_id, posts(:welcome).id
@@ -2036,7 +2464,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2036
2464
 
2037
2465
  def test_load_target_respects_protected_attributes
2038
2466
  topic = Topic.create!
2039
- reply = topic.replies.create(:title => "reply 1")
2467
+ reply = topic.replies.create(title: "reply 1")
2040
2468
  reply.approved = false
2041
2469
  reply.save!
2042
2470
 
@@ -2059,11 +2487,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2059
2487
  ary = topics(:first).replies.to_a
2060
2488
  target = topics(:first).replies.target
2061
2489
 
2062
- assert_not_equal target.object_id, ary.object_id
2490
+ assert_not_same target, ary
2063
2491
  end
2064
2492
 
2065
2493
  def test_merging_with_custom_attribute_writer
2066
- bulb = Bulb.new(:color => "red")
2494
+ bulb = Bulb.new(color: "red")
2067
2495
  assert_equal "RED!", bulb.color
2068
2496
 
2069
2497
  car = Car.create!
@@ -2073,26 +2501,34 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2073
2501
  end
2074
2502
 
2075
2503
  def test_abstract_class_with_polymorphic_has_many
2076
- post = SubStiPost.create! :title => "fooo", :body => "baa"
2077
- tagging = Tagging.create! :taggable => post
2504
+ post = SubStiPost.create! title: "fooo", body: "baa"
2505
+ tagging = Tagging.create! taggable: post
2078
2506
  assert_equal [tagging], post.taggings
2079
2507
  end
2080
2508
 
2081
2509
  def test_with_polymorphic_has_many_with_custom_columns_name
2082
- post = Post.create! :title => 'foo', :body => 'bar'
2510
+ post = Post.create! title: "foo", body: "bar"
2083
2511
  image = Image.create!
2084
2512
 
2085
2513
  post.images << image
2086
2514
 
2087
2515
  assert_equal [image], post.images
2516
+ assert_equal post, image.imageable
2088
2517
  end
2089
2518
 
2090
2519
  def test_build_with_polymorphic_has_many_does_not_allow_to_override_type_and_id
2091
2520
  welcome = posts(:welcome)
2092
- tagging = welcome.taggings.build(:taggable_id => 99, :taggable_type => 'ShouldNotChange')
2521
+ tagging = welcome.taggings.build(taggable_id: 99, taggable_type: "ShouldNotChange")
2093
2522
 
2094
2523
  assert_equal welcome.id, tagging.taggable_id
2095
- assert_equal 'Post', tagging.taggable_type
2524
+ assert_equal "Post", tagging.taggable_type
2525
+ end
2526
+
2527
+ def test_build_from_polymorphic_association_sets_inverse_instance
2528
+ post = Post.new
2529
+ tagging = post.taggings.build
2530
+
2531
+ assert_equal post, tagging.taggable
2096
2532
  end
2097
2533
 
2098
2534
  def test_dont_call_save_callbacks_twice_on_has_many
@@ -2104,30 +2540,30 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2104
2540
  end
2105
2541
 
2106
2542
  def test_association_attributes_are_available_to_after_initialize
2107
- car = Car.create(:name => 'honda')
2543
+ car = Car.create(name: "honda")
2108
2544
  bulb = car.bulbs.build
2109
2545
 
2110
- assert_equal car.id, bulb.attributes_after_initialize['car_id']
2546
+ assert_equal car.id, bulb.attributes_after_initialize["car_id"]
2111
2547
  end
2112
2548
 
2113
2549
  def test_attributes_are_set_when_initialized_from_has_many_null_relationship
2114
- car = Car.new name: 'honda'
2115
- bulb = car.bulbs.where(name: 'headlight').first_or_initialize
2116
- assert_equal 'headlight', bulb.name
2550
+ car = Car.new name: "honda"
2551
+ bulb = car.bulbs.where(name: "headlight").first_or_initialize
2552
+ assert_equal "headlight", bulb.name
2117
2553
  end
2118
2554
 
2119
2555
  def test_attributes_are_set_when_initialized_from_polymorphic_has_many_null_relationship
2120
- post = Post.new title: 'title', body: 'bar'
2121
- tag = Tag.create!(name: 'foo')
2556
+ post = Post.new title: "title", body: "bar"
2557
+ tag = Tag.create!(name: "foo")
2122
2558
 
2123
2559
  tagging = post.taggings.where(tag: tag).first_or_initialize
2124
2560
 
2125
2561
  assert_equal tag.id, tagging.tag_id
2126
- assert_equal 'Post', tagging.taggable_type
2562
+ assert_equal "Post", tagging.taggable_type
2127
2563
  end
2128
2564
 
2129
2565
  def test_replace
2130
- car = Car.create(:name => 'honda')
2566
+ car = Car.create(name: "honda")
2131
2567
  bulb1 = car.bulbs.create
2132
2568
  bulb2 = Bulb.create
2133
2569
 
@@ -2138,7 +2574,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2138
2574
  end
2139
2575
 
2140
2576
  def test_replace_returns_target
2141
- car = Car.create(:name => 'honda')
2577
+ car = Car.create(name: "honda")
2142
2578
  bulb1 = car.bulbs.create
2143
2579
  bulb2 = car.bulbs.create
2144
2580
  bulb3 = Bulb.create
@@ -2152,18 +2588,48 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2152
2588
  def test_collection_association_with_private_kernel_method
2153
2589
  firm = companies(:first_firm)
2154
2590
  assert_equal [accounts(:signals37)], firm.accounts.open
2591
+ assert_equal [accounts(:signals37)], firm.accounts.available
2592
+ end
2593
+
2594
+ def test_association_with_or_doesnt_set_inverse_instance_key
2595
+ firm = companies(:first_firm)
2596
+ accounts = firm.accounts.or(Account.where(firm_id: nil)).order(:id)
2597
+ assert_equal [firm.id, nil], accounts.map(&:firm_id)
2598
+ end
2599
+
2600
+ def test_association_with_rewhere_doesnt_set_inverse_instance_key
2601
+ firm = companies(:first_firm)
2602
+ accounts = firm.accounts.rewhere(firm_id: [firm.id, nil]).order(:id)
2603
+ assert_equal [firm.id, nil], accounts.map(&:firm_id)
2155
2604
  end
2156
2605
 
2157
2606
  test "first_or_initialize adds the record to the association" do
2158
- firm = Firm.create! name: 'omg'
2159
- client = firm.clients_of_firm.first_or_initialize
2607
+ firm = Firm.create! name: "omg"
2608
+ client = firm.clients_of_firm.where(name: "lol").first_or_initialize do
2609
+ assert_equal 5, Client.count
2610
+ end
2611
+ assert_equal "lol", client.name
2160
2612
  assert_equal [client], firm.clients_of_firm
2161
2613
  end
2162
2614
 
2163
2615
  test "first_or_create adds the record to the association" do
2164
- firm = Firm.create! name: 'omg'
2616
+ firm = Firm.create! name: "omg"
2617
+ firm.clients_of_firm.load_target
2618
+ client = firm.clients_of_firm.where(name: "lol").first_or_create do
2619
+ assert_equal 5, Client.count
2620
+ end
2621
+ assert_equal "lol", client.name
2622
+ assert_equal [client], firm.clients_of_firm
2623
+ assert_equal [client], firm.reload.clients_of_firm
2624
+ end
2625
+
2626
+ test "first_or_create! adds the record to the association" do
2627
+ firm = Firm.create! name: "omg"
2165
2628
  firm.clients_of_firm.load_target
2166
- client = firm.clients_of_firm.first_or_create name: 'lol'
2629
+ client = firm.clients_of_firm.where(name: "lol").first_or_create! do
2630
+ assert_equal 5, Client.count
2631
+ end
2632
+ assert_equal "lol", client.name
2167
2633
  assert_equal [client], firm.clients_of_firm
2168
2634
  assert_equal [client], firm.reload.clients_of_firm
2169
2635
  end
@@ -2172,7 +2638,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2172
2638
  post = posts(:welcome)
2173
2639
 
2174
2640
  assert post.taggings_with_delete_all.count > 0
2175
- assert !post.taggings_with_delete_all.loaded?
2641
+ assert_not_predicate post.taggings_with_delete_all, :loaded?
2176
2642
 
2177
2643
  # 2 queries: one DELETE and another to update the counter cache
2178
2644
  assert_queries(2) do
@@ -2183,9 +2649,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2183
2649
  test "has many associations on new records use null relations" do
2184
2650
  post = Post.new
2185
2651
 
2186
- assert_no_queries(ignore_none: false) do
2652
+ assert_no_queries do
2187
2653
  assert_equal [], post.comments
2188
- assert_equal [], post.comments.where(body: 'omg')
2654
+ assert_equal [], post.comments.where(body: "omg")
2189
2655
  assert_equal [], post.comments.pluck(:body)
2190
2656
  assert_equal 0, post.comments.sum(:id)
2191
2657
  assert_equal 0, post.comments.count
@@ -2194,34 +2660,34 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2194
2660
 
2195
2661
  test "collection proxy respects default scope" do
2196
2662
  author = authors(:mary)
2197
- assert !author.first_posts.exists?
2663
+ assert_not_predicate author.first_posts, :exists?
2198
2664
  end
2199
2665
 
2200
2666
  test "association with extend option" do
2201
2667
  post = posts(:welcome)
2202
- assert_equal "lifo", post.comments_with_extend.author
2203
- assert_equal "hello", post.comments_with_extend.greeting
2668
+ assert_equal "lifo", post.comments_with_extend.author
2669
+ assert_equal "hello :)", post.comments_with_extend.greeting
2204
2670
  end
2205
2671
 
2206
2672
  test "association with extend option with multiple extensions" do
2207
2673
  post = posts(:welcome)
2208
- assert_equal "lifo", post.comments_with_extend_2.author
2209
- assert_equal "hullo", post.comments_with_extend_2.greeting
2674
+ assert_equal "lifo", post.comments_with_extend_2.author
2675
+ assert_equal "hullo :)", post.comments_with_extend_2.greeting
2210
2676
  end
2211
2677
 
2212
2678
  test "extend option affects per association" do
2213
2679
  post = posts(:welcome)
2214
- assert_equal "lifo", post.comments_with_extend.author
2215
- assert_equal "lifo", post.comments_with_extend_2.author
2216
- assert_equal "hello", post.comments_with_extend.greeting
2217
- assert_equal "hullo", post.comments_with_extend_2.greeting
2680
+ assert_equal "lifo", post.comments_with_extend.author
2681
+ assert_equal "lifo", post.comments_with_extend_2.author
2682
+ assert_equal "hello :)", post.comments_with_extend.greeting
2683
+ assert_equal "hullo :)", post.comments_with_extend_2.greeting
2218
2684
  end
2219
2685
 
2220
2686
  test "delete record with complex joins" do
2221
2687
  david = authors(:david)
2222
2688
 
2223
2689
  post = david.posts.first
2224
- post.type = 'PostWithSpecialCategorization'
2690
+ post.type = "PostWithSpecialCategorization"
2225
2691
  post.save
2226
2692
 
2227
2693
  categorization = post.categorizations.first
@@ -2234,8 +2700,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2234
2700
  end
2235
2701
 
2236
2702
  test "does not duplicate associations when used with natural primary keys" do
2237
- speedometer = Speedometer.create!(id: '4')
2238
- speedometer.minivans.create!(minivan_id: 'a-van-red' ,name: 'a van', color: 'red')
2703
+ speedometer = Speedometer.create!(id: "4")
2704
+ speedometer.minivans.create!(minivan_id: "a-van-red", name: "a van", color: "red")
2239
2705
 
2240
2706
  assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}"
2241
2707
  assert_equal 1, speedometer.reload.minivans.to_a.size
@@ -2248,10 +2714,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2248
2714
 
2249
2715
  assert_equal [bulb1], car.bulbs
2250
2716
  assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
2717
+ assert_equal [bulb1, bulb2], Car.includes(:all_bulbs).find(car.id).all_bulbs.sort_by(&:id)
2718
+ assert_equal [bulb1, bulb2], Car.eager_load(:all_bulbs).find(car.id).all_bulbs.sort_by(&:id)
2251
2719
  end
2252
2720
 
2253
2721
  test "can unscope and where the default scope of the associated model" do
2254
- Car.has_many :other_bulbs, -> { unscope(where: [:name]).where(name: 'other') }, class_name: "Bulb"
2255
2722
  car = Car.create!
2256
2723
  bulb1 = Bulb.create! name: "defaulty", car: car
2257
2724
  bulb2 = Bulb.create! name: "other", car: car
@@ -2261,7 +2728,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2261
2728
  end
2262
2729
 
2263
2730
  test "can rewhere the default scope of the associated model" do
2264
- Car.has_many :old_bulbs, -> { rewhere(name: 'old') }, class_name: "Bulb"
2265
2731
  car = Car.create!
2266
2732
  bulb1 = Bulb.create! name: "defaulty", car: car
2267
2733
  bulb2 = Bulb.create! name: "old", car: car
@@ -2270,13 +2736,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2270
2736
  assert_equal [bulb2], car.old_bulbs
2271
2737
  end
2272
2738
 
2273
- test 'unscopes the default scope of associated model when used with include' do
2739
+ test "unscopes the default scope of associated model when used with include" do
2274
2740
  car = Car.create!
2275
- bulb = Bulb.create! name: "other", car: car
2741
+ bulb1 = Bulb.create! name: "defaulty", car: car
2742
+ bulb2 = Bulb.create! name: "other", car: car
2276
2743
 
2277
- assert_equal [bulb], Car.find(car.id).all_bulbs
2278
- assert_equal [bulb], Car.includes(:all_bulbs).find(car.id).all_bulbs
2279
- assert_equal [bulb], Car.eager_load(:all_bulbs).find(car.id).all_bulbs
2744
+ assert_equal [bulb1, bulb2], Car.includes(:all_bulbs2).find(car.id).all_bulbs2.sort_by(&:id)
2745
+ assert_equal [bulb1, bulb2], Car.eager_load(:all_bulbs2).find(car.id).all_bulbs2.sort_by(&:id)
2280
2746
  end
2281
2747
 
2282
2748
  test "raises RecordNotDestroyed when replaced child can't be destroyed" do
@@ -2291,7 +2757,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2291
2757
  assert_equal "Failed to destroy the record", error.message
2292
2758
  end
2293
2759
 
2294
- test 'updates counter cache when default scope is given' do
2760
+ test "updates counter cache when default scope is given" do
2295
2761
  topic = DefaultRejectedTopic.create approved: true
2296
2762
 
2297
2763
  assert_difference "topic.reload.replies_count", 1 do
@@ -2299,8 +2765,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2299
2765
  end
2300
2766
  end
2301
2767
 
2302
- test 'dangerous association name raises ArgumentError' do
2303
- [:errors, 'errors', :save, 'save'].each do |name|
2768
+ test "dangerous association name raises ArgumentError" do
2769
+ [:errors, "errors", :save, "save"].each do |name|
2304
2770
  assert_raises(ArgumentError, "Association #{name} should not be allowed") do
2305
2771
  Class.new(ActiveRecord::Base) do
2306
2772
  has_many name
@@ -2309,16 +2775,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2309
2775
  end
2310
2776
  end
2311
2777
 
2312
- test 'passes custom context validation to validate children' do
2778
+ test "passes custom context validation to validate children" do
2313
2779
  pirate = FamousPirate.new
2314
2780
  pirate.famous_ships << ship = FamousShip.new
2315
2781
 
2316
- assert pirate.valid?
2782
+ assert_predicate pirate, :valid?
2317
2783
  assert_not pirate.valid?(:conference)
2318
2784
  assert_equal "can't be blank", ship.errors[:name].first
2319
2785
  end
2320
2786
 
2321
- test 'association with instance dependent scope' do
2787
+ test "association with instance dependent scope" do
2322
2788
  bob = authors(:bob)
2323
2789
  Post.create!(title: "signed post by bob", body: "stuff", author: authors(:bob))
2324
2790
  Post.create!(title: "anonymous post", body: "more stuff", author: authors(:bob))
@@ -2328,22 +2794,26 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2328
2794
  assert_equal [], authors(:david).posts_with_signature.map(&:title)
2329
2795
  end
2330
2796
 
2331
- test 'associations autosaves when object is already persisted' do
2797
+ test "associations autosaves when object is already persisted" do
2332
2798
  bulb = Bulb.create!
2333
2799
  tyre = Tyre.create!
2334
2800
 
2335
- car = Car.create! do |c|
2801
+ car = Car.create!(name: "honda") do |c|
2336
2802
  c.bulbs << bulb
2337
2803
  c.tyres << tyre
2338
2804
  end
2339
2805
 
2806
+ assert_equal [nil, "honda"], car.saved_change_to_name
2807
+
2340
2808
  assert_equal 1, car.bulbs.count
2341
2809
  assert_equal 1, car.tyres.count
2342
2810
  end
2343
2811
 
2344
- test 'associations replace in memory when records have the same id' do
2812
+ test "associations replace in memory when records have the same id" do
2345
2813
  bulb = Bulb.create!
2346
- car = Car.create!(bulbs: [bulb])
2814
+ car = Car.create!(name: "honda", bulbs: [bulb])
2815
+
2816
+ assert_equal [nil, "honda"], car.saved_change_to_name
2347
2817
 
2348
2818
  new_bulb = Bulb.find(bulb.id)
2349
2819
  new_bulb.name = "foo"
@@ -2352,9 +2822,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2352
2822
  assert_equal "foo", car.bulbs.first.name
2353
2823
  end
2354
2824
 
2355
- test 'in memory replacement executes no queries' do
2825
+ test "in memory replacement executes no queries" do
2356
2826
  bulb = Bulb.create!
2357
- car = Car.create!(bulbs: [bulb])
2827
+ car = Car.create!(name: "honda", bulbs: [bulb])
2828
+
2829
+ assert_equal [nil, "honda"], car.saved_change_to_name
2358
2830
 
2359
2831
  new_bulb = Bulb.find(bulb.id)
2360
2832
 
@@ -2363,7 +2835,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2363
2835
  end
2364
2836
  end
2365
2837
 
2366
- test 'in memory replacements do not execute callbacks' do
2838
+ test "in memory replacements do not execute callbacks" do
2367
2839
  raise_after_add = false
2368
2840
  klass = Class.new(ActiveRecord::Base) do
2369
2841
  self.table_name = :cars
@@ -2384,9 +2856,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2384
2856
  end
2385
2857
  end
2386
2858
 
2387
- test 'in memory replacements sets inverse instance' do
2859
+ test "in memory replacements sets inverse instance" do
2388
2860
  bulb = Bulb.create!
2389
- car = Car.create!(bulbs: [bulb])
2861
+ car = Car.create!(name: "honda", bulbs: [bulb])
2862
+
2863
+ assert_equal [nil, "honda"], car.saved_change_to_name
2390
2864
 
2391
2865
  new_bulb = Bulb.find(bulb.id)
2392
2866
  car.bulbs = [new_bulb]
@@ -2394,10 +2868,21 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2394
2868
  assert_same car, new_bulb.car
2395
2869
  end
2396
2870
 
2397
- test 'in memory replacement maintains order' do
2871
+ test "reattach to new objects replaces inverse association and foreign key" do
2872
+ bulb = Bulb.create!(car: Car.create!)
2873
+ assert bulb.car_id
2874
+ car = Car.new
2875
+ car.bulbs << bulb
2876
+ assert_equal car, bulb.car
2877
+ assert_nil bulb.car_id
2878
+ end
2879
+
2880
+ test "in memory replacement maintains order" do
2398
2881
  first_bulb = Bulb.create!
2399
2882
  second_bulb = Bulb.create!
2400
- car = Car.create!(bulbs: [first_bulb, second_bulb])
2883
+ car = Car.create!(name: "honda", bulbs: [first_bulb, second_bulb])
2884
+
2885
+ assert_equal [nil, "honda"], car.saved_change_to_name
2401
2886
 
2402
2887
  same_bulb = Bulb.find(first_bulb.id)
2403
2888
  car.bulbs = [second_bulb, same_bulb]
@@ -2405,8 +2890,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2405
2890
  assert_equal [first_bulb, second_bulb], car.bulbs
2406
2891
  end
2407
2892
 
2893
+ test "association size calculation works with default scoped selects when not previously fetched" do
2894
+ firm = Firm.create!(name: "Firm")
2895
+ 5.times { firm.developers_with_select << Developer.create!(name: "Developer") }
2896
+
2897
+ same_firm = Firm.find(firm.id)
2898
+ assert_equal 5, same_firm.developers_with_select.size
2899
+ end
2900
+
2408
2901
  test "prevent double insertion of new object when the parent association loaded in the after save callback" do
2409
- reset_callbacks(:save, Bulb) do
2902
+ reset_callbacks(Bulb, :save) do
2410
2903
  Bulb.after_save { |record| record.car.bulbs.load }
2411
2904
 
2412
2905
  car = Car.create!
@@ -2417,7 +2910,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2417
2910
  end
2418
2911
 
2419
2912
  test "prevent double firing the before save callback of new object when the parent association saved in the callback" do
2420
- reset_callbacks(:save, Bulb) do
2913
+ reset_callbacks(Bulb, :save) do
2421
2914
  count = 0
2422
2915
  Bulb.before_save { |record| record.car.save && count += 1 }
2423
2916
 
@@ -2428,10 +2921,68 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2428
2921
  end
2429
2922
  end
2430
2923
 
2431
- def test_association_force_reload_with_only_true_is_deprecated
2432
- company = Company.find(1)
2924
+ test "calling size on an association that has not been loaded performs a query" do
2925
+ car = Car.create!
2926
+ Bulb.create(car_id: car.id)
2927
+
2928
+ car_two = Car.create!
2929
+
2930
+ assert_queries(1) do
2931
+ assert_equal 1, car.bulbs.size
2932
+ end
2433
2933
 
2434
- assert_deprecated { company.clients_of_firm(true) }
2934
+ assert_queries(1) do
2935
+ assert_equal 0, car_two.bulbs.size
2936
+ end
2937
+ end
2938
+
2939
+ test "calling size on an association that has been loaded does not perform query" do
2940
+ car = Car.create!
2941
+ Bulb.create(car_id: car.id)
2942
+ car.bulb_ids
2943
+
2944
+ car_two = Car.create!
2945
+ car_two.bulb_ids
2946
+
2947
+ assert_no_queries do
2948
+ assert_equal 1, car.bulbs.size
2949
+ end
2950
+
2951
+ assert_no_queries do
2952
+ assert_equal 0, car_two.bulbs.size
2953
+ end
2954
+ end
2955
+
2956
+ test "calling empty on an association that has not been loaded performs a query" do
2957
+ car = Car.create!
2958
+ Bulb.create(car_id: car.id)
2959
+
2960
+ car_two = Car.create!
2961
+
2962
+ assert_queries(1) do
2963
+ assert_not_empty car.bulbs
2964
+ end
2965
+
2966
+ assert_queries(1) do
2967
+ assert_empty car_two.bulbs
2968
+ end
2969
+ end
2970
+
2971
+ test "calling empty on an association that has been loaded does not performs query" do
2972
+ car = Car.create!
2973
+ Bulb.create(car_id: car.id)
2974
+ car.bulb_ids
2975
+
2976
+ car_two = Car.create!
2977
+ car_two.bulb_ids
2978
+
2979
+ assert_no_queries do
2980
+ assert_not_empty car.bulbs
2981
+ end
2982
+
2983
+ assert_no_queries do
2984
+ assert_empty car_two.bulbs
2985
+ end
2435
2986
  end
2436
2987
 
2437
2988
  class AuthorWithErrorDestroyingAssociation < ActiveRecord::Base
@@ -2465,15 +3016,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2465
3016
  end
2466
3017
 
2467
3018
  def test_ids_reader_memoization
2468
- car = Car.create!(name: 'Tofaş')
3019
+ car = Car.create!(name: "Tofaş")
2469
3020
  bulb = Bulb.create!(car: car)
2470
3021
 
2471
3022
  assert_equal [bulb.id], car.bulb_ids
2472
3023
  assert_no_queries { car.bulb_ids }
3024
+
3025
+ bulb2 = car.bulbs.create!
3026
+
3027
+ assert_equal [bulb.id, bulb2.id], car.bulb_ids
3028
+ assert_no_queries { car.bulb_ids }
2473
3029
  end
2474
3030
 
2475
3031
  def test_loading_association_in_validate_callback_doesnt_affect_persistence
2476
- reset_callbacks(:validation, Bulb) do
3032
+ reset_callbacks(Bulb, :validation) do
2477
3033
  Bulb.after_validation { |record| record.car.bulbs.load }
2478
3034
 
2479
3035
  car = Car.create!(name: "Car")
@@ -2483,19 +3039,36 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
2483
3039
  end
2484
3040
  end
2485
3041
 
2486
- private
2487
-
2488
- def reset_callbacks(kind, klass)
2489
- old_callbacks = {}
2490
- old_callbacks[klass] = klass.send("_#{kind}_callbacks").dup
2491
- klass.subclasses.each do |subclass|
2492
- old_callbacks[subclass] = subclass.send("_#{kind}_callbacks").dup
2493
- end
2494
- yield
2495
- ensure
2496
- klass.send("_#{kind}_callbacks=", old_callbacks[klass])
2497
- klass.subclasses.each do |subclass|
2498
- subclass.send("_#{kind}_callbacks=", old_callbacks[subclass])
3042
+ def test_create_children_could_be_rolled_back_by_after_save
3043
+ firm = Firm.create!(name: "A New Firm, Inc")
3044
+ assert_no_difference "Client.count" do
3045
+ client = firm.clients.create(name: "New Client") do |cli|
3046
+ cli.rollback_on_save = true
3047
+ assert_not cli.rollback_on_create_called
2499
3048
  end
3049
+ assert client.rollback_on_create_called
3050
+ end
3051
+ end
3052
+
3053
+ def test_has_many_with_out_of_range_value
3054
+ reference = Reference.create!(id: 2147483648) # out of range in the integer
3055
+ assert_equal [], reference.ideal_jobs
3056
+ end
3057
+
3058
+ def test_has_many_preloading_with_duplicate_records
3059
+ posts = Post.joins(:comments).preload(:comments).order(:id).to_a
3060
+ assert_equal [1, 2], posts.first.comments.map(&:id).sort
3061
+ end
3062
+
3063
+ def test_has_many_association_with_same_foreign_key_name
3064
+ assert_nothing_raised do
3065
+ firm = Firm.find(15)
3066
+ assert_not_nil(firm.comments.first)
3067
+ end
3068
+ end
3069
+
3070
+ private
3071
+ def force_signal37_to_load_all_clients_of_firm
3072
+ companies(:first_firm).clients_of_firm.load_target
2500
3073
  end
2501
3074
  end