ibm_db 5.2.0 → 5.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (622) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +6 -0
  3. data/LICENSE +55 -18
  4. data/ext/Makefile +12 -12
  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 +11 -11
  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 +1458 -1279
  12. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  13. data/test/activejob/destroy_association_async_test.rb +305 -0
  14. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  15. data/test/activejob/helper.rb +15 -0
  16. data/test/assets/schema_dump_5_1.yml +345 -0
  17. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  18. data/test/cases/adapter_test.rb +432 -218
  19. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  20. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  21. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  22. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  23. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  24. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  25. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  26. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  27. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  28. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  29. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  30. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  31. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  32. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  33. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  34. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  35. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  36. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  37. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  38. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  39. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  40. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  41. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  43. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  44. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  45. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  46. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  47. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  48. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  49. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  50. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  51. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  52. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  53. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  54. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  55. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  56. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  57. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  58. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  59. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  60. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  61. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  62. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  63. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  64. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  65. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  66. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  67. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  68. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  69. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  70. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  71. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  72. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  73. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  74. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  75. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  76. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  77. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  78. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  79. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  80. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  81. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  82. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  83. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  84. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  85. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  86. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  87. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  88. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  89. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  90. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  91. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  92. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  93. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  94. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  95. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  96. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  97. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  98. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  99. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  100. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  101. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  102. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  103. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  104. data/test/cases/aggregations_test.rb +14 -12
  105. data/test/cases/annotate_test.rb +46 -0
  106. data/test/cases/ar_schema_test.rb +153 -86
  107. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  108. data/test/cases/arel/attributes/math_test.rb +83 -0
  109. data/test/cases/arel/attributes_test.rb +27 -0
  110. data/test/cases/arel/collectors/bind_test.rb +40 -0
  111. data/test/cases/arel/collectors/composite_test.rb +47 -0
  112. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  113. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  114. data/test/cases/arel/crud_test.rb +65 -0
  115. data/test/cases/arel/delete_manager_test.rb +53 -0
  116. data/test/cases/arel/factory_methods_test.rb +46 -0
  117. data/test/cases/arel/helper.rb +45 -0
  118. data/test/cases/arel/insert_manager_test.rb +241 -0
  119. data/test/cases/arel/nodes/and_test.rb +30 -0
  120. data/test/cases/arel/nodes/as_test.rb +36 -0
  121. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  122. data/test/cases/arel/nodes/bin_test.rb +35 -0
  123. data/test/cases/arel/nodes/binary_test.rb +29 -0
  124. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  125. data/test/cases/arel/nodes/case_test.rb +96 -0
  126. data/test/cases/arel/nodes/casted_test.rb +18 -0
  127. data/test/cases/arel/nodes/comment_test.rb +22 -0
  128. data/test/cases/arel/nodes/count_test.rb +35 -0
  129. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  130. data/test/cases/arel/nodes/descending_test.rb +46 -0
  131. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  132. data/test/cases/arel/nodes/equality_test.rb +62 -0
  133. data/test/cases/arel/nodes/extract_test.rb +43 -0
  134. data/test/cases/arel/nodes/false_test.rb +21 -0
  135. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  136. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  137. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  138. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  139. data/test/cases/arel/nodes/node_test.rb +22 -0
  140. data/test/cases/arel/nodes/not_test.rb +31 -0
  141. data/test/cases/arel/nodes/or_test.rb +36 -0
  142. data/test/cases/arel/nodes/over_test.rb +69 -0
  143. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  144. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  145. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  146. data/test/cases/arel/nodes/sum_test.rb +35 -0
  147. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  148. data/test/cases/arel/nodes/true_test.rb +21 -0
  149. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  150. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  151. data/test/cases/arel/nodes/window_test.rb +81 -0
  152. data/test/cases/arel/nodes_test.rb +34 -0
  153. data/test/cases/arel/select_manager_test.rb +1238 -0
  154. data/test/cases/arel/support/fake_record.rb +135 -0
  155. data/test/cases/arel/table_test.rb +216 -0
  156. data/test/cases/arel/update_manager_test.rb +126 -0
  157. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  158. data/test/cases/arel/visitors/dot_test.rb +90 -0
  159. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  160. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  161. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  162. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  163. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  164. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  165. data/test/cases/associations/callbacks_test.rb +56 -38
  166. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  167. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  168. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  169. data/test/cases/associations/eager_singularization_test.rb +21 -21
  170. data/test/cases/associations/eager_test.rb +559 -415
  171. data/test/cases/associations/extension_test.rb +18 -12
  172. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  173. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  174. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  175. data/test/cases/associations/has_one_associations_test.rb +294 -129
  176. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  177. data/test/cases/associations/inner_join_association_test.rb +114 -38
  178. data/test/cases/associations/inverse_associations_test.rb +606 -398
  179. data/test/cases/associations/join_model_test.rb +158 -148
  180. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  181. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  182. data/test/cases/associations/required_test.rb +35 -10
  183. data/test/cases/associations_test.rb +241 -110
  184. data/test/cases/attribute_methods/read_test.rb +11 -11
  185. data/test/cases/attribute_methods_test.rb +413 -298
  186. data/test/cases/attributes_test.rb +145 -27
  187. data/test/cases/autosave_association_test.rb +681 -436
  188. data/test/cases/base_prevent_writes_test.rb +229 -0
  189. data/test/cases/base_test.rb +599 -542
  190. data/test/cases/batches_test.rb +288 -82
  191. data/test/cases/binary_test.rb +26 -31
  192. data/test/cases/bind_parameter_test.rb +194 -21
  193. data/test/cases/boolean_test.rb +52 -0
  194. data/test/cases/cache_key_test.rb +110 -5
  195. data/test/cases/calculations_test.rb +737 -174
  196. data/test/cases/callbacks_test.rb +74 -207
  197. data/test/cases/clone_test.rb +15 -10
  198. data/test/cases/coders/json_test.rb +2 -0
  199. data/test/cases/coders/yaml_column_test.rb +16 -13
  200. data/test/cases/collection_cache_key_test.rb +177 -20
  201. data/test/cases/column_alias_test.rb +9 -7
  202. data/test/cases/column_definition_test.rb +10 -68
  203. data/test/cases/comment_test.rb +166 -107
  204. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  205. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  206. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  207. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  208. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  209. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  210. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  211. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  212. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  213. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  214. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  215. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  216. data/test/cases/connection_management_test.rb +13 -11
  217. data/test/cases/connection_pool_test.rb +316 -83
  218. data/test/cases/core_test.rb +82 -58
  219. data/test/cases/counter_cache_test.rb +204 -50
  220. data/test/cases/custom_locking_test.rb +5 -3
  221. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  222. data/test/cases/database_configurations/resolver_test.rb +150 -0
  223. data/test/cases/database_configurations_test.rb +145 -0
  224. data/test/cases/database_selector_test.rb +296 -0
  225. data/test/cases/database_statements_test.rb +18 -16
  226. data/test/cases/date_test.rb +8 -16
  227. data/test/cases/date_time_precision_test.rb +100 -78
  228. data/test/cases/date_time_test.rb +23 -8
  229. data/test/cases/defaults_test.rb +106 -71
  230. data/test/cases/delegated_type_test.rb +57 -0
  231. data/test/cases/dirty_test.rb +419 -223
  232. data/test/cases/disconnected_test.rb +6 -6
  233. data/test/cases/dup_test.rb +54 -27
  234. data/test/cases/enum_test.rb +461 -82
  235. data/test/cases/errors_test.rb +7 -7
  236. data/test/cases/explain_subscriber_test.rb +17 -15
  237. data/test/cases/explain_test.rb +11 -19
  238. data/test/cases/filter_attributes_test.rb +153 -0
  239. data/test/cases/finder_respond_to_test.rb +14 -14
  240. data/test/cases/finder_test.rb +669 -287
  241. data/test/cases/fixture_set/file_test.rb +34 -38
  242. data/test/cases/fixtures_test.rb +833 -176
  243. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  244. data/test/cases/habtm_destroy_order_test.rb +25 -25
  245. data/test/cases/helper.rb +78 -49
  246. data/test/cases/hot_compatibility_test.rb +33 -32
  247. data/test/cases/i18n_test.rb +18 -17
  248. data/test/cases/inheritance_test.rb +180 -115
  249. data/test/cases/insert_all_test.rb +489 -0
  250. data/test/cases/instrumentation_test.rb +101 -0
  251. data/test/cases/integration_test.rb +119 -31
  252. data/test/cases/invalid_connection_test.rb +18 -16
  253. data/test/cases/invertible_migration_test.rb +183 -43
  254. data/test/cases/json_attribute_test.rb +35 -0
  255. data/test/cases/json_serialization_test.rb +57 -58
  256. data/test/cases/json_shared_test_cases.rb +290 -0
  257. data/test/cases/locking_test.rb +413 -119
  258. data/test/cases/log_subscriber_test.rb +68 -26
  259. data/test/cases/marshal_serialization_test.rb +39 -0
  260. data/test/cases/migration/change_schema_test.rb +118 -72
  261. data/test/cases/migration/change_table_test.rb +138 -30
  262. data/test/cases/migration/check_constraint_test.rb +162 -0
  263. data/test/cases/migration/column_attributes_test.rb +45 -35
  264. data/test/cases/migration/column_positioning_test.rb +18 -6
  265. data/test/cases/migration/columns_test.rb +93 -77
  266. data/test/cases/migration/command_recorder_test.rb +121 -34
  267. data/test/cases/migration/compatibility_test.rb +578 -23
  268. data/test/cases/migration/create_join_table_test.rb +35 -25
  269. data/test/cases/migration/foreign_key_test.rb +503 -284
  270. data/test/cases/migration/helper.rb +4 -3
  271. data/test/cases/migration/index_test.rb +119 -70
  272. data/test/cases/migration/logger_test.rb +9 -6
  273. data/test/cases/migration/pending_migrations_test.rb +88 -34
  274. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  275. data/test/cases/migration/references_index_test.rb +38 -19
  276. data/test/cases/migration/references_statements_test.rb +15 -14
  277. data/test/cases/migration/rename_table_test.rb +53 -30
  278. data/test/cases/migration_test.rb +637 -269
  279. data/test/cases/migrator_test.rb +191 -135
  280. data/test/cases/mixin_test.rb +7 -11
  281. data/test/cases/modules_test.rb +36 -34
  282. data/test/cases/multi_db_migrator_test.rb +223 -0
  283. data/test/cases/multiparameter_attributes_test.rb +60 -33
  284. data/test/cases/multiple_db_test.rb +16 -22
  285. data/test/cases/nested_attributes_test.rb +341 -320
  286. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  287. data/test/cases/null_relation_test.rb +84 -0
  288. data/test/cases/numeric_data_test.rb +93 -0
  289. data/test/cases/persistence_test.rb +361 -269
  290. data/test/cases/pooled_connections_test.rb +18 -26
  291. data/test/cases/prepared_statement_status_test.rb +48 -0
  292. data/test/cases/primary_keys_test.rb +210 -104
  293. data/test/cases/query_cache_test.rb +610 -141
  294. data/test/cases/quoting_test.rb +132 -31
  295. data/test/cases/readonly_test.rb +49 -48
  296. data/test/cases/reaper_test.rb +146 -32
  297. data/test/cases/reflection_test.rb +167 -156
  298. data/test/cases/relation/delegation_test.rb +49 -36
  299. data/test/cases/relation/delete_all_test.rb +117 -0
  300. data/test/cases/relation/merging_test.rb +319 -42
  301. data/test/cases/relation/mutation_test.rb +55 -93
  302. data/test/cases/relation/or_test.rb +129 -29
  303. data/test/cases/relation/predicate_builder_test.rb +21 -6
  304. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  305. data/test/cases/relation/select_test.rb +67 -0
  306. data/test/cases/relation/update_all_test.rb +317 -0
  307. data/test/cases/relation/where_chain_test.rb +68 -32
  308. data/test/cases/relation/where_clause_test.rb +136 -61
  309. data/test/cases/relation/where_test.rb +155 -48
  310. data/test/cases/relation_test.rb +266 -112
  311. data/test/cases/relations_test.rb +969 -744
  312. data/test/cases/reload_models_test.rb +13 -9
  313. data/test/cases/reserved_word_test.rb +141 -0
  314. data/test/cases/result_test.rb +68 -17
  315. data/test/cases/sanitize_test.rb +87 -71
  316. data/test/cases/schema_dumper_test.rb +221 -128
  317. data/test/cases/schema_loading_test.rb +3 -2
  318. data/test/cases/scoping/default_scoping_test.rb +185 -144
  319. data/test/cases/scoping/named_scoping_test.rb +177 -89
  320. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  321. data/test/cases/secure_token_test.rb +18 -3
  322. data/test/cases/serialization_test.rb +30 -28
  323. data/test/cases/serialized_attribute_test.rb +133 -42
  324. data/test/cases/signed_id_test.rb +168 -0
  325. data/test/cases/statement_cache_test.rb +41 -24
  326. data/test/cases/statement_invalid_test.rb +42 -0
  327. data/test/cases/store_test.rb +180 -55
  328. data/test/cases/strict_loading_test.rb +473 -0
  329. data/test/cases/suppressor_test.rb +26 -12
  330. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  331. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  332. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  333. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  334. data/test/cases/test_case.rb +51 -40
  335. data/test/cases/test_databases_test.rb +79 -0
  336. data/test/cases/test_fixtures_test.rb +79 -19
  337. data/test/cases/time_precision_test.rb +98 -76
  338. data/test/cases/timestamp_test.rb +102 -99
  339. data/test/cases/touch_later_test.rb +12 -10
  340. data/test/cases/transaction_callbacks_test.rb +344 -90
  341. data/test/cases/transaction_isolation_test.rb +12 -12
  342. data/test/cases/transactions_test.rb +612 -162
  343. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  344. data/test/cases/type/date_time_test.rb +4 -2
  345. data/test/cases/type/integer_test.rb +4 -2
  346. data/test/cases/type/string_test.rb +10 -8
  347. data/test/cases/type/time_test.rb +28 -0
  348. data/test/cases/type/type_map_test.rb +29 -28
  349. data/test/cases/type/unsigned_integer_test.rb +19 -0
  350. data/test/cases/type_test.rb +2 -0
  351. data/test/cases/types_test.rb +3 -1
  352. data/test/cases/unconnected_test.rb +14 -1
  353. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  354. data/test/cases/validations/absence_validation_test.rb +19 -17
  355. data/test/cases/validations/association_validation_test.rb +30 -28
  356. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  357. data/test/cases/validations/i18n_validation_test.rb +22 -21
  358. data/test/cases/validations/length_validation_test.rb +34 -33
  359. data/test/cases/validations/numericality_validation_test.rb +181 -0
  360. data/test/cases/validations/presence_validation_test.rb +21 -19
  361. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  362. data/test/cases/validations_repair_helper.rb +2 -0
  363. data/test/cases/validations_test.rb +61 -26
  364. data/test/cases/view_test.rb +122 -116
  365. data/test/cases/yaml_serialization_test.rb +79 -34
  366. data/test/config.example.yml +19 -19
  367. data/test/config.rb +3 -1
  368. data/test/config.yml +16 -6
  369. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  370. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  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/randomly_named_a9.yml +7 -7
  398. data/test/fixtures/readers.yml +6 -0
  399. data/test/fixtures/reserved_words/values.yml +2 -2
  400. data/test/fixtures/sponsors.yml +3 -0
  401. data/test/fixtures/strict_zines.yml +2 -0
  402. data/test/fixtures/subscribers.yml +1 -1
  403. data/test/fixtures/tasks.yml +1 -1
  404. data/test/fixtures/warehouse-things.yml +3 -0
  405. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  406. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  407. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  408. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  409. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  410. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  411. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  412. data/test/migrations/rename/1_we_need_things.rb +2 -0
  413. data/test/migrations/rename/2_rename_things.rb +2 -0
  414. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  415. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  416. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  417. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  418. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  419. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  420. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  421. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  422. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  423. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  424. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  425. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  426. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  427. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  428. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  429. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  430. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  431. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  432. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  433. data/test/models/account.rb +46 -0
  434. data/test/models/admin/account.rb +3 -1
  435. data/test/models/admin/randomly_named_c1.rb +2 -0
  436. data/test/models/admin/user.rb +16 -8
  437. data/test/models/admin.rb +4 -2
  438. data/test/models/aircraft.rb +3 -1
  439. data/test/models/arunit2_model.rb +2 -0
  440. data/test/models/author.rb +153 -102
  441. data/test/models/auto_id.rb +2 -0
  442. data/test/models/autoloadable/extra_firm.rb +2 -0
  443. data/test/models/binary.rb +3 -1
  444. data/test/models/binary_field.rb +6 -0
  445. data/test/models/bird.rb +13 -1
  446. data/test/models/book.rb +14 -4
  447. data/test/models/book_destroy_async.rb +24 -0
  448. data/test/models/boolean.rb +5 -0
  449. data/test/models/bulb.rb +13 -4
  450. data/test/models/cake_designer.rb +2 -0
  451. data/test/models/car.rb +17 -10
  452. data/test/models/carrier.rb +2 -0
  453. data/test/models/cart.rb +5 -0
  454. data/test/models/cat.rb +2 -0
  455. data/test/models/categorization.rb +8 -6
  456. data/test/models/category.rb +28 -16
  457. data/test/models/chef.rb +2 -0
  458. data/test/models/citation.rb +5 -1
  459. data/test/models/club.rb +13 -10
  460. data/test/models/college.rb +4 -2
  461. data/test/models/column.rb +2 -0
  462. data/test/models/column_name.rb +2 -0
  463. data/test/models/comment.rb +32 -10
  464. data/test/models/company.rb +102 -106
  465. data/test/models/company_in_module.rb +27 -26
  466. data/test/models/computer.rb +3 -1
  467. data/test/models/contact.rb +15 -13
  468. data/test/models/content.rb +5 -3
  469. data/test/models/contract.rb +21 -3
  470. data/test/models/country.rb +2 -4
  471. data/test/models/course.rb +3 -1
  472. data/test/models/customer.rb +10 -8
  473. data/test/models/customer_carrier.rb +2 -0
  474. data/test/models/dashboard.rb +2 -0
  475. data/test/models/default.rb +2 -0
  476. data/test/models/department.rb +2 -0
  477. data/test/models/destroy_async_parent.rb +15 -0
  478. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  479. data/test/models/developer.rb +152 -85
  480. data/test/models/dl_keyed_belongs_to.rb +13 -0
  481. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  482. data/test/models/dl_keyed_has_many.rb +5 -0
  483. data/test/models/dl_keyed_has_many_through.rb +5 -0
  484. data/test/models/dl_keyed_has_one.rb +5 -0
  485. data/test/models/dl_keyed_join.rb +10 -0
  486. data/test/models/dog.rb +2 -0
  487. data/test/models/dog_lover.rb +2 -0
  488. data/test/models/doubloon.rb +3 -1
  489. data/test/models/drink_designer.rb +17 -0
  490. data/test/models/edge.rb +4 -2
  491. data/test/models/electron.rb +2 -0
  492. data/test/models/engine.rb +3 -2
  493. data/test/models/entrant.rb +2 -0
  494. data/test/models/entry.rb +5 -0
  495. data/test/models/essay.rb +6 -3
  496. data/test/models/essay_destroy_async.rb +12 -0
  497. data/test/models/event.rb +3 -1
  498. data/test/models/eye.rb +5 -3
  499. data/test/models/face.rb +14 -6
  500. data/test/models/family.rb +6 -0
  501. data/test/models/family_tree.rb +6 -0
  502. data/test/models/friendship.rb +5 -3
  503. data/test/models/frog.rb +8 -0
  504. data/test/models/guid.rb +3 -1
  505. data/test/models/guitar.rb +2 -0
  506. data/test/models/hotel.rb +5 -3
  507. data/test/models/human.rb +39 -0
  508. data/test/models/image.rb +3 -1
  509. data/test/models/interest.rb +14 -3
  510. data/test/models/invoice.rb +4 -2
  511. data/test/models/item.rb +3 -1
  512. data/test/models/job.rb +5 -3
  513. data/test/models/joke.rb +4 -2
  514. data/test/models/keyboard.rb +3 -1
  515. data/test/models/legacy_thing.rb +2 -0
  516. data/test/models/lesson.rb +2 -0
  517. data/test/models/line_item.rb +3 -1
  518. data/test/models/liquid.rb +2 -0
  519. data/test/models/matey.rb +3 -1
  520. data/test/models/measurement.rb +4 -0
  521. data/test/models/member.rb +23 -20
  522. data/test/models/member_detail.rb +3 -0
  523. data/test/models/member_type.rb +2 -0
  524. data/test/models/membership.rb +4 -1
  525. data/test/models/mentor.rb +3 -1
  526. data/test/models/message.rb +5 -0
  527. data/test/models/minimalistic.rb +2 -0
  528. data/test/models/minivan.rb +3 -2
  529. data/test/models/mixed_case_monkey.rb +3 -1
  530. data/test/models/molecule.rb +2 -0
  531. data/test/models/mouse.rb +6 -0
  532. data/test/models/movie.rb +2 -0
  533. data/test/models/node.rb +4 -2
  534. data/test/models/non_primary_key.rb +2 -0
  535. data/test/models/notification.rb +2 -0
  536. data/test/models/numeric_data.rb +12 -0
  537. data/test/models/order.rb +4 -2
  538. data/test/models/organization.rb +9 -7
  539. data/test/models/other_dog.rb +3 -1
  540. data/test/models/owner.rb +6 -4
  541. data/test/models/parrot.rb +12 -4
  542. data/test/models/person.rb +59 -54
  543. data/test/models/personal_legacy_thing.rb +3 -1
  544. data/test/models/pet.rb +4 -2
  545. data/test/models/pet_treasure.rb +2 -0
  546. data/test/models/pirate.rb +67 -43
  547. data/test/models/possession.rb +3 -1
  548. data/test/models/post.rb +184 -86
  549. data/test/models/price_estimate.rb +11 -1
  550. data/test/models/professor.rb +3 -1
  551. data/test/models/project.rb +14 -12
  552. data/test/models/publisher/article.rb +2 -0
  553. data/test/models/publisher/magazine.rb +2 -0
  554. data/test/models/publisher.rb +2 -0
  555. data/test/models/randomly_named_c1.rb +2 -0
  556. data/test/models/rating.rb +5 -1
  557. data/test/models/reader.rb +7 -5
  558. data/test/models/recipe.rb +2 -0
  559. data/test/models/record.rb +2 -0
  560. data/test/models/reference.rb +6 -3
  561. data/test/models/reply.rb +39 -21
  562. data/test/models/room.rb +6 -0
  563. data/test/models/section.rb +6 -0
  564. data/test/models/seminar.rb +6 -0
  565. data/test/models/session.rb +6 -0
  566. data/test/models/ship.rb +12 -9
  567. data/test/models/ship_part.rb +5 -3
  568. data/test/models/shop.rb +4 -2
  569. data/test/models/shop_account.rb +2 -0
  570. data/test/models/speedometer.rb +2 -0
  571. data/test/models/sponsor.rb +8 -5
  572. data/test/models/squeak.rb +6 -0
  573. data/test/models/strict_zine.rb +7 -0
  574. data/test/models/string_key_object.rb +2 -0
  575. data/test/models/student.rb +2 -0
  576. data/test/models/subscriber.rb +4 -2
  577. data/test/models/subscription.rb +5 -1
  578. data/test/models/tag.rb +6 -3
  579. data/test/models/tagging.rb +13 -6
  580. data/test/models/task.rb +2 -0
  581. data/test/models/topic.rb +54 -19
  582. data/test/models/toy.rb +4 -0
  583. data/test/models/traffic_light.rb +2 -0
  584. data/test/models/treasure.rb +5 -3
  585. data/test/models/treaty.rb +2 -4
  586. data/test/models/tree.rb +2 -0
  587. data/test/models/tuning_peg.rb +2 -0
  588. data/test/models/tyre.rb +2 -0
  589. data/test/models/user.rb +12 -4
  590. data/test/models/uuid_child.rb +2 -0
  591. data/test/models/uuid_item.rb +2 -0
  592. data/test/models/uuid_parent.rb +2 -0
  593. data/test/models/vegetables.rb +12 -3
  594. data/test/models/vertex.rb +6 -4
  595. data/test/models/warehouse_thing.rb +2 -0
  596. data/test/models/wheel.rb +3 -1
  597. data/test/models/without_table.rb +3 -1
  598. data/test/models/zine.rb +3 -1
  599. data/test/schema/mysql2_specific_schema.rb +49 -35
  600. data/test/schema/oracle_specific_schema.rb +13 -15
  601. data/test/schema/postgresql_specific_schema.rb +51 -40
  602. data/test/schema/schema.rb +334 -154
  603. data/test/schema/sqlite_specific_schema.rb +9 -16
  604. data/test/support/config.rb +26 -26
  605. data/test/support/connection.rb +14 -8
  606. data/test/support/connection_helper.rb +3 -1
  607. data/test/support/ddl_helper.rb +2 -0
  608. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  609. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  610. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  611. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  618. data/test/support/schema_dumping_helper.rb +2 -0
  619. data/test/support/stubs/strong_parameters.rb +40 -0
  620. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  621. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  622. metadata +185 -4
