ibm_db 5.2.0-x86-mingw32 → 5.3.2-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (621) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/ext/Makefile +15 -13
  5. data/ext/ibm_db.c +62 -57
  6. data/ext/ibm_db.o +0 -0
  7. data/ext/ibm_db.so +0 -0
  8. data/ext/mkmf.log +26 -24
  9. data/ext/ruby_ibm_db_cli.c +1 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
  12. data/lib/ibm_db.so +1 -0
  13. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  14. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  15. data/test/activejob/destroy_association_async_test.rb +305 -0
  16. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  17. data/test/activejob/helper.rb +15 -0
  18. data/test/assets/schema_dump_5_1.yml +345 -0
  19. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  20. data/test/cases/adapter_test.rb +432 -218
  21. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  22. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  23. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  24. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  25. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  26. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  27. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  28. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  29. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  30. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  31. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  32. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  33. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  34. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  35. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  36. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  38. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  39. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  40. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  42. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  43. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  44. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  45. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  46. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  47. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  48. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  49. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  50. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  51. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  52. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  53. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  54. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  55. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  56. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  57. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  58. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  59. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  60. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  61. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  62. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  63. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  64. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  65. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  66. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  67. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  68. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  69. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  70. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  71. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  72. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  73. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  74. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  75. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  76. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  77. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  78. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  79. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  80. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  81. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  82. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  83. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  84. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  85. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  86. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  87. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  88. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  89. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  90. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  91. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  92. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  93. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  94. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  95. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  96. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  97. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  98. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  99. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  100. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  101. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  102. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  103. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  104. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  105. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  106. data/test/cases/aggregations_test.rb +14 -12
  107. data/test/cases/annotate_test.rb +46 -0
  108. data/test/cases/ar_schema_test.rb +153 -86
  109. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  110. data/test/cases/arel/attributes/math_test.rb +83 -0
  111. data/test/cases/arel/attributes_test.rb +27 -0
  112. data/test/cases/arel/collectors/bind_test.rb +40 -0
  113. data/test/cases/arel/collectors/composite_test.rb +47 -0
  114. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  115. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  116. data/test/cases/arel/crud_test.rb +65 -0
  117. data/test/cases/arel/delete_manager_test.rb +53 -0
  118. data/test/cases/arel/factory_methods_test.rb +46 -0
  119. data/test/cases/arel/helper.rb +45 -0
  120. data/test/cases/arel/insert_manager_test.rb +241 -0
  121. data/test/cases/arel/nodes/and_test.rb +30 -0
  122. data/test/cases/arel/nodes/as_test.rb +36 -0
  123. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  124. data/test/cases/arel/nodes/bin_test.rb +35 -0
  125. data/test/cases/arel/nodes/binary_test.rb +29 -0
  126. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  127. data/test/cases/arel/nodes/case_test.rb +96 -0
  128. data/test/cases/arel/nodes/casted_test.rb +18 -0
  129. data/test/cases/arel/nodes/comment_test.rb +22 -0
  130. data/test/cases/arel/nodes/count_test.rb +35 -0
  131. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  132. data/test/cases/arel/nodes/descending_test.rb +46 -0
  133. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  134. data/test/cases/arel/nodes/equality_test.rb +62 -0
  135. data/test/cases/arel/nodes/extract_test.rb +43 -0
  136. data/test/cases/arel/nodes/false_test.rb +21 -0
  137. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  138. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  139. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  140. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  141. data/test/cases/arel/nodes/node_test.rb +22 -0
  142. data/test/cases/arel/nodes/not_test.rb +31 -0
  143. data/test/cases/arel/nodes/or_test.rb +36 -0
  144. data/test/cases/arel/nodes/over_test.rb +69 -0
  145. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  146. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  147. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  148. data/test/cases/arel/nodes/sum_test.rb +35 -0
  149. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  150. data/test/cases/arel/nodes/true_test.rb +21 -0
  151. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  152. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  153. data/test/cases/arel/nodes/window_test.rb +81 -0
  154. data/test/cases/arel/nodes_test.rb +34 -0
  155. data/test/cases/arel/select_manager_test.rb +1238 -0
  156. data/test/cases/arel/support/fake_record.rb +135 -0
  157. data/test/cases/arel/table_test.rb +216 -0
  158. data/test/cases/arel/update_manager_test.rb +126 -0
  159. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  160. data/test/cases/arel/visitors/dot_test.rb +90 -0
  161. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  162. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  163. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  164. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  165. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  166. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  167. data/test/cases/associations/callbacks_test.rb +56 -38
  168. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  169. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  170. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  171. data/test/cases/associations/eager_singularization_test.rb +21 -21
  172. data/test/cases/associations/eager_test.rb +559 -415
  173. data/test/cases/associations/extension_test.rb +18 -12
  174. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  175. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  176. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  177. data/test/cases/associations/has_one_associations_test.rb +294 -129
  178. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  179. data/test/cases/associations/inner_join_association_test.rb +114 -38
  180. data/test/cases/associations/inverse_associations_test.rb +606 -398
  181. data/test/cases/associations/join_model_test.rb +158 -148
  182. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  183. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  184. data/test/cases/associations/required_test.rb +35 -10
  185. data/test/cases/associations_test.rb +241 -110
  186. data/test/cases/attribute_methods/read_test.rb +11 -11
  187. data/test/cases/attribute_methods_test.rb +413 -298
  188. data/test/cases/attributes_test.rb +145 -27
  189. data/test/cases/autosave_association_test.rb +681 -436
  190. data/test/cases/base_prevent_writes_test.rb +229 -0
  191. data/test/cases/base_test.rb +599 -542
  192. data/test/cases/batches_test.rb +288 -82
  193. data/test/cases/binary_test.rb +26 -31
  194. data/test/cases/bind_parameter_test.rb +194 -21
  195. data/test/cases/boolean_test.rb +52 -0
  196. data/test/cases/cache_key_test.rb +110 -5
  197. data/test/cases/calculations_test.rb +740 -177
  198. data/test/cases/callbacks_test.rb +74 -207
  199. data/test/cases/clone_test.rb +15 -10
  200. data/test/cases/coders/json_test.rb +2 -0
  201. data/test/cases/coders/yaml_column_test.rb +16 -13
  202. data/test/cases/collection_cache_key_test.rb +177 -20
  203. data/test/cases/column_alias_test.rb +9 -7
  204. data/test/cases/column_definition_test.rb +10 -68
  205. data/test/cases/comment_test.rb +166 -107
  206. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  207. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  208. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  209. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  210. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  211. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  212. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  213. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  214. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  215. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  216. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  217. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  218. data/test/cases/connection_management_test.rb +13 -11
  219. data/test/cases/connection_pool_test.rb +316 -83
  220. data/test/cases/core_test.rb +82 -58
  221. data/test/cases/counter_cache_test.rb +204 -50
  222. data/test/cases/custom_locking_test.rb +5 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  224. data/test/cases/database_configurations/resolver_test.rb +150 -0
  225. data/test/cases/database_configurations_test.rb +145 -0
  226. data/test/cases/database_selector_test.rb +296 -0
  227. data/test/cases/database_statements_test.rb +18 -16
  228. data/test/cases/date_test.rb +8 -16
  229. data/test/cases/date_time_precision_test.rb +100 -78
  230. data/test/cases/date_time_test.rb +23 -8
  231. data/test/cases/defaults_test.rb +106 -71
  232. data/test/cases/delegated_type_test.rb +57 -0
  233. data/test/cases/dirty_test.rb +419 -223
  234. data/test/cases/disconnected_test.rb +6 -6
  235. data/test/cases/dup_test.rb +54 -27
  236. data/test/cases/enum_test.rb +461 -82
  237. data/test/cases/errors_test.rb +7 -7
  238. data/test/cases/explain_subscriber_test.rb +17 -15
  239. data/test/cases/explain_test.rb +11 -19
  240. data/test/cases/filter_attributes_test.rb +153 -0
  241. data/test/cases/finder_respond_to_test.rb +14 -14
  242. data/test/cases/finder_test.rb +669 -287
  243. data/test/cases/fixture_set/file_test.rb +34 -38
  244. data/test/cases/fixtures_test.rb +833 -176
  245. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  246. data/test/cases/habtm_destroy_order_test.rb +25 -25
  247. data/test/cases/helper.rb +78 -49
  248. data/test/cases/hot_compatibility_test.rb +33 -32
  249. data/test/cases/i18n_test.rb +18 -17
  250. data/test/cases/inheritance_test.rb +180 -115
  251. data/test/cases/insert_all_test.rb +489 -0
  252. data/test/cases/instrumentation_test.rb +101 -0
  253. data/test/cases/integration_test.rb +119 -31
  254. data/test/cases/invalid_connection_test.rb +18 -16
  255. data/test/cases/invertible_migration_test.rb +183 -43
  256. data/test/cases/json_attribute_test.rb +35 -0
  257. data/test/cases/json_serialization_test.rb +57 -58
  258. data/test/cases/json_shared_test_cases.rb +290 -0
  259. data/test/cases/locking_test.rb +413 -119
  260. data/test/cases/log_subscriber_test.rb +68 -26
  261. data/test/cases/marshal_serialization_test.rb +39 -0
  262. data/test/cases/migration/change_schema_test.rb +118 -72
  263. data/test/cases/migration/change_table_test.rb +138 -30
  264. data/test/cases/migration/check_constraint_test.rb +162 -0
  265. data/test/cases/migration/column_attributes_test.rb +45 -35
  266. data/test/cases/migration/column_positioning_test.rb +18 -6
  267. data/test/cases/migration/columns_test.rb +93 -77
  268. data/test/cases/migration/command_recorder_test.rb +121 -34
  269. data/test/cases/migration/compatibility_test.rb +578 -23
  270. data/test/cases/migration/create_join_table_test.rb +35 -25
  271. data/test/cases/migration/foreign_key_test.rb +503 -284
  272. data/test/cases/migration/helper.rb +4 -3
  273. data/test/cases/migration/index_test.rb +119 -70
  274. data/test/cases/migration/logger_test.rb +9 -6
  275. data/test/cases/migration/pending_migrations_test.rb +88 -34
  276. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  277. data/test/cases/migration/references_index_test.rb +38 -19
  278. data/test/cases/migration/references_statements_test.rb +15 -14
  279. data/test/cases/migration/rename_table_test.rb +53 -30
  280. data/test/cases/migration_test.rb +637 -269
  281. data/test/cases/migrator_test.rb +191 -135
  282. data/test/cases/mixin_test.rb +7 -11
  283. data/test/cases/modules_test.rb +36 -34
  284. data/test/cases/multi_db_migrator_test.rb +223 -0
  285. data/test/cases/multiparameter_attributes_test.rb +60 -33
  286. data/test/cases/multiple_db_test.rb +16 -22
  287. data/test/cases/nested_attributes_test.rb +341 -320
  288. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  289. data/test/cases/null_relation_test.rb +84 -0
  290. data/test/cases/numeric_data_test.rb +93 -0
  291. data/test/cases/persistence_test.rb +361 -269
  292. data/test/cases/pooled_connections_test.rb +18 -26
  293. data/test/cases/prepared_statement_status_test.rb +48 -0
  294. data/test/cases/primary_keys_test.rb +210 -104
  295. data/test/cases/query_cache_test.rb +610 -141
  296. data/test/cases/quoting_test.rb +132 -31
  297. data/test/cases/readonly_test.rb +49 -48
  298. data/test/cases/reaper_test.rb +146 -32
  299. data/test/cases/reflection_test.rb +167 -156
  300. data/test/cases/relation/delegation_test.rb +49 -36
  301. data/test/cases/relation/delete_all_test.rb +117 -0
  302. data/test/cases/relation/merging_test.rb +319 -42
  303. data/test/cases/relation/mutation_test.rb +55 -93
  304. data/test/cases/relation/or_test.rb +129 -29
  305. data/test/cases/relation/predicate_builder_test.rb +21 -6
  306. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  307. data/test/cases/relation/select_test.rb +67 -0
  308. data/test/cases/relation/update_all_test.rb +317 -0
  309. data/test/cases/relation/where_chain_test.rb +68 -32
  310. data/test/cases/relation/where_clause_test.rb +136 -61
  311. data/test/cases/relation/where_test.rb +155 -48
  312. data/test/cases/relation_test.rb +266 -112
  313. data/test/cases/relations_test.rb +969 -744
  314. data/test/cases/reload_models_test.rb +13 -9
  315. data/test/cases/reserved_word_test.rb +141 -0
  316. data/test/cases/result_test.rb +68 -17
  317. data/test/cases/sanitize_test.rb +87 -71
  318. data/test/cases/schema_dumper_test.rb +221 -128
  319. data/test/cases/schema_loading_test.rb +3 -2
  320. data/test/cases/scoping/default_scoping_test.rb +185 -144
  321. data/test/cases/scoping/named_scoping_test.rb +177 -89
  322. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  323. data/test/cases/secure_token_test.rb +18 -3
  324. data/test/cases/serialization_test.rb +30 -28
  325. data/test/cases/serialized_attribute_test.rb +133 -42
  326. data/test/cases/signed_id_test.rb +168 -0
  327. data/test/cases/statement_cache_test.rb +41 -24
  328. data/test/cases/statement_invalid_test.rb +42 -0
  329. data/test/cases/store_test.rb +180 -55
  330. data/test/cases/strict_loading_test.rb +473 -0
  331. data/test/cases/suppressor_test.rb +26 -12
  332. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  333. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  334. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  335. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  336. data/test/cases/test_case.rb +51 -40
  337. data/test/cases/test_databases_test.rb +79 -0
  338. data/test/cases/test_fixtures_test.rb +79 -19
  339. data/test/cases/time_precision_test.rb +98 -76
  340. data/test/cases/timestamp_test.rb +102 -99
  341. data/test/cases/touch_later_test.rb +12 -10
  342. data/test/cases/transaction_callbacks_test.rb +344 -90
  343. data/test/cases/transaction_isolation_test.rb +12 -12
  344. data/test/cases/transactions_test.rb +612 -162
  345. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  346. data/test/cases/type/date_time_test.rb +4 -2
  347. data/test/cases/type/integer_test.rb +4 -2
  348. data/test/cases/type/string_test.rb +10 -8
  349. data/test/cases/type/time_test.rb +28 -0
  350. data/test/cases/type/type_map_test.rb +29 -28
  351. data/test/cases/type/unsigned_integer_test.rb +19 -0
  352. data/test/cases/type_test.rb +2 -0
  353. data/test/cases/types_test.rb +3 -1
  354. data/test/cases/unconnected_test.rb +14 -1
  355. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  356. data/test/cases/validations/absence_validation_test.rb +19 -17
  357. data/test/cases/validations/association_validation_test.rb +30 -28
  358. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  359. data/test/cases/validations/i18n_validation_test.rb +22 -21
  360. data/test/cases/validations/length_validation_test.rb +34 -33
  361. data/test/cases/validations/numericality_validation_test.rb +181 -0
  362. data/test/cases/validations/presence_validation_test.rb +21 -19
  363. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  364. data/test/cases/validations_repair_helper.rb +2 -0
  365. data/test/cases/validations_test.rb +61 -26
  366. data/test/cases/view_test.rb +122 -116
  367. data/test/cases/yaml_serialization_test.rb +79 -34
  368. data/test/config.example.yml +19 -19
  369. data/test/config.rb +3 -1
  370. data/test/config.yml +16 -6
  371. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  372. data/test/fixtures/author_addresses.yml +1 -8
  373. data/test/fixtures/authors.yml +1 -7
  374. data/test/fixtures/binaries.yml +4 -0
  375. data/test/fixtures/books.yml +9 -2
  376. data/test/fixtures/categories_posts.yml +3 -0
  377. data/test/fixtures/citations.yml +5 -0
  378. data/test/fixtures/comments.yml +7 -0
  379. data/test/fixtures/companies.yml +5 -0
  380. data/test/fixtures/computers.yml +2 -0
  381. data/test/fixtures/customers.yml +10 -1
  382. data/test/fixtures/developers.yml +1 -1
  383. data/test/fixtures/essays.yml +10 -0
  384. data/test/fixtures/faces.yml +3 -3
  385. data/test/fixtures/humans.yml +5 -0
  386. data/test/fixtures/interests.yml +7 -7
  387. data/test/fixtures/memberships.yml +7 -0
  388. data/test/fixtures/minimalistics.yml +3 -0
  389. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  390. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  391. data/test/fixtures/naked/yml/parrots.yml +1 -0
  392. data/test/fixtures/other_books.yml +26 -0
  393. data/test/fixtures/other_posts.yml +1 -0
  394. data/test/fixtures/parrots.yml +7 -1
  395. data/test/fixtures/pirates.yml +3 -0
  396. data/test/fixtures/posts.yml +11 -3
  397. data/test/fixtures/readers.yml +6 -0
  398. data/test/fixtures/reserved_words/values.yml +2 -2
  399. data/test/fixtures/sponsors.yml +3 -0
  400. data/test/fixtures/strict_zines.yml +2 -0
  401. data/test/fixtures/subscribers.yml +1 -1
  402. data/test/fixtures/tasks.yml +1 -1
  403. data/test/fixtures/warehouse-things.yml +3 -0
  404. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  405. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  406. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  407. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  408. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  409. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  410. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  411. data/test/migrations/rename/1_we_need_things.rb +2 -0
  412. data/test/migrations/rename/2_rename_things.rb +2 -0
  413. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  414. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  415. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  416. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  417. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  418. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  419. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  420. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  421. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  422. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  423. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  424. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  425. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  426. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  427. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  428. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  429. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  430. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  431. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  432. data/test/models/account.rb +46 -0
  433. data/test/models/admin/account.rb +3 -1
  434. data/test/models/admin/randomly_named_c1.rb +2 -0
  435. data/test/models/admin/user.rb +16 -8
  436. data/test/models/admin.rb +4 -2
  437. data/test/models/aircraft.rb +3 -1
  438. data/test/models/arunit2_model.rb +2 -0
  439. data/test/models/author.rb +153 -102
  440. data/test/models/auto_id.rb +2 -0
  441. data/test/models/autoloadable/extra_firm.rb +2 -0
  442. data/test/models/binary.rb +3 -1
  443. data/test/models/binary_field.rb +6 -0
  444. data/test/models/bird.rb +13 -1
  445. data/test/models/book.rb +14 -4
  446. data/test/models/book_destroy_async.rb +24 -0
  447. data/test/models/boolean.rb +5 -0
  448. data/test/models/bulb.rb +13 -4
  449. data/test/models/cake_designer.rb +2 -0
  450. data/test/models/car.rb +17 -10
  451. data/test/models/carrier.rb +2 -0
  452. data/test/models/cart.rb +5 -0
  453. data/test/models/cat.rb +2 -0
  454. data/test/models/categorization.rb +8 -6
  455. data/test/models/category.rb +28 -16
  456. data/test/models/chef.rb +2 -0
  457. data/test/models/citation.rb +5 -1
  458. data/test/models/club.rb +13 -10
  459. data/test/models/college.rb +4 -2
  460. data/test/models/column.rb +2 -0
  461. data/test/models/column_name.rb +2 -0
  462. data/test/models/comment.rb +32 -10
  463. data/test/models/company.rb +102 -106
  464. data/test/models/company_in_module.rb +27 -26
  465. data/test/models/computer.rb +3 -1
  466. data/test/models/contact.rb +15 -13
  467. data/test/models/content.rb +5 -3
  468. data/test/models/contract.rb +21 -3
  469. data/test/models/country.rb +2 -4
  470. data/test/models/course.rb +3 -1
  471. data/test/models/customer.rb +10 -8
  472. data/test/models/customer_carrier.rb +2 -0
  473. data/test/models/dashboard.rb +2 -0
  474. data/test/models/default.rb +2 -0
  475. data/test/models/department.rb +2 -0
  476. data/test/models/destroy_async_parent.rb +15 -0
  477. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  478. data/test/models/developer.rb +152 -85
  479. data/test/models/dl_keyed_belongs_to.rb +13 -0
  480. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  481. data/test/models/dl_keyed_has_many.rb +5 -0
  482. data/test/models/dl_keyed_has_many_through.rb +5 -0
  483. data/test/models/dl_keyed_has_one.rb +5 -0
  484. data/test/models/dl_keyed_join.rb +10 -0
  485. data/test/models/dog.rb +2 -0
  486. data/test/models/dog_lover.rb +2 -0
  487. data/test/models/doubloon.rb +3 -1
  488. data/test/models/drink_designer.rb +17 -0
  489. data/test/models/edge.rb +4 -2
  490. data/test/models/electron.rb +2 -0
  491. data/test/models/engine.rb +3 -2
  492. data/test/models/entrant.rb +2 -0
  493. data/test/models/entry.rb +5 -0
  494. data/test/models/essay.rb +6 -3
  495. data/test/models/essay_destroy_async.rb +12 -0
  496. data/test/models/event.rb +3 -1
  497. data/test/models/eye.rb +5 -3
  498. data/test/models/face.rb +14 -6
  499. data/test/models/family.rb +6 -0
  500. data/test/models/family_tree.rb +6 -0
  501. data/test/models/friendship.rb +5 -3
  502. data/test/models/frog.rb +8 -0
  503. data/test/models/guid.rb +3 -1
  504. data/test/models/guitar.rb +2 -0
  505. data/test/models/hotel.rb +5 -3
  506. data/test/models/human.rb +39 -0
  507. data/test/models/image.rb +3 -1
  508. data/test/models/interest.rb +14 -3
  509. data/test/models/invoice.rb +4 -2
  510. data/test/models/item.rb +3 -1
  511. data/test/models/job.rb +5 -3
  512. data/test/models/joke.rb +4 -2
  513. data/test/models/keyboard.rb +3 -1
  514. data/test/models/legacy_thing.rb +2 -0
  515. data/test/models/lesson.rb +2 -0
  516. data/test/models/line_item.rb +3 -1
  517. data/test/models/liquid.rb +2 -0
  518. data/test/models/matey.rb +3 -1
  519. data/test/models/measurement.rb +4 -0
  520. data/test/models/member.rb +23 -20
  521. data/test/models/member_detail.rb +3 -0
  522. data/test/models/member_type.rb +2 -0
  523. data/test/models/membership.rb +4 -1
  524. data/test/models/mentor.rb +3 -1
  525. data/test/models/message.rb +5 -0
  526. data/test/models/minimalistic.rb +2 -0
  527. data/test/models/minivan.rb +3 -2
  528. data/test/models/mixed_case_monkey.rb +3 -1
  529. data/test/models/molecule.rb +2 -0
  530. data/test/models/mouse.rb +6 -0
  531. data/test/models/movie.rb +2 -0
  532. data/test/models/node.rb +4 -2
  533. data/test/models/non_primary_key.rb +2 -0
  534. data/test/models/notification.rb +2 -0
  535. data/test/models/numeric_data.rb +12 -0
  536. data/test/models/order.rb +4 -2
  537. data/test/models/organization.rb +9 -7
  538. data/test/models/other_dog.rb +3 -1
  539. data/test/models/owner.rb +6 -4
  540. data/test/models/parrot.rb +12 -4
  541. data/test/models/person.rb +59 -54
  542. data/test/models/personal_legacy_thing.rb +3 -1
  543. data/test/models/pet.rb +4 -2
  544. data/test/models/pet_treasure.rb +2 -0
  545. data/test/models/pirate.rb +67 -43
  546. data/test/models/possession.rb +3 -1
  547. data/test/models/post.rb +184 -86
  548. data/test/models/price_estimate.rb +11 -1
  549. data/test/models/professor.rb +3 -1
  550. data/test/models/project.rb +14 -12
  551. data/test/models/publisher/article.rb +2 -0
  552. data/test/models/publisher/magazine.rb +2 -0
  553. data/test/models/publisher.rb +2 -0
  554. data/test/models/randomly_named_c1.rb +2 -0
  555. data/test/models/rating.rb +5 -1
  556. data/test/models/reader.rb +7 -5
  557. data/test/models/recipe.rb +2 -0
  558. data/test/models/record.rb +2 -0
  559. data/test/models/reference.rb +6 -3
  560. data/test/models/reply.rb +39 -21
  561. data/test/models/room.rb +6 -0
  562. data/test/models/section.rb +6 -0
  563. data/test/models/seminar.rb +6 -0
  564. data/test/models/session.rb +6 -0
  565. data/test/models/ship.rb +12 -9
  566. data/test/models/ship_part.rb +5 -3
  567. data/test/models/shop.rb +4 -2
  568. data/test/models/shop_account.rb +2 -0
  569. data/test/models/speedometer.rb +2 -0
  570. data/test/models/sponsor.rb +8 -5
  571. data/test/models/squeak.rb +6 -0
  572. data/test/models/strict_zine.rb +7 -0
  573. data/test/models/string_key_object.rb +2 -0
  574. data/test/models/student.rb +2 -0
  575. data/test/models/subscriber.rb +4 -2
  576. data/test/models/subscription.rb +5 -1
  577. data/test/models/tag.rb +6 -3
  578. data/test/models/tagging.rb +13 -6
  579. data/test/models/task.rb +2 -0
  580. data/test/models/topic.rb +54 -19
  581. data/test/models/toy.rb +4 -0
  582. data/test/models/traffic_light.rb +2 -0
  583. data/test/models/treasure.rb +5 -3
  584. data/test/models/treaty.rb +2 -4
  585. data/test/models/tree.rb +2 -0
  586. data/test/models/tuning_peg.rb +2 -0
  587. data/test/models/tyre.rb +2 -0
  588. data/test/models/user.rb +12 -4
  589. data/test/models/uuid_child.rb +2 -0
  590. data/test/models/uuid_item.rb +2 -0
  591. data/test/models/uuid_parent.rb +2 -0
  592. data/test/models/vegetables.rb +12 -3
  593. data/test/models/vertex.rb +6 -4
  594. data/test/models/warehouse_thing.rb +2 -0
  595. data/test/models/wheel.rb +3 -1
  596. data/test/models/without_table.rb +3 -1
  597. data/test/models/zine.rb +3 -1
  598. data/test/schema/mysql2_specific_schema.rb +49 -35
  599. data/test/schema/oracle_specific_schema.rb +13 -15
  600. data/test/schema/postgresql_specific_schema.rb +51 -40
  601. data/test/schema/schema.rb +334 -154
  602. data/test/schema/sqlite_specific_schema.rb +9 -16
  603. data/test/support/config.rb +26 -26
  604. data/test/support/connection.rb +14 -8
  605. data/test/support/connection_helper.rb +3 -1
  606. data/test/support/ddl_helper.rb +2 -0
  607. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  608. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  609. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  610. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  611. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  617. data/test/support/schema_dumping_helper.rb +2 -0
  618. data/test/support/stubs/strong_parameters.rb +40 -0
  619. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  620. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  621. metadata +190 -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