@@ -1,79 +1,184 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cases/helper"
2
- require 'models/post'
3
- require 'models/tagging'
4
- require 'models/tag'
5
- require 'models/comment'
6
- require 'models/author'
7
- require 'models/essay'
8
- require 'models/category'
9
- require 'models/company'
10
- require 'models/person'
11
- require 'models/reader'
12
- require 'models/owner'
13
- require 'models/pet'
14
- require 'models/reference'
15
- require 'models/job'
16
- require 'models/subscriber'
17
- require 'models/subscription'
18
- require 'models/book'
19
- require 'models/developer'
20
- require 'models/computer'
21
- require 'models/project'
22
- require 'models/member'
23
- require 'models/membership'
24
- require 'models/club'
25
- require 'models/categorization'
26
- require 'models/sponsor'
27
- require 'models/mentor'
28
- require 'models/contract'
4
+ require "models/post"
5
+ require "models/tagging"
6
+ require "models/tag"
7
+ require "models/rating"
8
+ require "models/comment"
9
+ require "models/author"
10
+ require "models/essay"
11
+ require "models/category"
12
+ require "models/company"
13
+ require "models/person"
14
+ require "models/reader"
15
+ require "models/owner"
16
+ require "models/pet"
17
+ require "models/reference"
18
+ require "models/job"
19
+ require "models/subscriber"
20
+ require "models/subscription"
21
+ require "models/book"
22
+ require "models/citation"
23
+ require "models/developer"
24
+ require "models/computer"
25
+ require "models/project"
26
+ require "models/member"
27
+ require "models/membership"
28
+ require "models/club"
29
+ require "models/categorization"
30
+ require "models/sponsor"
31
+ require "models/mentor"
32
+ require "models/contract"
33
+
34
+ class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
35
+ fixtures :citations
36
+
37
+ def test_preloading_too_many_ids
38
+ assert_equal Citation.count, Citation.preload(:reference_of).to_a.size
39
+ end
40
+
41
+ def test_eager_loading_too_many_ids
42
+ assert_equal Citation.count, Citation.eager_load(:citations).offset(0).size
43
+ end
44
+ end
29
45
 
30
46
  class EagerAssociationTest < ActiveRecord::TestCase
31
47
  fixtures :posts, :comments, :authors, :essays, :author_addresses, :categories, :categories_posts,
32
- :companies, :accounts, :tags, :taggings, :people, :readers, :categorizations,
48
+ :companies, :accounts, :tags, :taggings, :ratings, :people, :readers, :categorizations,
33
49
  :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
34
50
  :developers, :projects, :developers_projects, :members, :memberships, :clubs, :sponsors
35
51
 
36
52
  def test_eager_with_has_one_through_join_model_with_conditions_on_the_through
37
- member = Member.all.merge!(:includes => :favourite_club).find(members(:some_other_guy).id)
53
+ member = Member.all.merge!(includes: :favourite_club).find(members(:some_other_guy).id)
38
54
  assert_nil member.favourite_club
39
55
  end
40
56
 
57
+ def test_should_work_inverse_of_with_eager_load
58
+ author = authors(:david)
59
+ assert_same author, author.posts.first.author
60
+ assert_same author, author.posts.eager_load(:comments).first.author
61
+ end
62
+
41
63
  def test_loading_with_one_association
42
- posts = Post.all.merge!(:includes => :comments).to_a
64
+ posts = Post.all.merge!(includes: :comments).to_a
43
65
  post = posts.find { |p| p.id == 1 }
44
66
  assert_equal 2, post.comments.size
45
- assert post.comments.include?(comments(:greetings))
67
+ assert_includes post.comments, comments(:greetings)
46
68
 
47
- post = Post.all.merge!(:includes => :comments, :where => "posts.title = 'Welcome to the weblog'").first
69
+ post = Post.all.merge!(includes: :comments, where: "posts.title = 'Welcome to the weblog'").first
48
70
  assert_equal 2, post.comments.size
49
- assert post.comments.include?(comments(:greetings))
71
+ assert_includes post.comments, comments(:greetings)
50
72
 
51
- posts = Post.all.merge!(:includes => :last_comment).to_a
73
+ posts = Post.all.merge!(includes: :last_comment).to_a
52
74
  post = posts.find { |p| p.id == 1 }
53
75
  assert_equal Post.find(1).last_comment, post.last_comment
54
76
  end
55
77
 
56
78
  def test_loading_with_one_association_with_non_preload
57
- posts = Post.all.merge!(:includes => :last_comment, :order => 'comments.id DESC').to_a
79
+ posts = Post.all.merge!(includes: :last_comment, order: "comments.id DESC").to_a
58
80
  post = posts.find { |p| p.id == 1 }
59
81
  assert_equal Post.find(1).last_comment, post.last_comment
60
82
  end
61
83
 
62
84
  def test_loading_conditions_with_or
63
85
  posts = authors(:david).posts.references(:comments).merge(
64
- :includes => :comments,
65
- :where => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'"
86
+ includes: :comments,
87
+ where: "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'"
66
88
  ).to_a
67
89
  assert_nil posts.detect { |p| p.author_id != authors(:david).id },
68
90
  "expected to find only david's posts"
69
91
  end
70
92
 
93
+ def test_loading_polymorphic_association_with_mixed_table_conditions
94
+ rating = Rating.first
95
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
96
+
97
+ rating = Rating.preload(:taggings_without_tag).first
98
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
99
+
100
+ rating = Rating.eager_load(:taggings_without_tag).first
101
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
102
+ end
103
+
104
+ def test_loading_association_with_string_joins
105
+ rating = Rating.first
106
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_with_no_tag
107
+
108
+ rating = Rating.preload(:taggings_with_no_tag).first
109
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_with_no_tag
110
+
111
+ rating = Rating.eager_load(:taggings_with_no_tag).first
112
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_with_no_tag
113
+ end
114
+
71
115
  def test_loading_with_scope_including_joins
72
- assert_equal clubs(:boring_club), Member.preload(:general_club).find(1).general_club
116
+ member = Member.first
117
+ assert_equal members(:groucho), member
118
+ assert_equal clubs(:boring_club), member.general_club
119
+
120
+ member = Member.preload(:general_club).first
121
+ assert_equal members(:groucho), member
122
+ assert_equal clubs(:boring_club), member.general_club
123
+
124
+ member = Member.eager_load(:general_club).first
125
+ assert_equal members(:groucho), member
126
+ assert_equal clubs(:boring_club), member.general_club
127
+ end
128
+
129
+ def test_loading_association_with_same_table_joins
130
+ super_memberships = [memberships(:super_membership_of_boring_club)]
131
+
132
+ member = Member.joins(:favourite_memberships).first
133
+ assert_equal members(:groucho), member
134
+ assert_equal super_memberships, member.super_memberships
135
+
136
+ member = Member.joins(:favourite_memberships).preload(:super_memberships).first
137
+ assert_equal members(:groucho), member
138
+ assert_equal super_memberships, member.super_memberships
139
+
140
+ member = Member.joins(:favourite_memberships).eager_load(:super_memberships).first
141
+ assert_equal members(:groucho), member
142
+ assert_equal super_memberships, member.super_memberships
143
+ end
144
+
145
+ def test_loading_association_with_intersection_joins
146
+ member = Member.joins(:current_membership).first
147
+ assert_equal members(:groucho), member
148
+ assert_equal clubs(:boring_club), member.club
149
+ assert_equal memberships(:membership_of_boring_club), member.current_membership
150
+
151
+ member = Member.joins(:current_membership).preload(:club, :current_membership).first
152
+ assert_equal members(:groucho), member
153
+ assert_equal clubs(:boring_club), member.club
154
+ assert_equal memberships(:membership_of_boring_club), member.current_membership
155
+
156
+ member = Member.joins(:current_membership).eager_load(:club, :current_membership).first
157
+ assert_equal members(:groucho), member
158
+ assert_equal clubs(:boring_club), member.club
159
+ assert_equal memberships(:membership_of_boring_club), member.current_membership
160
+ end
161
+
162
+ def test_loading_associations_dont_leak_instance_state
163
+ assertions = ->(firm) {
164
+ assert_equal companies(:first_firm), firm
165
+
166
+ assert_predicate firm.association(:readonly_account), :loaded?
167
+ assert_predicate firm.association(:accounts), :loaded?
168
+
169
+ assert_equal accounts(:signals37), firm.readonly_account
170
+ assert_equal [accounts(:signals37)], firm.accounts
171
+
172
+ assert_predicate firm.readonly_account, :readonly?
173
+ assert firm.accounts.none?(&:readonly?)
174
+ }
175
+
176
+ assertions.call(Firm.preload(:readonly_account, :accounts).first)
177
+ assertions.call(Firm.eager_load(:readonly_account, :accounts).first)
73
178
  end
74
179
 
75
180
  def test_with_ordering
76
- list = Post.all.merge!(:includes => :comments, :order => "posts.id DESC").to_a
181
+ list = Post.all.merge!(includes: :comments, order: "posts.id DESC").to_a
77
182
  [:other_by_mary, :other_by_bob, :misc_by_mary, :misc_by_bob, :eager_other,
78
183
  :sti_habtm, :sti_post_and_comments, :sti_comments, :authorless, :thinking, :welcome
79
184
  ].each_with_index do |post, index|
@@ -94,119 +199,84 @@ class EagerAssociationTest < ActiveRecord::TestCase
94
199
  assert_no_queries { authors.map(&:post) }
95
200
  end
96
201
 
97
- def test_with_two_tables_in_from_without_getting_double_quoted
98
- posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
99
- assert_equal 2, posts.first.comments.size
100
- end
101
-
102
- def test_loading_with_multiple_associations
103
- posts = Post.all.merge!(:includes => [ :comments, :author, :categories ], :order => "posts.id").to_a
104
- assert_equal 2, posts.first.comments.size
105
- assert_equal 2, posts.first.categories.size
106
- assert posts.first.comments.include?(comments(:greetings))
107
- end
202
+ def test_type_cast_in_where_references_association_name
203
+ parent = comments(:greetings)
204
+ child = parent.children.create!(label: "child", body: "hi", post_id: parent.post_id)
108
205
 
109
- def test_duplicate_middle_objects
110
- comments = Comment.all.merge!(:where => 'post_id = 1', :includes => [:post => :author]).to_a
111
- assert_no_queries do
112
- comments.each {|comment| comment.post.author.name}
113
- end
114
- end
206
+ comment = Comment.includes(:children).where("children.label": "child").last
115
207
 
116
- def test_preloading_has_many_in_multiple_queries_with_more_ids_than_database_can_handle
117
- assert_called(Comment.connection, :in_clause_length, returns: 5) do
118
- posts = Post.all.merge!(:includes=>:comments).to_a
119
- assert_equal 11, posts.size
120
- end
208
+ assert_equal parent, comment
209
+ assert_equal [child], comment.children
121
210
  end
122
211
 
123
- def test_preloading_has_many_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
124
- assert_called(Comment.connection, :in_clause_length, returns: nil) do
125
- posts = Post.all.merge!(:includes=>:comments).to_a
126
- assert_equal 11, posts.size
127
- end
212
+ def test_attribute_alias_in_where_references_association_name
213
+ firm = Firm.includes(:clients).where("clients.new_name": "Summit").last
214
+ assert_equal companies(:first_firm), firm
215
+ assert_equal [companies(:first_client)], firm.clients
128
216
  end
129
217
 
130
- def test_preloading_habtm_in_multiple_queries_with_more_ids_than_database_can_handle
131
- assert_called(Comment.connection, :in_clause_length, times: 2, returns: 5) do
132
- posts = Post.all.merge!(:includes=>:categories).to_a
133
- assert_equal 11, posts.size
134
- end
218
+ def test_calculate_with_string_in_from_and_eager_loading
219
+ assert_equal 10, Post.from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").count
135
220
  end
136
221
 
137
- def test_preloading_habtm_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
138
- assert_called(Comment.connection, :in_clause_length, times: 2, returns: nil) do
139
- posts = Post.all.merge!(:includes=>:categories).to_a
140
- assert_equal 11, posts.size
141
- end
142
- end
143
-
144
- def test_load_associated_records_in_one_query_when_adapter_has_no_limit
145
- assert_called(Comment.connection, :in_clause_length, returns: nil) do
146
- post = posts(:welcome)
147
- assert_queries(2) do
148
- Post.includes(:comments).where(:id => post.id).to_a
149
- end
150
- end
222
+ def test_with_two_tables_in_from_without_getting_double_quoted
223
+ posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
224
+ assert_equal 2, posts.first.comments.size
151
225
  end
152
226
 
153
- def test_load_associated_records_in_several_queries_when_many_ids_passed
154
- assert_called(Comment.connection, :in_clause_length, returns: 1) do
155
- post1, post2 = posts(:welcome), posts(:thinking)
156
- assert_queries(3) do
157
- Post.includes(:comments).where(:id => [post1.id, post2.id]).to_a
158
- end
159
- end
227
+ def test_loading_with_multiple_associations
228
+ posts = Post.all.merge!(includes: [ :comments, :author, :categories ], order: "posts.id").to_a
229
+ assert_equal 2, posts.first.comments.size
230
+ assert_equal 2, posts.first.categories.size
231
+ assert_includes posts.first.comments, comments(:greetings)
160
232
  end
161
233
 
162
- def test_load_associated_records_in_one_query_when_a_few_ids_passed
163
- assert_called(Comment.connection, :in_clause_length, returns: 3) do
164
- post = posts(:welcome)
165
- assert_queries(2) do
166
- Post.includes(:comments).where(:id => post.id).to_a
167
- end
234
+ def test_duplicate_middle_objects
235
+ comments = Comment.all.merge!(where: "post_id = 1", includes: [post: :author]).to_a
236
+ assert_no_queries do
237
+ comments.each { |comment| comment.post.author.name }
168
238
  end
169
239
  end
170
240
 
171
241
  def test_including_duplicate_objects_from_belongs_to
172
- popular_post = Post.create!(:title => 'foo', :body => "I like cars!")
173
- comment = popular_post.comments.create!(:body => "lol")
174
- popular_post.readers.create!(:person => people(:michael))
175
- popular_post.readers.create!(:person => people(:david))
242
+ popular_post = Post.create!(title: "foo", body: "I like cars!")
243
+ comment = popular_post.comments.create!(body: "lol")
244
+ popular_post.readers.create!(person: people(:michael))
245
+ popular_post.readers.create!(person: people(:david))
176
246
 
177
- readers = Reader.all.merge!(:where => ["post_id = ?", popular_post.id],
178
- :includes => {:post => :comments}).to_a
247
+ readers = Reader.all.merge!(where: ["post_id = ?", popular_post.id],
248
+ includes: { post: :comments }).to_a
179
249
  readers.each do |reader|
180
250
  assert_equal [comment], reader.post.comments
181
251
  end
182
252
  end
183
253
 
184
254
  def test_including_duplicate_objects_from_has_many
185
- car_post = Post.create!(:title => 'foo', :body => "I like cars!")
255
+ car_post = Post.create!(title: "foo", body: "I like cars!")
186
256
  car_post.categories << categories(:general)
187
257
  car_post.categories << categories(:technology)
188
258
 
189
- comment = car_post.comments.create!(:body => "hmm")
190
- categories = Category.all.merge!(:where => { 'posts.id' => car_post.id },
191
- :includes => {:posts => :comments}).to_a
259
+ comment = car_post.comments.create!(body: "hmm")
260
+ categories = Category.all.merge!(where: { "posts.id" => car_post.id },
261
+ includes: { posts: :comments }).to_a
192
262
  categories.each do |category|
193
263
  assert_equal [comment], category.posts[0].comments
194
264
  end
195
265
  end
196
266
 
197
267
  def test_associations_loaded_for_all_records
198
- post = Post.create!(:title => 'foo', :body => "I like cars!")
199
- SpecialComment.create!(:body => 'Come on!', :post => post)
200
- first_category = Category.create! :name => 'First!', :posts => [post]
201
- second_category = Category.create! :name => 'Second!', :posts => [post]
268
+ post = Post.create!(title: "foo", body: "I like cars!")
269
+ SpecialComment.create!(body: "Come on!", post: post)
270
+ first_category = Category.create! name: "First!", posts: [post]
271
+ second_category = Category.create! name: "Second!", posts: [post]
202
272
 
203
- categories = Category.where(:id => [first_category.id, second_category.id]).includes(:posts => :special_comments)
273
+ categories = Category.where(id: [first_category.id, second_category.id]).includes(posts: :special_comments)
204
274
  assert_equal categories.map { |category| category.posts.first.special_comments.loaded? }, [true, true]
205
275
  end
206
276
 
207
277
  def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
208
278
  author_id = authors(:david).id
209
- author = assert_queries(3) { Author.all.merge!(:includes => {:posts_with_comments => :comments}).find(author_id) } # find the author, then find the posts, then find the comments
279
+ author = assert_queries(3) { Author.all.merge!(includes: { posts_with_comments: :comments }).find(author_id) } # find the author, then find the posts, then find the comments
210
280
  author.posts_with_comments.each do |post_with_comments|
211
281
  assert_equal post_with_comments.comments.length, post_with_comments.comments.count
212
282
  assert_nil post_with_comments.comments.to_a.uniq!
@@ -217,7 +287,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
217
287
  author = authors(:david)
218
288
  post = author.post_about_thinking_with_last_comment
219
289
  last_comment = post.last_comment
220
- author = assert_queries(3) { Author.all.merge!(:includes => {:post_about_thinking_with_last_comment => :last_comment}).find(author.id)} # find the author, then find the posts, then find the comments
290
+ author = assert_queries(3) { Author.all.merge!(includes: { post_about_thinking_with_last_comment: :last_comment }).find(author.id) } # find the author, then find the posts, then find the comments
221
291
  assert_no_queries do
222
292
  assert_equal post, author.post_about_thinking_with_last_comment
223
293
  assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
@@ -228,7 +298,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
228
298
  post = posts(:welcome)
229
299
  author = post.author
230
300
  author_address = author.author_address
231
- post = assert_queries(3) { Post.all.merge!(:includes => {:author_with_address => :author_address}).find(post.id) } # find the post, then find the author, then find the address
301
+ post = assert_queries(3) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) } # find the post, then find the author, then find the address
232
302
  assert_no_queries do
233
303
  assert_equal author, post.author_with_address
234
304
  assert_equal author_address, post.author_with_address.author_address
@@ -238,53 +308,50 @@ class EagerAssociationTest < ActiveRecord::TestCase
238
308
  def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
239
309
  post = posts(:welcome)
240
310
  post.update!(author: nil)
241
- post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) }
311
+ post = assert_queries(1) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) }
242
312
  # find the post, then find the author which is null so no query for the author or address
243
313
  assert_no_queries do
244
- assert_equal nil, post.author_with_address
314
+ assert_nil post.author_with_address
245
315
  end
246
316
  end
247
317
 
248
318
  def test_finding_with_includes_on_null_belongs_to_polymorphic_association
249
319
  sponsor = sponsors(:moustache_club_sponsor_for_groucho)
250
320
  sponsor.update!(sponsorable: nil)
251
- sponsor = assert_queries(1) { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
321
+ sponsor = assert_queries(1) { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) }
252
322
  assert_no_queries do
253
- assert_equal nil, sponsor.sponsorable
323
+ assert_nil sponsor.sponsorable
254
324
  end
255
325
  end
256
326
 
257
327
  def test_finding_with_includes_on_empty_polymorphic_type_column
258
328
  sponsor = sponsors(:moustache_club_sponsor_for_groucho)
259
- sponsor.update!(sponsorable_type: '', sponsorable_id: nil) # sponsorable_type column might be declared NOT NULL
329
+ sponsor.update!(sponsorable_type: "", sponsorable_id: nil) # sponsorable_type column might be declared NOT NULL
260
330
  sponsor = assert_queries(1) do
261
- assert_nothing_raised { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
331
+ assert_nothing_raised { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) }
262
332
  end
263
333
  assert_no_queries do
264
- assert_equal nil, sponsor.sponsorable
334
+ assert_nil sponsor.sponsorable
265
335
  end
266
336
  end
267
337
 
268
338
  def test_loading_from_an_association
269
- posts = authors(:david).posts.merge(:includes => :comments, :order => "posts.id").to_a
339
+ posts = authors(:david).posts.merge(includes: :comments, order: "posts.id").to_a
270
340
  assert_equal 2, posts.first.comments.size
271
341
  end
272
342
 
273
343
  def test_loading_from_an_association_that_has_a_hash_of_conditions
274
- assert_nothing_raised do
275
- Author.all.merge!(:includes => :hello_posts_with_hash_conditions).to_a
276
- end
277
- assert !Author.all.merge!(:includes => :hello_posts_with_hash_conditions).find(authors(:david).id).hello_posts.empty?
344
+ assert_not_empty Author.all.merge!(includes: :hello_posts_with_hash_conditions).find(authors(:david).id).hello_posts
278
345
  end
279
346
 
280
347
  def test_loading_with_no_associations
281
- assert_nil Post.all.merge!(:includes => :author).find(posts(:authorless).id).author
348
+ assert_nil Post.all.merge!(includes: :author).find(posts(:authorless).id).author
282
349
  end
283
350
 
284
351
  # Regression test for 21c75e5
285
352
  def test_nested_loading_does_not_raise_exception_when_association_does_not_exist
286
353
  assert_nothing_raised do
287
- Post.all.merge!(:includes => {:author => :author_addresss}).find(posts(:authorless).id)
354
+ Post.all.merge!(includes: { author: :author_addresss }).find(posts(:authorless).id)
288
355
  end
289
356
  end
290
357
 
@@ -292,117 +359,117 @@ class EagerAssociationTest < ActiveRecord::TestCase
292
359
  post_id = Comment.where(author_id: nil).where.not(post_id: nil).first.post_id
293
360
 
294
361
  assert_nothing_raised do
295
- Post.preload(:comments => [{:author => :essays}]).find(post_id)
362
+ Post.preload(comments: [{ author: :essays }]).find(post_id)
296
363
  end
297
364
  end
298
365
 
299
366
  def test_nested_loading_through_has_one_association
300
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}).find(author_addresses(:david_address).id)
367
+ aa = AuthorAddress.all.merge!(includes: { author: :posts }).find(author_addresses(:david_address).id)
301
368
  assert_equal aa.author.posts.count, aa.author.posts.length
302
369
  end
303
370
 
304
371
  def test_nested_loading_through_has_one_association_with_order
305
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'author_addresses.id').find(author_addresses(:david_address).id)
372
+ aa = AuthorAddress.all.merge!(includes: { author: :posts }, order: "author_addresses.id").find(author_addresses(:david_address).id)
306
373
  assert_equal aa.author.posts.count, aa.author.posts.length
307
374
  end
308
375
 
309
376
  def test_nested_loading_through_has_one_association_with_order_on_association
310
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'authors.id').find(author_addresses(:david_address).id)
377
+ aa = AuthorAddress.all.merge!(includes: { author: :posts }, order: "authors.id").find(author_addresses(:david_address).id)
311
378
  assert_equal aa.author.posts.count, aa.author.posts.length
312
379
  end
313
380
 
314
381
  def test_nested_loading_through_has_one_association_with_order_on_nested_association
315
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'posts.id').find(author_addresses(:david_address).id)
382
+ aa = AuthorAddress.all.merge!(includes: { author: :posts }, order: "posts.id").find(author_addresses(:david_address).id)
316
383
  assert_equal aa.author.posts.count, aa.author.posts.length
317
384
  end
318
385
 
319
386
  def test_nested_loading_through_has_one_association_with_conditions
320
387
  aa = AuthorAddress.references(:author_addresses).merge(
321
- :includes => {:author => :posts},
322
- :where => "author_addresses.id > 0"
388
+ includes: { author: :posts },
389
+ where: "author_addresses.id > 0"
323
390
  ).find author_addresses(:david_address).id
324
391
  assert_equal aa.author.posts.count, aa.author.posts.length
325
392
  end
326
393
 
327
394
  def test_nested_loading_through_has_one_association_with_conditions_on_association
328
395
  aa = AuthorAddress.references(:authors).merge(
329
- :includes => {:author => :posts},
330
- :where => "authors.id > 0"
396
+ includes: { author: :posts },
397
+ where: "authors.id > 0"
331
398
  ).find author_addresses(:david_address).id
332
399
  assert_equal aa.author.posts.count, aa.author.posts.length
333
400
  end
334
401
 
335
402
  def test_nested_loading_through_has_one_association_with_conditions_on_nested_association
336
403
  aa = AuthorAddress.references(:posts).merge(
337
- :includes => {:author => :posts},
338
- :where => "posts.id > 0"
404
+ includes: { author: :posts },
405
+ where: "posts.id > 0"
339
406
  ).find author_addresses(:david_address).id
340
407
  assert_equal aa.author.posts.count, aa.author.posts.length
341
408
  end
342
409
 
343
410
  def test_eager_association_loading_with_belongs_to_and_foreign_keys
344
- pets = Pet.all.merge!(:includes => :owner).to_a
411
+ pets = Pet.all.merge!(includes: :owner).to_a
345
412
  assert_equal 4, pets.length
346
413
  end
347
414
 
348
415
  def test_eager_association_loading_with_belongs_to
349
- comments = Comment.all.merge!(:includes => :post).to_a
350
- assert_equal 11, comments.length
416
+ comments = Comment.all.merge!(includes: :post).to_a
417
+ assert_equal 12, comments.length
351
418
  titles = comments.map { |c| c.post.title }
352
- assert titles.include?(posts(:welcome).title)
353
- assert titles.include?(posts(:sti_post_and_comments).title)
419
+ assert_includes titles, posts(:welcome).title
420
+ assert_includes titles, posts(:sti_post_and_comments).title
354
421
  end
355
422
 
356
423
  def test_eager_association_loading_with_belongs_to_and_limit
357
- comments = Comment.all.merge!(:includes => :post, :limit => 5, :order => 'comments.id').to_a
424
+ comments = Comment.all.merge!(includes: :post, limit: 5, order: "comments.id").to_a
358
425
  assert_equal 5, comments.length
359
- assert_equal [1,2,3,5,6], comments.collect(&:id)
426
+ assert_equal [1, 2, 3, 5, 6], comments.collect(&:id)
360
427
  end
361
428
 
362
429
  def test_eager_association_loading_with_belongs_to_and_limit_and_conditions
363
- comments = Comment.all.merge!(:includes => :post, :where => 'post_id = 4', :limit => 3, :order => 'comments.id').to_a
430
+ comments = Comment.all.merge!(includes: :post, where: "post_id = 4", limit: 3, order: "comments.id").to_a
364
431
  assert_equal 3, comments.length
365
- assert_equal [5,6,7], comments.collect(&:id)
432
+ assert_equal [5, 6, 7], comments.collect(&:id)
366
433
  end
367
434
 
368
435
  def test_eager_association_loading_with_belongs_to_and_limit_and_offset
369
- comments = Comment.all.merge!(:includes => :post, :limit => 3, :offset => 2, :order => 'comments.id').to_a
436
+ comments = Comment.all.merge!(includes: :post, limit: 3, offset: 2, order: "comments.id").to_a
370
437
  assert_equal 3, comments.length
371
- assert_equal [3,5,6], comments.collect(&:id)
438
+ assert_equal [3, 5, 6], comments.collect(&:id)
372
439
  end
373
440
 
374
441
  def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions
375
- comments = Comment.all.merge!(:includes => :post, :where => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id').to_a
442
+ comments = Comment.all.merge!(includes: :post, where: "post_id = 4", limit: 3, offset: 1, order: "comments.id").to_a
376
443
  assert_equal 3, comments.length
377
- assert_equal [6,7,8], comments.collect(&:id)
444
+ assert_equal [6, 7, 8], comments.collect(&:id)
378
445
  end
379
446
 
380
447
  def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array
381
- comments = Comment.all.merge!(:includes => :post, :where => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id').to_a
448
+ comments = Comment.all.merge!(includes: :post, where: ["post_id = ?", 4], limit: 3, offset: 1, order: "comments.id").to_a
382
449
  assert_equal 3, comments.length
383
- assert_equal [6,7,8], comments.collect(&:id)
450
+ assert_equal [6, 7, 8], comments.collect(&:id)
384
451
  end
385
452
 
386
453
  def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
387
454
  assert_nothing_raised do
388
- Comment.includes(:post).references(:posts).where('posts.id = ?', 4)
455
+ Comment.includes(:post).references(:posts).where("posts.id = ?", 4)
389
456
  end
390
457
  end
391
458
 
392
459
  def test_eager_association_loading_with_belongs_to_and_conditions_hash
393
460
  comments = []
394
461
  assert_nothing_raised do
395
- comments = Comment.all.merge!(:includes => :post, :where => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id').to_a
462
+ comments = Comment.all.merge!(includes: :post, where: { posts: { id: 4 } }, limit: 3, order: "comments.id").to_a
396
463
  end
397
464
  assert_equal 3, comments.length
398
- assert_equal [5,6,7], comments.collect(&:id)
465
+ assert_equal [5, 6, 7], comments.collect(&:id)
399
466
  assert_no_queries do
400
467
  comments.first.post
401
468
  end
402
469
  end
403
470
 
404
471
  def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
405
- quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
472
+ quoted_posts_id = Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id")
406
473
  assert_nothing_raised do
407
474
  Comment.includes(:post).references(:posts).where("#{quoted_posts_id} = ?", 4)
408
475
  end
@@ -410,61 +477,61 @@ class EagerAssociationTest < ActiveRecord::TestCase
410
477
 
411
478
  def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
412
479
  assert_nothing_raised do
413
- Comment.all.merge!(:includes => :post, :order => 'posts.id').to_a
480
+ Comment.all.merge!(includes: :post, order: "posts.id").to_a
414
481
  end
415
482
  end
416
483
 
417
484
  def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name
418
- quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
485
+ quoted_posts_id = Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id")
419
486
  assert_nothing_raised do
420
487
  Comment.includes(:post).references(:posts).order(quoted_posts_id)
421
488
  end
422
489
  end
423
490
 
424
491
  def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations
425
- posts = Post.all.merge!(:includes => [:author, :very_special_comment], :limit => 1, :order => 'posts.id').to_a
492
+ posts = Post.all.merge!(includes: [:author, :very_special_comment], limit: 1, order: "posts.id").to_a
426
493
  assert_equal 1, posts.length
427
494
  assert_equal [1], posts.collect(&:id)
428
495
  end
429
496
 
430
497
  def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations
431
- posts = Post.all.merge!(:includes => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id').to_a
498
+ posts = Post.all.merge!(includes: [:author, :very_special_comment], limit: 1, offset: 1, order: "posts.id").to_a
432
499
  assert_equal 1, posts.length
433
500
  assert_equal [2], posts.collect(&:id)
434
501
  end
435
502
 
436
503
  def test_eager_association_loading_with_belongs_to_inferred_foreign_key_from_association_name
437
- author_favorite = AuthorFavorite.all.merge!(:includes => :favorite_author).first
504
+ author_favorite = AuthorFavorite.all.merge!(includes: :favorite_author).first
438
505
  assert_equal authors(:mary), assert_no_queries { author_favorite.favorite_author }
439
506
  end
440
507
 
441
508
  def test_eager_load_belongs_to_quotes_table_and_column_names
442
509
  job = Job.includes(:ideal_reference).find jobs(:unicyclist).id
443
510
  references(:michael_unicyclist)
444
- assert_no_queries{ assert_equal references(:michael_unicyclist), job.ideal_reference}
511
+ assert_no_queries { assert_equal references(:michael_unicyclist), job.ideal_reference }
445
512
  end
446
513
 
447
514
  def test_eager_load_has_one_quotes_table_and_column_names
448
- michael = Person.all.merge!(:includes => :favourite_reference).find(people(:michael).id)
515
+ michael = Person.all.merge!(includes: :favourite_reference).find(people(:michael).id)
449
516
  references(:michael_unicyclist)
450
- assert_no_queries{ assert_equal references(:michael_unicyclist), michael.favourite_reference}
517
+ assert_no_queries { assert_equal references(:michael_unicyclist), michael.favourite_reference }
451
518
  end
452
519
 
453
520
  def test_eager_load_has_many_quotes_table_and_column_names
454
- michael = Person.all.merge!(:includes => :references).find(people(:michael).id)
455
- references(:michael_magician,:michael_unicyclist)
456
- assert_no_queries{ assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) }
521
+ michael = Person.all.merge!(includes: :references).find(people(:michael).id)
522
+ references(:michael_magician, :michael_unicyclist)
523
+ assert_no_queries { assert_equal references(:michael_magician, :michael_unicyclist), michael.references.sort_by(&:id) }
457
524
  end
458
525
 
459
526
  def test_eager_load_has_many_through_quotes_table_and_column_names
460
- michael = Person.all.merge!(:includes => :jobs).find(people(:michael).id)
527
+ michael = Person.all.merge!(includes: :jobs).find(people(:michael).id)
461
528
  jobs(:magician, :unicyclist)
462
- assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
529
+ assert_no_queries { assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
463
530
  end
464
531
 
465
532
  def test_eager_load_has_many_with_string_keys
466
533
  subscriptions = subscriptions(:webster_awdr, :webster_rfr)
467
- subscriber =Subscriber.all.merge!(:includes => :subscriptions).find(subscribers(:second).id)
534
+ subscriber = Subscriber.all.merge!(includes: :subscriptions).find(subscribers(:second).id)
468
535
  assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
469
536
  end
470
537
 
@@ -475,32 +542,32 @@ class EagerAssociationTest < ActiveRecord::TestCase
475
542
 
476
543
  b = Book.create!
477
544
 
478
- Subscription.create!(:subscriber_id => "PL", :book_id => b.id)
545
+ Subscription.create!(subscriber_id: "PL", book_id: b.id)
479
546
  s.reload
480
547
  s.book_ids = s.book_ids
481
548
  end
482
549
 
483
550
  def test_eager_load_has_many_through_with_string_keys
484
551
  books = books(:awdr, :rfr)
485
- subscriber = Subscriber.all.merge!(:includes => :books).find(subscribers(:second).id)
552
+ subscriber = Subscriber.all.merge!(includes: :books).find(subscribers(:second).id)
486
553
  assert_equal books, subscriber.books.sort_by(&:id)
487
554
  end
488
555
 
489
556
  def test_eager_load_belongs_to_with_string_keys
490
557
  subscriber = subscribers(:second)
491
- subscription = Subscription.all.merge!(:includes => :subscriber).find(subscriptions(:webster_awdr).id)
558
+ subscription = Subscription.all.merge!(includes: :subscriber).find(subscriptions(:webster_awdr).id)
492
559
  assert_equal subscriber, subscription.subscriber
493
560
  end
494
561
 
495
562
  def test_eager_association_loading_with_explicit_join
496
- posts = Post.all.merge!(:includes => :comments, :joins => "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", :limit => 1, :order => 'author_id').to_a
563
+ posts = Post.all.merge!(includes: :comments, joins: "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", limit: 1, order: "author_id").to_a
497
564
  assert_equal 1, posts.length
498
565
  end
499
566
 
500
567
  def test_eager_with_has_many_through
501
- posts_with_comments = people(:michael).posts.merge(:includes => :comments, :order => 'posts.id').to_a
502
- posts_with_author = people(:michael).posts.merge(:includes => :author, :order => 'posts.id').to_a
503
- posts_with_comments_and_author = people(:michael).posts.merge(:includes => [ :comments, :author ], :order => 'posts.id').to_a
568
+ posts_with_comments = people(:michael).posts.merge(includes: :comments, order: "posts.id").to_a
569
+ posts_with_author = people(:michael).posts.merge(includes: :author, order: "posts.id").to_a
570
+ posts_with_comments_and_author = people(:michael).posts.merge(includes: [ :comments, :author ], order: "posts.id").to_a
504
571
  assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum + post.comments.size }
505
572
  assert_equal authors(:david), assert_no_queries { posts_with_author.first.author }
506
573
  assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
@@ -508,35 +575,58 @@ class EagerAssociationTest < ActiveRecord::TestCase
508
575
 
509
576
  def test_eager_with_has_many_through_a_belongs_to_association
510
577
  author = authors(:mary)
511
- Post.create!(:author => author, :title => "TITLE", :body => "BODY")
512
- author.author_favorites.create(:favorite_author_id => 1)
513
- author.author_favorites.create(:favorite_author_id => 2)
514
- posts_with_author_favorites = author.posts.merge(:includes => :author_favorites).to_a
578
+ Post.create!(author: author, title: "TITLE", body: "BODY")
579
+ author.author_favorites.create(favorite_author_id: 1)
580
+ author.author_favorites.create(favorite_author_id: 2)
581
+ posts_with_author_favorites = author.posts.merge(includes: :author_favorites).to_a
515
582
  assert_no_queries { posts_with_author_favorites.first.author_favorites.first.author_id }
516
583
  end
517
584
 
518
585
  def test_eager_with_has_many_through_an_sti_join_model
519
- author = Author.all.merge!(:includes => :special_post_comments, :order => 'authors.id').first
586
+ author = Author.all.merge!(includes: :special_post_comments, order: "authors.id").first
520
587
  assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }
521
588
  end
522
589
 
590
+ def test_preloading_with_has_one_through_an_sti_with_after_initialize
591
+ author_a = Author.create!(name: "A")
592
+ author_b = Author.create!(name: "B")
593
+ post_a = StiPost.create!(author: author_a, title: "TITLE", body: "BODY")
594
+ post_b = SpecialPost.create!(author: author_b, title: "TITLE", body: "BODY")
595
+ comment_a = SpecialComment.create!(post: post_a, body: "TEST")
596
+ comment_b = SpecialComment.create!(post: post_b, body: "TEST")
597
+ reset_callbacks(StiPost, :initialize) do
598
+ StiPost.after_initialize { author }
599
+ SpecialComment.where(id: [comment_a.id, comment_b.id]).includes(:author).each do |comment|
600
+ assert comment.author
601
+ end
602
+ end
603
+ end
604
+
605
+ def test_preloading_has_many_through_with_implicit_source
606
+ authors = Author.includes(:very_special_comments).to_a.sort_by(&:id)
607
+ assert_no_queries do
608
+ special_comment_authors = authors.map { |author| [author.name, author.very_special_comments.size] }
609
+ assert_equal [["David", 1], ["Mary", 0], ["Bob", 0]], special_comment_authors
610
+ end
611
+ end
612
+
523
613
  def test_eager_with_has_many_through_an_sti_join_model_with_conditions_on_both
524
- author = Author.all.merge!(:includes => :special_nonexistent_post_comments, :order => 'authors.id').first
614
+ author = Author.all.merge!(includes: :special_nonexistent_post_comments, order: "authors.id").first
525
615
  assert_equal [], author.special_nonexistent_post_comments
526
616
  end
527
617
 
528
618
  def test_eager_with_has_many_through_join_model_with_conditions
529
- assert_equal Author.all.merge!(:includes => :hello_post_comments,
530
- :order => 'authors.id').first.hello_post_comments.sort_by(&:id),
531
- Author.all.merge!(:order => 'authors.id').first.hello_post_comments.sort_by(&:id)
619
+ assert_equal Author.all.merge!(includes: :hello_post_comments,
620
+ order: "authors.id").first.hello_post_comments.sort_by(&:id),
621
+ Author.all.merge!(order: "authors.id").first.hello_post_comments.sort_by(&:id)
532
622
  end
533
623
 
534
624
  def test_eager_with_has_many_through_join_model_with_conditions_on_top_level
535
- assert_equal comments(:more_greetings), Author.all.merge!(:includes => :comments_with_order_and_conditions).find(authors(:david).id).comments_with_order_and_conditions.first
625
+ assert_equal comments(:more_greetings), Author.all.merge!(includes: :comments_with_order_and_conditions).find(authors(:david).id).comments_with_order_and_conditions.first
536
626
  end
537
627
 
538
628
  def test_eager_with_has_many_through_join_model_with_include
539
- author_comments = Author.all.merge!(:includes => :comments_with_include).find(authors(:david).id).comments_with_include.to_a
629
+ author_comments = Author.all.merge!(includes: :comments_with_include).find(authors(:david).id).comments_with_include.to_a
540
630
  assert_no_queries do
541
631
  author_comments.first.post.title
542
632
  end
@@ -544,7 +634,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
544
634
 
545
635
  def test_eager_with_has_many_through_with_conditions_join_model_with_include
546
636
  post_tags = Post.find(posts(:welcome).id).misc_tags
547
- eager_post_tags = Post.all.merge!(:includes => :misc_tags).find(1).misc_tags
637
+ eager_post_tags = Post.all.merge!(includes: :misc_tags).find(1).misc_tags
548
638
  assert_equal post_tags, eager_post_tags
549
639
  end
550
640
 
@@ -555,67 +645,67 @@ class EagerAssociationTest < ActiveRecord::TestCase
555
645
  end
556
646
 
557
647
  def test_eager_with_has_many_and_limit
558
- posts = Post.all.merge!(:order => 'posts.id asc', :includes => [ :author, :comments ], :limit => 2).to_a
648
+ posts = Post.all.merge!(order: "posts.id asc", includes: [ :author, :comments ], limit: 2).to_a
559
649
  assert_equal 2, posts.size
560
650
  assert_equal 3, posts.inject(0) { |sum, post| sum + post.comments.size }
561
651
  end
562
652
 
563
653
  def test_eager_with_has_many_and_limit_and_conditions
564
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => "posts.body = 'hello'", :order => "posts.id").to_a
654
+ posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: "posts.body = 'hello'", order: "posts.id").to_a
565
655
  assert_equal 2, posts.size
566
- assert_equal [4,5], posts.collect(&:id)
656
+ assert_equal [4, 5], posts.collect(&:id)
567
657
  end
568
658
 
569
659
  def test_eager_with_has_many_and_limit_and_conditions_array
570
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => [ "posts.body = ?", 'hello' ], :order => "posts.id").to_a
660
+ posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: [ "posts.body = ?", "hello" ], order: "posts.id").to_a
571
661
  assert_equal 2, posts.size
572
- assert_equal [4,5], posts.collect(&:id)
662
+ assert_equal [4, 5], posts.collect(&:id)
573
663
  end
574
664
 
575
665
  def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
576
- posts = Post.includes(:author, :comments).limit(2).references(:author).where("authors.name = ?", 'David')
666
+ posts = Post.includes(:author, :comments).limit(2).references("author").where("authors.name = ?", "David")
577
667
  assert_equal 2, posts.size
578
668
 
579
- count = Post.includes(:author, :comments).limit(2).references(:author).where("authors.name = ?", 'David').count
669
+ count = Post.includes(:author, :comments).limit(2).references("author").where("authors.name = ?", "David").count
580
670
  assert_equal posts.size, count
581
671
  end
582
672
 
583
673
  def test_eager_with_has_many_and_limit_and_high_offset
584
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10, :where => { 'authors.name' => 'David' }).to_a
674
+ posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10, where: { "authors.name" => "David" }).to_a
585
675
  assert_equal 0, posts.size
586
676
  end
587
677
 
588
678
  def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
589
679
  assert_queries(1) do
590
680
  posts = Post.references(:authors, :comments).
591
- merge(:includes => [ :author, :comments ], :limit => 2, :offset => 10,
592
- :where => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ]).to_a
681
+ merge(includes: [ :author, :comments ], limit: 2, offset: 10,
682
+ where: [ "authors.name = ? and comments.body = ?", "David", "go crazy" ]).to_a
593
683
  assert_equal 0, posts.size
594
684
  end
595
685
  end
596
686
 
597
687
  def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
598
688
  assert_queries(1) do
599
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10,
600
- :where => { 'authors.name' => 'David', 'comments.body' => 'go crazy' }).to_a
689
+ posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10,
690
+ where: { "authors.name" => "David", "comments.body" => "go crazy" }).to_a
601
691
  assert_equal 0, posts.size
602
692
  end
603
693
  end
604
694
 
605
695
  def test_count_eager_with_has_many_and_limit_and_high_offset
606
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10, :where => { 'authors.name' => 'David' }).count(:all)
696
+ posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10, where: { "authors.name" => "David" }).count(:all)
607
697
  assert_equal 0, posts
608
698
  end
609
699
 
610
700
  def test_eager_with_has_many_and_limit_with_no_results
611
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => "posts.title = 'magic forest'").to_a
701
+ posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: "posts.title = 'magic forest'").to_a
612
702
  assert_equal 0, posts.size
613
703
  end
614
704
 
615
705
  def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
616
706
  author = authors(:david)
617
707
  author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
618
- assert_equal author_posts_without_comments.size, author.posts.includes(:comments).where('comments.id is null').references(:comments).count
708
+ assert_equal author_posts_without_comments.size, author.posts.includes(:comments).where("comments.id is null").references(:comments).count
619
709
  end
620
710
 
621
711
  def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
@@ -625,13 +715,13 @@ class EagerAssociationTest < ActiveRecord::TestCase
625
715
  end
626
716
 
627
717
  def test_eager_with_has_and_belongs_to_many_and_limit
628
- posts = Post.all.merge!(:includes => :categories, :order => "posts.id", :limit => 3).to_a
718
+ posts = Post.all.merge!(includes: :categories, order: "posts.id", limit: 3).to_a
629
719
  assert_equal 3, posts.size
630
720
  assert_equal 2, posts[0].categories.size
631
721
  assert_equal 1, posts[1].categories.size
632
722
  assert_equal 0, posts[2].categories.size
633
- assert posts[0].categories.include?(categories(:technology))
634
- assert posts[1].categories.include?(categories(:general))
723
+ assert_includes posts[0].categories, categories(:technology)
724
+ assert_includes posts[1].categories, categories(:general)
635
725
  end
636
726
 
637
727
  # Since the preloader for habtm gets raw row hashes from the database and then
@@ -647,7 +737,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
647
737
  post1 = general.posts.to_a.find { |p| p == welcome }
648
738
  post2 = technology.posts.to_a.find { |p| p == welcome }
649
739
 
650
- assert_equal post1.object_id, post2.object_id
740
+ assert_same post1, post2
651
741
  end
652
742
 
653
743
  def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
@@ -675,7 +765,6 @@ class EagerAssociationTest < ActiveRecord::TestCase
675
765
  .where("comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'")
676
766
  .references(:comments)
677
767
  .scoping do
678
-
679
768
  posts = authors(:david).posts.limit(2).to_a
680
769
  assert_equal 2, posts.size
681
770
  end
@@ -684,39 +773,38 @@ class EagerAssociationTest < ActiveRecord::TestCase
684
773
  .where("authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')")
685
774
  .references(:authors, :comments)
686
775
  .scoping do
687
-
688
776
  count = Post.limit(2).count
689
777
  assert_equal count, posts.size
690
778
  end
691
779
  end
692
780
 
693
781
  def test_eager_association_loading_with_habtm
694
- posts = Post.all.merge!(:includes => :categories, :order => "posts.id").to_a
782
+ posts = Post.all.merge!(includes: :categories, order: "posts.id").to_a
695
783
  assert_equal 2, posts[0].categories.size
696
784
  assert_equal 1, posts[1].categories.size
697
785
  assert_equal 0, posts[2].categories.size
698
- assert posts[0].categories.include?(categories(:technology))
699
- assert posts[1].categories.include?(categories(:general))
786
+ assert_includes posts[0].categories, categories(:technology)
787
+ assert_includes posts[1].categories, categories(:general)
700
788
  end
701
789
 
702
790
  def test_eager_with_inheritance
703
- SpecialPost.all.merge!(:includes => [ :comments ]).to_a
791
+ SpecialPost.all.merge!(includes: [ :comments ]).to_a
704
792
  end
705
793
 
706
794
  def test_eager_has_one_with_association_inheritance
707
- post = Post.all.merge!(:includes => [ :very_special_comment ]).find(4)
795
+ post = Post.all.merge!(includes: [ :very_special_comment ]).find(4)
708
796
  assert_equal "VerySpecialComment", post.very_special_comment.class.to_s
709
797
  end
710
798
 
711
799
  def test_eager_has_many_with_association_inheritance
712
- post = Post.all.merge!(:includes => [ :special_comments ]).find(4)
800
+ post = Post.all.merge!(includes: [ :special_comments ]).find(4)
713
801
  post.special_comments.each do |special_comment|
714
802
  assert special_comment.is_a?(SpecialComment)
715
803
  end
716
804
  end
717
805
 
718
806
  def test_eager_habtm_with_association_inheritance
719
- post = Post.all.merge!(:includes => [ :special_categories ]).find(6)
807
+ post = Post.all.merge!(includes: [ :special_categories ]).find(6)
720
808
  assert_equal 1, post.special_categories.size
721
809
  post.special_categories.each do |special_category|
722
810
  assert_equal "SpecialCategory", special_category.class.to_s
@@ -725,8 +813,8 @@ class EagerAssociationTest < ActiveRecord::TestCase
725
813
 
726
814
  def test_eager_with_has_one_dependent_does_not_destroy_dependent
727
815
  assert_not_nil companies(:first_firm).account
728
- f = Firm.all.merge!(:includes => :account,
729
- :where => ["companies.name = ?", "37signals"]).first
816
+ f = Firm.all.merge!(includes: :account,
817
+ where: ["companies.name = ?", "37signals"]).first
730
818
  assert_not_nil f.account
731
819
  assert_equal companies(:first_firm, :reload).account, f.account
732
820
  end
@@ -739,38 +827,54 @@ class EagerAssociationTest < ActiveRecord::TestCase
739
827
  end
740
828
 
741
829
  def test_eager_with_invalid_association_reference
742
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
743
- Post.all.merge!(:includes=> :monkeys ).find(6)
830
+ e = assert_raise(ActiveRecord::AssociationNotFoundError) {
831
+ Post.all.merge!(includes: :monkeys).find(6)
744
832
  }
745
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
746
- Post.all.merge!(:includes=>[ :monkeys ]).find(6)
833
+ assert_match(/Association named 'monkeys' was not found on Post; perhaps you misspelled it\?/, e.message)
834
+
835
+ e = assert_raise(ActiveRecord::AssociationNotFoundError) {
836
+ Post.all.merge!(includes: [ :monkeys ]).find(6)
747
837
  }
748
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
749
- Post.all.merge!(:includes=>[ 'monkeys' ]).find(6)
838
+ assert_match(/Association named 'monkeys' was not found on Post; perhaps you misspelled it\?/, e.message)
839
+
840
+ e = assert_raise(ActiveRecord::AssociationNotFoundError) {
841
+ Post.all.merge!(includes: [ "monkeys" ]).find(6)
750
842
  }
751
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
752
- Post.all.merge!(:includes=>[ :monkeys, :elephants ]).find(6)
843
+ assert_match(/Association named 'monkeys' was not found on Post; perhaps you misspelled it\?/, e.message)
844
+
845
+ e = assert_raise(ActiveRecord::AssociationNotFoundError) {
846
+ Post.all.merge!(includes: [ :monkeys, :elephants ]).find(6)
753
847
  }
848
+ assert_match(/Association named 'monkeys' was not found on Post; perhaps you misspelled it\?/, e.message)
849
+ end
850
+
851
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
852
+ test "exceptions have suggestions for fix" do
853
+ error = assert_raise(ActiveRecord::AssociationNotFoundError) {
854
+ Post.all.merge!(includes: :monkeys).find(6)
855
+ }
856
+ assert_match "Did you mean?", error.message
857
+ end
754
858
  end
755
859
 
756
860
  def test_eager_has_many_through_with_order
757
- tag = OrderedTag.create(name: 'Foo')
758
- post1 = Post.create!(title: 'Beaches', body: "I like beaches!")
759
- post2 = Post.create!(title: 'Pools', body: "I like pools!")
861
+ tag = OrderedTag.create(name: "Foo")
862
+ post1 = Post.create!(title: "Beaches", body: "I like beaches!")
863
+ post2 = Post.create!(title: "Pools", body: "I like pools!")
760
864
 
761
- Tagging.create!(taggable_type: 'Post', taggable_id: post1.id, tag: tag)
762
- Tagging.create!(taggable_type: 'Post', taggable_id: post2.id, tag: tag)
865
+ Tagging.create!(taggable_type: "Post", taggable_id: post1.id, tag: tag)
866
+ Tagging.create!(taggable_type: "Post", taggable_id: post2.id, tag: tag)
763
867
 
764
868
  tag_with_includes = OrderedTag.includes(:tagged_posts).find(tag.id)
765
- assert_equal(tag_with_includes.taggings.map(&:taggable).map(&:title), tag_with_includes.tagged_posts.map(&:title))
869
+ assert_equal tag_with_includes.ordered_taggings.map(&:taggable).map(&:title), tag_with_includes.tagged_posts.map(&:title)
766
870
  end
767
871
 
768
872
  def test_eager_has_many_through_multiple_with_order
769
- tag1 = OrderedTag.create!(name: 'Bar')
770
- tag2 = OrderedTag.create!(name: 'Foo')
873
+ tag1 = OrderedTag.create!(name: "Bar")
874
+ tag2 = OrderedTag.create!(name: "Foo")
771
875
 
772
- post1 = Post.create!(title: 'Beaches', body: "I like beaches!")
773
- post2 = Post.create!(title: 'Pools', body: "I like pools!")
876
+ post1 = Post.create!(title: "Beaches", body: "I like beaches!")
877
+ post2 = Post.create!(title: "Pools", body: "I like pools!")
774
878
 
775
879
  Tagging.create!(taggable: post1, tag: tag1)
776
880
  Tagging.create!(taggable: post2, tag: tag1)
@@ -786,7 +890,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
786
890
  end
787
891
 
788
892
  def test_eager_with_default_scope
789
- developer = EagerDeveloperWithDefaultScope.where(:name => 'David').first
893
+ developer = EagerDeveloperWithDefaultScope.where(name: "David").first
790
894
  projects = Project.order(:id).to_a
791
895
  assert_no_queries do
792
896
  assert_equal(projects, developer.projects)
@@ -794,7 +898,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
794
898
  end
795
899
 
796
900
  def test_eager_with_default_scope_as_class_method
797
- developer = EagerDeveloperWithClassMethodDefaultScope.where(:name => 'David').first
901
+ developer = EagerDeveloperWithClassMethodDefaultScope.where(name: "David").first
798
902
  projects = Project.order(:id).to_a
799
903
  assert_no_queries do
800
904
  assert_equal(projects, developer.projects)
@@ -811,7 +915,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
811
915
  end
812
916
 
813
917
  def test_eager_with_default_scope_as_class_method_using_find_by_method
814
- developer = EagerDeveloperWithClassMethodDefaultScope.find_by(name: 'David')
918
+ developer = EagerDeveloperWithClassMethodDefaultScope.find_by(name: "David")
815
919
  projects = Project.order(:id).to_a
816
920
  assert_no_queries do
817
921
  assert_equal(projects, developer.projects)
@@ -819,7 +923,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
819
923
  end
820
924
 
821
925
  def test_eager_with_default_scope_as_lambda
822
- developer = EagerDeveloperWithLambdaDefaultScope.where(:name => 'David').first
926
+ developer = EagerDeveloperWithLambdaDefaultScope.where(name: "David").first
823
927
  projects = Project.order(:id).to_a
824
928
  assert_no_queries do
825
929
  assert_equal(projects, developer.projects)
@@ -828,8 +932,8 @@ class EagerAssociationTest < ActiveRecord::TestCase
828
932
 
829
933
  def test_eager_with_default_scope_as_block
830
934
  # warm up the habtm cache
831
- EagerDeveloperWithBlockDefaultScope.where(:name => 'David').first.projects
832
- developer = EagerDeveloperWithBlockDefaultScope.where(:name => 'David').first
935
+ EagerDeveloperWithBlockDefaultScope.where(name: "David").first.projects
936
+ developer = EagerDeveloperWithBlockDefaultScope.where(name: "David").first
833
937
  projects = Project.order(:id).to_a
834
938
  assert_no_queries do
835
939
  assert_equal(projects, developer.projects)
@@ -837,108 +941,70 @@ class EagerAssociationTest < ActiveRecord::TestCase
837
941
  end
838
942
 
839
943
  def test_eager_with_default_scope_as_callable
840
- developer = EagerDeveloperWithCallableDefaultScope.where(:name => 'David').first
944
+ developer = EagerDeveloperWithCallableDefaultScope.where(name: "David").first
841
945
  projects = Project.order(:id).to_a
842
946
  assert_no_queries do
843
947
  assert_equal(projects, developer.projects)
844
948
  end
845
949
  end
846
950
 
847
- def find_all_ordered(className, include=nil)
848
- className.all.merge!(:order=>"#{className.table_name}.#{className.primary_key}", :includes=>include).to_a
849
- end
850
-
851
951
  def test_limited_eager_with_order
852
- unless current_adapter?(:IBM_DBAdapter)
853
- assert_equal(
854
- posts(:thinking, :sti_comments),
855
- Post.all.merge!(
856
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
857
- :order => 'UPPER(posts.title)', :limit => 2, :offset => 1
858
- ).to_a
859
- )
860
- assert_equal(
861
- posts(:sti_post_and_comments, :sti_comments),
862
- Post.all.merge!(
863
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
864
- :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1
865
- ).to_a
866
- )
867
- else
868
- assert_equal(
869
- posts(:thinking, :sti_comments),
870
- Post.all.merge!(
871
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
872
- :order => 'posts.id', :limit => 2, :offset => 1
873
- ).to_a
874
- )
875
- assert_equal(
876
- posts(:sti_post_and_comments, :sti_comments),
877
- Post.all.merge!(
878
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
879
- :order => 'posts.id DESC', :limit => 2, :offset => 1
880
- ).to_a
881
- )
882
- end
952
+ assert_equal(
953
+ posts(:thinking, :sti_comments),
954
+ Post.all.merge!(
955
+ includes: [:author, :comments], where: { "authors.name" => "David" },
956
+ order: "UPPER(posts.title)", limit: 2, offset: 1
957
+ ).to_a
958
+ )
959
+ assert_equal(
960
+ posts(:sti_post_and_comments, :sti_comments),
961
+ Post.all.merge!(
962
+ includes: [:author, :comments], where: { "authors.name" => "David" },
963
+ order: "UPPER(posts.title) DESC", limit: 2, offset: 1
964
+ ).to_a
965
+ )
883
966
  end
884
967
 
885
968
  def test_limited_eager_with_multiple_order_columns
886
- unless current_adapter?(:IBM_DBAdapter)
887
- assert_equal(
888
- posts(:thinking, :sti_comments),
889
- Post.all.merge!(
890
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
891
- :order => ['UPPER(posts.title)', 'posts.id'], :limit => 2, :offset => 1
892
- ).to_a
893
- )
894
- assert_equal(
895
- posts(:sti_post_and_comments, :sti_comments),
896
- Post.all.merge!(
897
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
898
- :order => ['UPPER(posts.title) DESC', 'posts.id'], :limit => 2, :offset => 1
899
- ).to_a
900
- )
901
- else
902
- assert_equal(
903
- posts(:thinking, :sti_comments),
904
- Post.all.merge!(
905
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
906
- :order => ['posts.id'], :limit => 2, :offset => 1
907
- ).to_a
908
- )
909
- assert_equal(
910
- posts(:sti_post_and_comments, :sti_comments),
911
- Post.all.merge!(
912
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
913
- :order => ['posts.id DESC'], :limit => 2, :offset => 1
914
- ).to_a
915
- )
916
- end
969
+ assert_equal(
970
+ posts(:thinking, :sti_comments),
971
+ Post.all.merge!(
972
+ includes: [:author, :comments], where: { "authors.name" => "David" },
973
+ order: ["UPPER(posts.title)", "posts.id"], limit: 2, offset: 1
974
+ ).to_a
975
+ )
976
+ assert_equal(
977
+ posts(:sti_post_and_comments, :sti_comments),
978
+ Post.all.merge!(
979
+ includes: [:author, :comments], where: { "authors.name" => "David" },
980
+ order: ["UPPER(posts.title) DESC", "posts.id"], limit: 2, offset: 1
981
+ ).to_a
982
+ )
917
983
  end
918
984
 
919
985
  def test_limited_eager_with_numeric_in_association
920
986
  assert_equal(
921
987
  people(:david, :susan),
922
988
  Person.references(:number1_fans_people).merge(
923
- :includes => [:readers, :primary_contact, :number1_fan],
924
- :where => "number1_fans_people.first_name like 'M%'",
925
- :order => 'people.id', :limit => 2, :offset => 0
989
+ includes: [:readers, :primary_contact, :number1_fan],
990
+ where: "number1_fans_people.first_name like 'M%'",
991
+ order: "people.id", limit: 2, offset: 0
926
992
  ).to_a
927
993
  )
928
994
  end
929
995
 
930
996
  def test_polymorphic_type_condition
931
- post = Post.all.merge!(:includes => :taggings).find(posts(:thinking).id)
932
- assert post.taggings.include?(taggings(:thinking_general))
933
- post = SpecialPost.all.merge!(:includes => :taggings).find(posts(:thinking).id)
934
- assert post.taggings.include?(taggings(:thinking_general))
997
+ post = Post.all.merge!(includes: :taggings).find(posts(:thinking).id)
998
+ assert_includes post.taggings, taggings(:thinking_general)
999
+ post = SpecialPost.all.merge!(includes: :taggings).find(posts(:thinking).id)
1000
+ assert_includes post.taggings, taggings(:thinking_general)
935
1001
  end
936
1002
 
937
1003
  def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm
938
1004
  # Eager includes of has many and habtm associations aren't necessarily sorted in the same way
939
1005
  def assert_equal_after_sort(item1, item2, item3 = nil)
940
- assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id})
941
- assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3
1006
+ assert_equal(item1.sort { |a, b| a.id <=> b.id }, item2.sort { |a, b| a.id <=> b.id })
1007
+ assert_equal(item3.sort { |a, b| a.id <=> b.id }, item2.sort { |a, b| a.id <=> b.id }) if item3
942
1008
  end
943
1009
  # Test regular association, association with conditions, association with
944
1010
  # STI, and association with conditions assured not to be true
@@ -956,7 +1022,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
956
1022
  d3 = find_all_ordered(className, [:posts, post_type])
957
1023
  assert_equal(d1[i], d3[i])
958
1024
  assert_equal_after_sort(d1[i].posts, d3[i].posts)
959
- assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type))
1025
+ assert_equal_after_sort(d1[i].public_send(post_type), d2[i].public_send(post_type), d3[i].public_send(post_type))
960
1026
  end
961
1027
  end
962
1028
  end
@@ -967,7 +1033,11 @@ class EagerAssociationTest < ActiveRecord::TestCase
967
1033
  d2 = find_all_ordered(Firm, :account)
968
1034
  d1.each_index do |i|
969
1035
  assert_equal(d1[i], d2[i])
970
- assert_equal(d1[i].account, d2[i].account)
1036
+ if d1[i].account.nil?
1037
+ assert_nil(d2[i].account)
1038
+ else
1039
+ assert_equal(d1[i].account, d2[i].account)
1040
+ end
971
1041
  end
972
1042
  end
973
1043
 
@@ -977,28 +1047,34 @@ class EagerAssociationTest < ActiveRecord::TestCase
977
1047
  d2 = find_all_ordered(Client, firm_types)
978
1048
  d1.each_index do |i|
979
1049
  assert_equal(d1[i], d2[i])
980
- firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) }
1050
+ firm_types.each do |type|
1051
+ if (expected = d1[i].public_send(type)).nil?
1052
+ assert_nil(d2[i].public_send(type))
1053
+ else
1054
+ assert_equal(expected, d2[i].public_send(type))
1055
+ end
1056
+ end
981
1057
  end
982
1058
  end
983
1059
  def test_eager_with_valid_association_as_string_not_symbol
984
- assert_nothing_raised { Post.all.merge!(:includes => 'comments').to_a }
1060
+ assert_nothing_raised { Post.all.merge!(includes: "comments").to_a }
985
1061
  end
986
1062
 
987
1063
  def test_eager_with_floating_point_numbers
988
1064
  assert_queries(2) do
989
1065
  # Before changes, the floating point numbers will be interpreted as table names and will cause this to run in one query
990
- Comment.all.merge!(:where => "123.456 = 123.456", :includes => :post).to_a
1066
+ Comment.all.merge!(where: "123.456 = 123.456", includes: :post).to_a
991
1067
  end
992
1068
  end
993
1069
 
994
1070
  def test_preconfigured_includes_with_belongs_to
995
1071
  author = posts(:welcome).author_with_posts
996
- assert_no_queries {assert_equal 5, author.posts.size}
1072
+ assert_no_queries { assert_equal 5, author.posts.size }
997
1073
  end
998
1074
 
999
1075
  def test_preconfigured_includes_with_has_one
1000
1076
  comment = posts(:sti_comments).very_special_comment_with_post
1001
- assert_no_queries {assert_equal posts(:sti_comments), comment.post}
1077
+ assert_no_queries { assert_equal posts(:sti_comments), comment.post }
1002
1078
  end
1003
1079
 
1004
1080
  def test_eager_association_with_scope_with_joins
@@ -1040,13 +1116,13 @@ class EagerAssociationTest < ActiveRecord::TestCase
1040
1116
  end
1041
1117
 
1042
1118
  def test_association_loading_notification
1043
- notifications = messages_for('instantiation.active_record') do
1044
- Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1119
+ notifications = messages_for("instantiation.active_record") do
1120
+ Developer.all.merge!(includes: "projects", where: { "developers_projects.access_level" => 1 }, limit: 5).to_a.size
1045
1121
  end
1046
1122
 
1047
1123
  message = notifications.first
1048
1124
  payload = message.last
1049
- count = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1125
+ count = Developer.all.merge!(includes: "projects", where: { "developers_projects.access_level" => 1 }, limit: 5).to_a.size
1050
1126
 
1051
1127
  # eagerloaded row count should be greater than just developer count
1052
1128
  assert_operator payload[:record_count], :>, count
@@ -1054,7 +1130,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
1054
1130
  end
1055
1131
 
1056
1132
  def test_base_messages
1057
- notifications = messages_for('instantiation.active_record') do
1133
+ notifications = messages_for("instantiation.active_record") do
1058
1134
  Developer.all.to_a
1059
1135
  end
1060
1136
  message = notifications.first
@@ -1076,61 +1152,55 @@ class EagerAssociationTest < ActiveRecord::TestCase
1076
1152
  end
1077
1153
 
1078
1154
  def test_load_with_sti_sharing_association
1079
- assert_queries(2) do #should not do 1 query per subclass
1155
+ assert_queries(2) do # should not do 1 query per subclass
1080
1156
  Comment.includes(:post).to_a
1081
1157
  end
1082
1158
  end
1083
1159
 
1084
1160
  def test_conditions_on_join_table_with_include_and_limit
1085
- assert_equal 3, Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1161
+ assert_equal 3, Developer.all.merge!(includes: "projects", where: { "developers_projects.access_level" => 1 }, limit: 5).to_a.size
1086
1162
  end
1087
1163
 
1088
1164
  def test_dont_create_temporary_active_record_instances
1089
1165
  Developer.instance_count = 0
1090
- developers = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a
1166
+ developers = Developer.all.merge!(includes: "projects", where: { "developers_projects.access_level" => 1 }, limit: 5).to_a
1091
1167
  assert_equal developers.count, Developer.instance_count
1092
1168
  end
1093
1169
 
1094
1170
  def test_order_on_join_table_with_include_and_limit
1095
- assert_equal 5, Developer.all.merge!(:includes => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).to_a.size
1171
+ assert_equal 5, Developer.all.merge!(includes: "projects", order: "developers_projects.joined_on DESC", limit: 5).to_a.size
1096
1172
  end
1097
1173
 
1098
1174
  def test_eager_loading_with_order_on_joined_table_preloads
1099
1175
  posts = assert_queries(2) do
1100
- Post.all.merge!(:joins => :comments, :includes => :author, :order => 'comments.id DESC').to_a
1176
+ Post.all.merge!(joins: :comments, includes: :author, order: "comments.id DESC").to_a
1101
1177
  end
1102
- assert_equal posts(:eager_other), posts[1]
1103
- assert_equal authors(:mary), assert_no_queries { posts[1].author}
1178
+ assert_equal posts(:eager_other), posts[2]
1179
+ assert_equal authors(:mary), assert_no_queries { posts[2].author }
1104
1180
  end
1105
1181
 
1106
1182
  def test_eager_loading_with_conditions_on_joined_table_preloads
1107
1183
  posts = assert_queries(2) do
1108
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => [:comments], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1109
- end
1110
- assert_equal [posts(:welcome)], posts
1111
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1112
-
1113
- posts = assert_queries(2) do
1114
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => [:comments], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1184
+ Post.all.merge!(select: "distinct posts.*", includes: :author, joins: [:comments], where: "comments.body like 'Thank you%'", order: "posts.id").to_a
1115
1185
  end
1116
1186
  assert_equal [posts(:welcome)], posts
1117
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1187
+ assert_equal authors(:david), assert_no_queries { posts[0].author }
1118
1188
 
1119
1189
  posts = assert_queries(2) do
1120
- Post.all.merge!(:includes => :author, :joins => {:taggings => :tag}, :where => "tags.name = 'General'", :order => 'posts.id').to_a
1190
+ Post.all.merge!(includes: :author, joins: { taggings: :tag }, where: "tags.name = 'General'", order: "posts.id").to_a
1121
1191
  end
1122
1192
  assert_equal posts(:welcome, :thinking), posts
1123
1193
 
1124
1194
  posts = assert_queries(2) do
1125
- Post.all.merge!(:includes => :author, :joins => {:taggings => {:tag => :taggings}}, :where => "taggings_tags.super_tag_id=2", :order => 'posts.id').to_a
1195
+ Post.all.merge!(includes: :author, joins: { taggings: { tag: :taggings } }, where: "taggings_tags.super_tag_id=2", order: "posts.id").to_a
1126
1196
  end
1127
1197
  assert_equal posts(:welcome, :thinking), posts
1128
1198
  end
1129
1199
 
1130
1200
  def test_preload_has_many_with_association_condition_and_default_scope
1131
- post = Post.create!(:title => 'Beaches', :body => "I like beaches!")
1132
- Reader.create! :person => people(:david), :post => post
1133
- LazyReader.create! :person => people(:susan), :post => post
1201
+ post = Post.create!(title: "Beaches", body: "I like beaches!")
1202
+ Reader.create! person: people(:david), post: post
1203
+ LazyReader.create! person: people(:susan), post: post
1134
1204
 
1135
1205
  assert_equal 1, post.lazy_readers.to_a.size
1136
1206
  assert_equal 2, post.lazy_readers_skimmers_or_not.to_a.size
@@ -1141,69 +1211,62 @@ class EagerAssociationTest < ActiveRecord::TestCase
1141
1211
 
1142
1212
  def test_eager_loading_with_conditions_on_string_joined_table_preloads
1143
1213
  posts = assert_queries(2) do
1144
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1214
+ Post.all.merge!(select: "distinct posts.*", includes: :author, joins: "INNER JOIN comments on comments.post_id = posts.id", where: "comments.body like 'Thank you%'", order: "posts.id").to_a
1145
1215
  end
1146
1216
  assert_equal [posts(:welcome)], posts
1147
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1217
+ assert_equal authors(:david), assert_no_queries { posts[0].author }
1148
1218
 
1149
1219
  posts = assert_queries(2) do
1150
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1220
+ Post.all.merge!(select: "distinct posts.*", includes: :author, joins: ["INNER JOIN comments on comments.post_id = posts.id"], where: "comments.body like 'Thank you%'", order: "posts.id").to_a
1151
1221
  end
1152
1222
  assert_equal [posts(:welcome)], posts
1153
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1223
+ assert_equal authors(:david), assert_no_queries { posts[0].author }
1154
1224
  end
1155
1225
 
1156
1226
  def test_eager_loading_with_select_on_joined_table_preloads
1157
1227
  posts = assert_queries(2) do
1158
- Post.all.merge!(:select => 'posts.*, authors.name as author_name', :includes => :comments, :joins => :author, :order => 'posts.id').to_a
1228
+ Post.all.merge!(select: "posts.*, authors.name as author_name", includes: :comments, joins: :author, order: "posts.id").to_a
1159
1229
  end
1160
- assert_equal 'David', posts[0].author_name
1161
- assert_equal posts(:welcome).comments, assert_no_queries { posts[0].comments}
1230
+ assert_equal "David", posts[0].author_name
1231
+ assert_equal posts(:welcome).comments.sort_by(&:id), assert_no_queries { posts[0].comments.sort_by(&:id) }
1162
1232
  end
1163
1233
 
1164
1234
  def test_eager_loading_with_conditions_on_join_model_preloads
1165
1235
  authors = assert_queries(2) do
1166
- Author.all.merge!(:includes => :author_address, :joins => :comments, :where => "posts.title like 'Welcome%'").to_a
1236
+ Author.all.merge!(includes: :author_address, joins: :comments, where: "posts.title like 'Welcome%'").to_a
1167
1237
  end
1168
1238
  assert_equal authors(:david), authors[0]
1169
1239
  assert_equal author_addresses(:david_address), authors[0].author_address
1170
1240
  end
1171
1241
 
1172
1242
  def test_preload_belongs_to_uses_exclusive_scope
1173
- people = Person.males.merge(:includes => :primary_contact).to_a
1174
- assert_not_equal people.length, 0
1243
+ people = Person.males.includes(:primary_contact).to_a
1244
+ assert_equal 2, people.length
1175
1245
  people.each do |person|
1176
- assert_no_queries {assert_not_nil person.primary_contact}
1246
+ assert_no_queries { assert_not_nil person.primary_contact }
1177
1247
  assert_equal Person.find(person.id).primary_contact, person.primary_contact
1178
1248
  end
1179
1249
  end
1180
1250
 
1181
1251
  def test_preload_has_many_uses_exclusive_scope
1182
1252
  people = Person.males.includes(:agents).to_a
1253
+ assert_equal 2, people.length
1183
1254
  people.each do |person|
1184
- assert_equal Person.find(person.id).agents, person.agents
1255
+ assert_equal Person.find(person.id).agents.sort_by(&:id), person.agents.sort_by(&:id)
1185
1256
  end
1186
1257
  end
1187
1258
 
1188
1259
  def test_preload_has_many_using_primary_key
1189
- expected = Firm.first.clients_using_primary_key.to_a
1260
+ expected = Firm.first.clients_using_primary_key.sort_by(&:id)
1190
1261
  firm = Firm.includes(:clients_using_primary_key).first
1191
1262
  assert_no_queries do
1192
- assert_equal expected, firm.clients_using_primary_key
1263
+ assert_equal expected, firm.clients_using_primary_key.sort_by(&:id)
1193
1264
  end
1194
1265
  end
1195
1266
 
1196
1267
  def test_include_has_many_using_primary_key
1197
1268
  expected = Firm.find(1).clients_using_primary_key.sort_by(&:name)
1198
- # Oracle adapter truncates alias to 30 characters
1199
- if current_adapter?(:OracleAdapter)
1200
- firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies'[0,30]+'.name').find(1)
1201
- elsif current_adapter?(:IBM_DBAdapter)
1202
- #firm = Firm.all.merge!(:includes => :clients_using_primary_key).find(1)
1203
- firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name').find(1)
1204
- else
1205
- firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name').find(1)
1206
- end
1269
+ firm = Firm.all.merge!(includes: :clients_using_primary_key, order: "clients_using_primary_keys_companies.name").find(1)
1207
1270
  assert_no_queries do
1208
1271
  assert_equal expected, firm.clients_using_primary_key
1209
1272
  end
@@ -1211,7 +1274,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
1211
1274
 
1212
1275
  def test_preload_has_one_using_primary_key
1213
1276
  expected = accounts(:signals37)
1214
- firm = Firm.all.merge!(:includes => :account_using_primary_key, :order => 'companies.id').first
1277
+ firm = Firm.all.merge!(includes: :account_using_primary_key, order: "companies.id").first
1215
1278
  assert_no_queries do
1216
1279
  assert_equal expected, firm.account_using_primary_key
1217
1280
  end
@@ -1219,35 +1282,37 @@ class EagerAssociationTest < ActiveRecord::TestCase
1219
1282
 
1220
1283
  def test_include_has_one_using_primary_key
1221
1284
  expected = accounts(:signals37)
1222
- firm = Firm.all.merge!(:includes => :account_using_primary_key, :order => 'accounts.id').to_a.detect {|f| f.id == 1}
1285
+ firm = Firm.all.merge!(includes: :account_using_primary_key, order: "accounts.id").to_a.detect { |f| f.id == 1 }
1223
1286
  assert_no_queries do
1224
1287
  assert_equal expected, firm.account_using_primary_key
1225
1288
  end
1226
1289
  end
1227
1290
 
1228
1291
  def test_preloading_empty_belongs_to
1229
- c = Client.create!(:name => 'Foo', :client_of => Company.maximum(:id) + 1)
1292
+ c = Client.create!(name: "Foo", client_of: Company.maximum(:id) + 1)
1230
1293
 
1231
1294
  client = assert_queries(2) { Client.preload(:firm).find(c.id) }
1232
1295
  assert_no_queries { assert_nil client.firm }
1296
+ assert_equal c.client_of, client.client_of
1233
1297
  end
1234
1298
 
1235
1299
  def test_preloading_empty_belongs_to_polymorphic
1236
- t = Tagging.create!(:taggable_type => 'Post', :taggable_id => Post.maximum(:id) + 1, :tag => tags(:general))
1300
+ t = Tagging.create!(taggable_type: "Post", taggable_id: Post.maximum(:id) + 1, tag: tags(:general))
1237
1301
 
1238
1302
  tagging = assert_queries(2) { Tagging.preload(:taggable).find(t.id) }
1239
1303
  assert_no_queries { assert_nil tagging.taggable }
1304
+ assert_equal t.taggable_id, tagging.taggable_id
1240
1305
  end
1241
1306
 
1242
1307
  def test_preloading_through_empty_belongs_to
1243
- c = Client.create!(:name => 'Foo', :client_of => Company.maximum(:id) + 1)
1308
+ c = Client.create!(name: "Foo", client_of: Company.maximum(:id) + 1)
1244
1309
 
1245
1310
  client = assert_queries(2) { Client.preload(:accounts).find(c.id) }
1246
1311
  assert_no_queries { assert client.accounts.empty? }
1247
1312
  end
1248
1313
 
1249
1314
  def test_preloading_has_many_through_with_distinct
1250
- mary = Author.includes(:unique_categorized_posts).where(:id => authors(:mary).id).first
1315
+ mary = Author.includes(:unique_categorized_posts).where(id: authors(:mary).id).first
1251
1316
  assert_equal 1, mary.unique_categorized_posts.length
1252
1317
  assert_equal 1, mary.unique_categorized_post_ids.length
1253
1318
  end
@@ -1275,31 +1340,31 @@ class EagerAssociationTest < ActiveRecord::TestCase
1275
1340
  groucho = members(:groucho)
1276
1341
 
1277
1342
  sponsor = assert_queries(2) {
1278
- Sponsor.includes(:thing).where(:id => sponsor.id).first
1343
+ Sponsor.includes(:thing).where(id: sponsor.id).first
1279
1344
  }
1280
1345
  assert_no_queries { assert_equal groucho, sponsor.thing }
1281
1346
  end
1282
1347
 
1283
1348
  def test_joins_with_includes_should_preload_via_joins
1284
- post = assert_queries(1) { Post.includes(:comments).joins(:comments).order('posts.id desc').to_a.first }
1349
+ post = assert_queries(1) { Post.includes(:comments).joins(:comments).order("posts.id desc").to_a.first }
1285
1350
 
1286
- assert_queries(0) do
1351
+ assert_no_queries do
1287
1352
  assert_not_equal 0, post.comments.to_a.count
1288
1353
  end
1289
1354
  end
1290
1355
 
1291
1356
  def test_join_eager_with_empty_order_should_generate_valid_sql
1292
1357
  assert_nothing_raised do
1293
- Post.includes(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
1358
+ Post.includes(:comments).order("").where(comments: { body: "Thank you for the welcome" }).first
1294
1359
  end
1295
1360
  end
1296
1361
 
1297
1362
  def test_deep_including_through_habtm
1298
1363
  # warm up habtm cache
1299
- posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1364
+ posts = Post.all.merge!(includes: { categories: :categorizations }, order: "posts.id").to_a
1300
1365
  posts[0].categories[0].categorizations.length
1301
1366
 
1302
- posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1367
+ posts = Post.all.merge!(includes: { categories: :categorizations }, order: "posts.id").to_a
1303
1368
  assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.length }
1304
1369
  assert_no_queries { assert_equal 1, posts[0].categories[1].categorizations.length }
1305
1370
  assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.length }
@@ -1315,21 +1380,39 @@ class EagerAssociationTest < ActiveRecord::TestCase
1315
1380
  assert_equal projects.last.mentor.developers.first.contracts, projects.last.developers.last.contracts
1316
1381
  end
1317
1382
 
1383
+ def test_preloading_has_many_through_with_custom_scope
1384
+ project = Project.includes(:developers_named_david_with_hash_conditions).find(projects(:active_record).id)
1385
+ assert_equal [developers(:david)], project.developers_named_david_with_hash_conditions
1386
+ end
1387
+
1318
1388
  test "scoping with a circular preload" do
1319
- assert_equal Comment.find(1), Comment.preload(:post => :comments).scoping { Comment.find(1) }
1389
+ assert_equal Comment.find(1), Comment.preload(post: :comments).scoping { Comment.find(1) }
1320
1390
  end
1321
1391
 
1322
1392
  test "circular preload does not modify unscoped" do
1323
1393
  expected = FirstPost.unscoped.find(2)
1324
- FirstPost.preload(:comments => :first_post).find(1)
1394
+ FirstPost.preload(comments: :first_post).find(1)
1325
1395
  assert_equal expected, FirstPost.unscoped.find(2)
1326
1396
  end
1327
1397
 
1328
- test "preload ignores the scoping" do
1329
- assert_equal(
1330
- Comment.find(1).post,
1331
- Post.where('1 = 0').scoping { Comment.preload(:post).find(1).post }
1332
- )
1398
+ test "belongs_to association ignores the scoping" do
1399
+ post = Comment.find(1).post
1400
+
1401
+ Post.where("1=0").scoping do
1402
+ assert_equal post, Comment.find(1).post
1403
+ assert_equal post, Comment.preload(:post).find(1).post
1404
+ assert_equal post, Comment.eager_load(:post).find(1).post
1405
+ end
1406
+ end
1407
+
1408
+ test "has_many association ignores the scoping" do
1409
+ comments = Post.find(1).comments.to_a
1410
+
1411
+ Comment.where("1=0").scoping do
1412
+ assert_equal comments, Post.find(1).comments
1413
+ assert_equal comments, Post.preload(:comments).find(1).comments
1414
+ assert_equal comments, Post.eager_load(:comments).find(1).comments
1415
+ end
1333
1416
  end
1334
1417
 
1335
1418
  test "deep preload" do
@@ -1353,10 +1436,10 @@ class EagerAssociationTest < ActiveRecord::TestCase
1353
1436
  end
1354
1437
 
1355
1438
  test "works in combination with order(:symbol) and reorder(:symbol)" do
1356
- author = Author.includes(:posts).references(:posts).order(:name).find_by('posts.title IS NOT NULL')
1439
+ author = Author.includes(:posts).references(:posts).order(:name).find_by("posts.title IS NOT NULL")
1357
1440
  assert_equal authors(:bob), author
1358
1441
 
1359
- author = Author.includes(:posts).references(:posts).reorder(:name).find_by('posts.title IS NOT NULL')
1442
+ author = Author.includes(:posts).references(:posts).reorder(:name).find_by("posts.title IS NOT NULL")
1360
1443
  assert_equal authors(:bob), author
1361
1444
  end
1362
1445
 
@@ -1382,6 +1465,8 @@ class EagerAssociationTest < ActiveRecord::TestCase
1382
1465
 
1383
1466
  assert_nothing_raised do
1384
1467
  authors(:david).essays.includes(:writer).any?
1468
+ authors(:david).essays.includes(:writer).exists?
1469
+ authors(:david).essays.includes(:owner).where("name IS NOT NULL").exists?
1385
1470
  end
1386
1471
  end
1387
1472
 
@@ -1396,7 +1481,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
1396
1481
 
1397
1482
  test "including associations with where.not adds implicit references" do
1398
1483
  author = assert_queries(2) {
1399
- Author.includes(:posts).where.not(posts: { title: 'Welcome to the weblog'} ).last
1484
+ Author.includes(:posts).where.not(posts: { title: "Welcome to the weblog" }).last
1400
1485
  }
1401
1486
 
1402
1487
  assert_no_queries {
@@ -1426,11 +1511,29 @@ class EagerAssociationTest < ActiveRecord::TestCase
1426
1511
  assert_match message, error.message
1427
1512
  end
1428
1513
 
1514
+ test "preloading and eager loading of optional instance dependent associations is not supported" do
1515
+ message = "association scope 'posts_mentioning_author' is"
1516
+ error = assert_raises(ArgumentError) do
1517
+ Author.includes(:posts_mentioning_author).to_a
1518
+ end
1519
+ assert_match message, error.message
1520
+
1521
+ error = assert_raises(ArgumentError) do
1522
+ Author.preload(:posts_mentioning_author).to_a
1523
+ end
1524
+ assert_match message, error.message
1525
+
1526
+ error = assert_raises(ArgumentError) do
1527
+ Author.eager_load(:posts_mentioning_author).to_a
1528
+ end
1529
+ assert_match message, error.message
1530
+ end
1531
+
1429
1532
  test "preload with invalid argument" do
1430
1533
  exception = assert_raises(ArgumentError) do
1431
1534
  Author.preload(10).to_a
1432
1535
  end
1433
- assert_equal('10 was not recognized for preload', exception.message)
1536
+ assert_equal("10 was not recognized for preload", exception.message)
1434
1537
  end
1435
1538
 
1436
1539
  test "associations with extensions are not instance dependent" do
@@ -1449,66 +1552,107 @@ class EagerAssociationTest < ActiveRecord::TestCase
1449
1552
  test "preloading readonly association" do
1450
1553
  # has-one
1451
1554
  firm = Firm.where(id: "1").preload(:readonly_account).first!
1452
- assert firm.readonly_account.readonly?
1555
+ assert_predicate firm.readonly_account, :readonly?
1453
1556
 
1454
1557
  # has_and_belongs_to_many
1455
1558
  project = Project.where(id: "2").preload(:readonly_developers).first!
1456
- assert project.readonly_developers.first.readonly?
1559
+ assert_predicate project.readonly_developers.first, :readonly?
1457
1560
 
1458
1561
  # has-many :through
1459
1562
  david = Author.where(id: "1").preload(:readonly_comments).first!
1460
- assert david.readonly_comments.first.readonly?
1563
+ assert_predicate david.readonly_comments.first, :readonly?
1461
1564
  end
1462
1565
 
1463
1566
  test "eager-loading non-readonly association" do
1464
1567
  # has_one
1465
1568
  firm = Firm.where(id: "1").eager_load(:account).first!
1466
- assert_not firm.account.readonly?
1569
+ assert_not_predicate firm.account, :readonly?
1467
1570
 
1468
1571
  # has_and_belongs_to_many
1469
1572
  project = Project.where(id: "2").eager_load(:developers).first!
1470
- assert_not project.developers.first.readonly?
1573
+ assert_not_predicate project.developers.first, :readonly?
1471
1574
 
1472
1575
  # has_many :through
1473
1576
  david = Author.where(id: "1").eager_load(:comments).first!
1474
- assert_not david.comments.first.readonly?
1577
+ assert_not_predicate david.comments.first, :readonly?
1475
1578
 
1476
1579
  # belongs_to
1477
1580
  post = Post.where(id: "1").eager_load(:author).first!
1478
- assert_not post.author.readonly?
1581
+ assert_not_predicate post.author, :readonly?
1479
1582
  end
1480
1583
 
1481
1584
  test "eager-loading readonly association" do
1482
1585
  # has-one
1483
1586
  firm = Firm.where(id: "1").eager_load(:readonly_account).first!
1484
- assert firm.readonly_account.readonly?
1587
+ assert_predicate firm.readonly_account, :readonly?
1485
1588
 
1486
1589
  # has_and_belongs_to_many
1487
1590
  project = Project.where(id: "2").eager_load(:readonly_developers).first!
1488
- assert project.readonly_developers.first.readonly?
1591
+ assert_predicate project.readonly_developers.first, :readonly?
1489
1592
 
1490
1593
  # has-many :through
1491
1594
  david = Author.where(id: "1").eager_load(:readonly_comments).first!
1492
- assert david.readonly_comments.first.readonly?
1595
+ assert_predicate david.readonly_comments.first, :readonly?
1493
1596
 
1494
1597
  # belongs_to
1495
1598
  post = Post.where(id: "1").eager_load(:readonly_author).first!
1496
- assert post.readonly_author.readonly?
1599
+ assert_predicate post.readonly_author, :readonly?
1497
1600
  end
1498
1601
 
1499
1602
  test "preloading a polymorphic association with references to the associated table" do
1500
- post = Post.includes(:tags).references(:tags).where('tags.name = ?', 'General').first
1603
+ post = Post.includes(:tags).references(:tags).where("tags.name = ?", "General").first
1501
1604
  assert_equal posts(:welcome), post
1502
1605
  end
1503
1606
 
1504
1607
  test "eager-loading a polymorphic association with references to the associated table" do
1505
- post = Post.eager_load(:tags).where('tags.name = ?', 'General').first
1608
+ post = Post.eager_load(:tags).where("tags.name = ?", "General").first
1506
1609
  assert_equal posts(:welcome), post
1507
1610
  end
1508
1611
 
1612
+ test "eager-loading with a polymorphic association won't work consistently" do
1613
+ assert_raise(ActiveRecord::EagerLoadPolymorphicError) { authors(:david).essays.eager_load(:writer).to_a }
1614
+ assert_raise(ActiveRecord::EagerLoadPolymorphicError) { authors(:david).essays.eager_load(:writer).count }
1615
+ assert_raise(ActiveRecord::EagerLoadPolymorphicError) { authors(:david).essays.eager_load(:writer).exists? }
1616
+ end
1617
+
1509
1618
  # CollectionProxy#reader is expensive, so the preloader avoids calling it.
1510
1619
  test "preloading has_many_through association avoids calling association.reader" do
1511
- ActiveRecord::Associations::HasManyAssociation.any_instance.expects(:reader).never
1512
- Author.preload(:readonly_comments).first!
1620
+ assert_not_called_on_instance_of(ActiveRecord::Associations::HasManyAssociation, :reader) do
1621
+ Author.preload(:readonly_comments).first!
1622
+ end
1623
+ end
1624
+
1625
+ test "preloading through a polymorphic association doesn't require the association to exist" do
1626
+ sponsors = []
1627
+ assert_queries 5 do
1628
+ sponsors = Sponsor.where(sponsorable_id: 1).preload(sponsorable: [:post, :membership]).to_a
1629
+ end
1630
+ # check the preload worked
1631
+ assert_queries 0 do
1632
+ sponsors.map(&:sponsorable).map { |s| s.respond_to?(:posts) ? s.post.author : s.membership }
1633
+ end
1513
1634
  end
1635
+
1636
+ test "preloading a regular association through a polymorphic association doesn't require the association to exist on all types" do
1637
+ sponsors = []
1638
+ assert_queries 6 do
1639
+ sponsors = Sponsor.where(sponsorable_id: 1).preload(sponsorable: [{ post: :first_comment }, :membership]).to_a
1640
+ end
1641
+ # check the preload worked
1642
+ assert_queries 0 do
1643
+ sponsors.map(&:sponsorable).map { |s| s.respond_to?(:posts) ? s.post.author : s.membership }
1644
+ end
1645
+ end
1646
+
1647
+ test "preloading a regular association with a typo through a polymorphic association still raises" do
1648
+ # this test contains an intentional typo of first -> fist
1649
+ assert_raises(ActiveRecord::AssociationNotFoundError) do
1650
+ Sponsor.where(sponsorable_id: 1).preload(sponsorable: [{ post: :fist_comment }, :membership]).to_a
1651
+ end
1652
+ end
1653
+
1654
+ private
1655
+ def find_all_ordered(klass, include = nil)
1656
+ klass.order("#{klass.table_name}.#{klass.primary_key}").includes(include).to_a
1657
+ end
1514
1658
  end