ibm_db 5.6.1 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Makefile +13 -9
  3. data/ext/extconf.rb +176 -110
  4. data/ext/ibm_db.c +60 -0
  5. data/ext/ibm_db.o +0 -0
  6. data/ext/ibm_db.so +0 -0
  7. data/ext/mkmf.log +6 -6
  8. data/ext/ruby_ibm_db_cli.c +14 -10
  9. data/ext/ruby_ibm_db_cli.h +4 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/IBM_DB.rb +2 -2
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
  13. data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
  14. data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
  15. data/test/activejob/destroy_association_async_job_test.rb +62 -0
  16. data/test/activejob/destroy_association_async_test.rb +147 -11
  17. data/test/activejob/job_runtime_test.rb +41 -0
  18. data/test/activejob/unloadable_base_job.rb +3 -0
  19. data/test/cases/active_record_schema_test.rb +196 -0
  20. data/test/cases/active_record_test.rb +21 -0
  21. data/test/cases/adapter_prevent_writes_test.rb +26 -202
  22. data/test/cases/adapter_test.rb +592 -82
  23. data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
  24. data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
  25. data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
  26. data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
  27. data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
  28. data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
  29. data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
  30. data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
  31. data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
  32. data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
  33. data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
  34. data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
  35. data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
  36. data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
  38. data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
  39. data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
  40. data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
  41. data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
  42. data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
  43. data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
  44. data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
  45. data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
  46. data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
  47. data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
  48. data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
  49. data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
  51. data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
  52. data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
  53. data/test/cases/adapters/postgresql/array_test.rb +6 -6
  54. data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
  55. data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
  56. data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
  57. data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
  58. data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
  59. data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
  60. data/test/cases/adapters/postgresql/citext_test.rb +7 -1
  61. data/test/cases/adapters/postgresql/collation_test.rb +1 -1
  62. data/test/cases/adapters/postgresql/composite_test.rb +1 -1
  63. data/test/cases/adapters/postgresql/connection_test.rb +43 -36
  64. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
  65. data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
  66. data/test/cases/adapters/postgresql/date_test.rb +2 -2
  67. data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
  69. data/test/cases/adapters/postgresql/domain_test.rb +1 -1
  70. data/test/cases/adapters/postgresql/enum_test.rb +208 -8
  71. data/test/cases/adapters/postgresql/explain_test.rb +25 -6
  72. data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
  73. data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
  74. data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
  75. data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
  76. data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
  77. data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
  78. data/test/cases/adapters/postgresql/integer_test.rb +1 -1
  79. data/test/cases/adapters/postgresql/interval_test.rb +9 -17
  80. data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
  81. data/test/cases/adapters/postgresql/json_test.rb +5 -0
  82. data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
  83. data/test/cases/adapters/postgresql/money_test.rb +17 -9
  84. data/test/cases/adapters/postgresql/network_test.rb +13 -1
  85. data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
  86. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
  87. data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
  88. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
  89. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
  90. data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
  91. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
  92. data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
  93. data/test/cases/adapters/postgresql/range_test.rb +185 -21
  94. data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
  95. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
  96. data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
  97. data/test/cases/adapters/postgresql/schema_test.rb +270 -20
  98. data/test/cases/adapters/postgresql/serial_test.rb +5 -5
  99. data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
  100. data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
  101. data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
  102. data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
  103. data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
  104. data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
  105. data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
  106. data/test/cases/adapters/postgresql/xml_test.rb +1 -1
  107. data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
  108. data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
  109. data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
  110. data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
  111. data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
  112. data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
  113. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
  114. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
  115. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
  116. data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
  117. data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
  118. data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
  119. data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
  120. data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
  121. data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
  122. data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
  123. data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
  124. data/test/cases/aggregations_test.rb +16 -0
  125. data/test/cases/annotate_test.rb +14 -12
  126. data/test/cases/arel/attributes/attribute_test.rb +86 -47
  127. data/test/cases/arel/collectors/bind_test.rb +1 -1
  128. data/test/cases/arel/collectors/composite_test.rb +11 -1
  129. data/test/cases/arel/collectors/sql_string_test.rb +1 -1
  130. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
  131. data/test/cases/arel/delete_manager_test.rb +0 -6
  132. data/test/cases/arel/factory_methods_test.rb +45 -0
  133. data/test/cases/arel/insert_manager_test.rb +1 -7
  134. data/test/cases/arel/nodes/as_test.rb +12 -0
  135. data/test/cases/arel/nodes/ascending_test.rb +1 -1
  136. data/test/cases/arel/nodes/bin_test.rb +1 -1
  137. data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
  138. data/test/cases/arel/nodes/cte_test.rb +46 -0
  139. data/test/cases/arel/nodes/descending_test.rb +1 -1
  140. data/test/cases/arel/nodes/equality_test.rb +3 -3
  141. data/test/cases/arel/nodes/filter_test.rb +37 -0
  142. data/test/cases/arel/nodes/fragments_test.rb +38 -0
  143. data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
  144. data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
  145. data/test/cases/arel/nodes/node_test.rb +1 -1
  146. data/test/cases/arel/nodes/or_test.rb +2 -2
  147. data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
  148. data/test/cases/arel/nodes/table_alias_test.rb +12 -0
  149. data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
  150. data/test/cases/arel/nodes/update_statement_test.rb +4 -0
  151. data/test/cases/arel/nodes_test.rb +3 -2
  152. data/test/cases/arel/select_manager_test.rb +12 -12
  153. data/test/cases/arel/support/fake_record.rb +22 -17
  154. data/test/cases/arel/table_test.rb +15 -25
  155. data/test/cases/arel/update_manager_test.rb +51 -6
  156. data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
  157. data/test/cases/arel/visitors/dot_test.rb +177 -2
  158. data/test/cases/arel/visitors/mysql_test.rb +49 -1
  159. data/test/cases/arel/visitors/postgres_test.rb +1 -31
  160. data/test/cases/arel/visitors/sqlite_test.rb +1 -1
  161. data/test/cases/arel/visitors/to_sql_test.rb +330 -20
  162. data/test/cases/assertions/query_assertions_test.rb +136 -0
  163. data/test/cases/associations/belongs_to_associations_test.rb +502 -41
  164. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
  165. data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
  166. data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
  167. data/test/cases/associations/eager_singularization_test.rb +1 -1
  168. data/test/cases/associations/eager_test.rb +255 -93
  169. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
  170. data/test/cases/associations/has_many_associations_test.rb +282 -72
  171. data/test/cases/associations/has_many_through_associations_test.rb +172 -45
  172. data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
  173. data/test/cases/associations/has_one_associations_test.rb +160 -29
  174. data/test/cases/associations/has_one_through_associations_test.rb +64 -15
  175. data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
  176. data/test/cases/associations/inner_join_association_test.rb +36 -6
  177. data/test/cases/associations/inverse_associations_test.rb +177 -40
  178. data/test/cases/associations/join_model_test.rb +17 -12
  179. data/test/cases/associations/left_outer_join_association_test.rb +14 -3
  180. data/test/cases/associations/nested_error_test.rb +116 -0
  181. data/test/cases/associations/nested_through_associations_test.rb +54 -19
  182. data/test/cases/associations/required_test.rb +1 -1
  183. data/test/cases/associations_test.rb +1278 -21
  184. data/test/cases/asynchronous_queries_test.rb +310 -0
  185. data/test/cases/attribute_methods/read_test.rb +6 -0
  186. data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
  187. data/test/cases/attribute_methods_test.rb +565 -46
  188. data/test/cases/attributes_test.rb +42 -1
  189. data/test/cases/autosave_association_test.rb +645 -92
  190. data/test/cases/base_prevent_writes_test.rb +28 -159
  191. data/test/cases/base_test.rb +434 -209
  192. data/test/cases/batches_test.rb +441 -57
  193. data/test/cases/binary_test.rb +31 -0
  194. data/test/cases/bind_parameter_test.rb +107 -16
  195. data/test/cases/cache_key_test.rb +7 -7
  196. data/test/cases/calculations_test.rb +541 -110
  197. data/test/cases/callbacks_test.rb +0 -1
  198. data/test/cases/clone_test.rb +5 -4
  199. data/test/cases/coders/yaml_column_test.rb +97 -2
  200. data/test/cases/collection_cache_key_test.rb +24 -16
  201. data/test/cases/column_alias_test.rb +2 -8
  202. data/test/cases/column_definition_test.rb +12 -3
  203. data/test/cases/comment_test.rb +23 -26
  204. data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
  205. data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
  206. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
  207. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
  208. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
  209. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
  210. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
  211. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
  212. data/test/cases/connection_adapters/registration_test.rb +98 -0
  213. data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
  214. data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
  215. data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
  216. data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
  217. data/test/cases/connection_handling_test.rb +210 -0
  218. data/test/cases/connection_management_test.rb +44 -7
  219. data/test/cases/connection_pool_test.rb +466 -99
  220. data/test/cases/core_test.rb +167 -9
  221. data/test/cases/counter_cache_test.rb +129 -2
  222. data/test/cases/custom_locking_test.rb +3 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +149 -13
  224. data/test/cases/database_configurations/resolver_test.rb +14 -10
  225. data/test/cases/database_configurations/url_config_test.rb +53 -0
  226. data/test/cases/database_configurations_test.rb +86 -43
  227. data/test/cases/database_selector_test.rb +30 -8
  228. data/test/cases/database_statements_test.rb +10 -14
  229. data/test/cases/date_time_precision_test.rb +141 -11
  230. data/test/cases/date_time_test.rb +19 -1
  231. data/test/cases/defaults_test.rb +107 -41
  232. data/test/cases/delegated_type_test.rb +69 -9
  233. data/test/cases/dirty_test.rb +82 -25
  234. data/test/cases/disconnected_test.rb +10 -9
  235. data/test/cases/dup_test.rb +26 -6
  236. data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
  237. data/test/cases/encryption/cipher_test.rb +65 -0
  238. data/test/cases/encryption/concurrency_test.rb +27 -0
  239. data/test/cases/encryption/config_test.rb +21 -0
  240. data/test/cases/encryption/configurable_test.rb +93 -0
  241. data/test/cases/encryption/contexts_test.rb +105 -0
  242. data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
  243. data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
  244. data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
  245. data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
  246. data/test/cases/encryption/encryptable_record_test.rb +470 -0
  247. data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
  248. data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
  249. data/test/cases/encryption/encryption_schemes_test.rb +240 -0
  250. data/test/cases/encryption/encryptor_test.rb +113 -0
  251. data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
  252. data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
  253. data/test/cases/encryption/helper.rb +152 -0
  254. data/test/cases/encryption/key_generator_test.rb +55 -0
  255. data/test/cases/encryption/key_provider_test.rb +57 -0
  256. data/test/cases/encryption/key_test.rb +17 -0
  257. data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
  258. data/test/cases/encryption/message_serializer_test.rb +82 -0
  259. data/test/cases/encryption/message_test.rb +43 -0
  260. data/test/cases/encryption/null_encryptor_test.rb +21 -0
  261. data/test/cases/encryption/properties_test.rb +69 -0
  262. data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
  263. data/test/cases/encryption/scheme_test.rb +58 -0
  264. data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
  265. data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
  266. data/test/cases/enum_test.rb +374 -72
  267. data/test/cases/errors_test.rb +7 -4
  268. data/test/cases/excluding_test.rb +116 -0
  269. data/test/cases/explain_subscriber_test.rb +6 -1
  270. data/test/cases/explain_test.rb +119 -10
  271. data/test/cases/filter_attributes_test.rb +7 -14
  272. data/test/cases/finder_respond_to_test.rb +3 -3
  273. data/test/cases/finder_test.rb +357 -72
  274. data/test/cases/fixture_set/file_test.rb +9 -0
  275. data/test/cases/fixtures_test.rb +426 -190
  276. data/test/cases/helper.rb +66 -192
  277. data/test/cases/hot_compatibility_test.rb +10 -10
  278. data/test/cases/inheritance_test.rb +51 -61
  279. data/test/cases/inherited_test.rb +40 -0
  280. data/test/cases/insert_all_test.rb +419 -9
  281. data/test/cases/instrumentation_test.rb +202 -30
  282. data/test/cases/integration_test.rb +25 -7
  283. data/test/cases/invalid_connection_test.rb +5 -5
  284. data/test/cases/invertible_migration_test.rb +108 -24
  285. data/test/cases/json_attribute_test.rb +1 -0
  286. data/test/cases/json_serialization_test.rb +5 -5
  287. data/test/cases/json_shared_test_cases.rb +5 -9
  288. data/test/cases/locking_test.rb +67 -31
  289. data/test/cases/log_subscriber_test.rb +17 -15
  290. data/test/cases/marshal_serialization_test.rb +78 -5
  291. data/test/cases/message_pack_test.rb +91 -0
  292. data/test/cases/migration/change_schema_test.rb +77 -46
  293. data/test/cases/migration/change_table_test.rb +129 -114
  294. data/test/cases/migration/check_constraint_test.rb +192 -10
  295. data/test/cases/migration/column_attributes_test.rb +4 -9
  296. data/test/cases/migration/column_positioning_test.rb +2 -2
  297. data/test/cases/migration/columns_test.rb +118 -4
  298. data/test/cases/migration/command_recorder_test.rb +181 -14
  299. data/test/cases/migration/compatibility_test.rb +883 -196
  300. data/test/cases/migration/create_join_table_test.rb +8 -1
  301. data/test/cases/migration/exclusion_constraint_test.rb +192 -0
  302. data/test/cases/migration/foreign_key_test.rb +356 -14
  303. data/test/cases/migration/helper.rb +4 -1
  304. data/test/cases/migration/index_test.rb +67 -2
  305. data/test/cases/migration/invalid_options_test.rb +129 -0
  306. data/test/cases/migration/logger_test.rb +7 -4
  307. data/test/cases/migration/pending_migrations_test.rb +103 -60
  308. data/test/cases/migration/references_foreign_key_test.rb +73 -4
  309. data/test/cases/migration/references_index_test.rb +25 -27
  310. data/test/cases/migration/references_statements_test.rb +27 -3
  311. data/test/cases/migration/rename_table_test.rb +39 -54
  312. data/test/cases/migration/schema_definitions_test.rb +109 -0
  313. data/test/cases/migration/unique_constraint_test.rb +248 -0
  314. data/test/cases/migration_test.rb +677 -220
  315. data/test/cases/migrator_test.rb +102 -75
  316. data/test/cases/multi_db_migrator_test.rb +55 -34
  317. data/test/cases/multiparameter_attributes_test.rb +26 -29
  318. data/test/cases/multiple_db_test.rb +42 -19
  319. data/test/cases/nested_attributes_test.rb +124 -6
  320. data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
  321. data/test/cases/normalized_attribute_test.rb +117 -0
  322. data/test/cases/null_relation_test.rb +35 -2
  323. data/test/cases/persistence/reload_association_cache_test.rb +20 -0
  324. data/test/cases/persistence_test.rb +629 -22
  325. data/test/cases/pooled_connections_test.rb +57 -56
  326. data/test/cases/prepared_statement_status_test.rb +8 -3
  327. data/test/cases/primary_class_test.rb +134 -0
  328. data/test/cases/primary_keys_test.rb +171 -55
  329. data/test/cases/query_cache_test.rb +558 -263
  330. data/test/cases/query_logs_test.rb +293 -0
  331. data/test/cases/quoting_test.rb +39 -72
  332. data/test/cases/readonly_test.rb +50 -12
  333. data/test/cases/reaper_test.rb +22 -6
  334. data/test/cases/reflection_test.rb +207 -9
  335. data/test/cases/relation/and_test.rb +43 -0
  336. data/test/cases/relation/delegation_test.rb +32 -5
  337. data/test/cases/relation/delete_all_test.rb +27 -6
  338. data/test/cases/relation/field_ordered_values_test.rb +128 -0
  339. data/test/cases/relation/load_async_test.rb +650 -0
  340. data/test/cases/relation/merging_test.rb +80 -109
  341. data/test/cases/relation/mutation_test.rb +12 -7
  342. data/test/cases/relation/or_test.rb +11 -8
  343. data/test/cases/relation/order_test.rb +90 -0
  344. data/test/cases/relation/predicate_builder_test.rb +21 -6
  345. data/test/cases/relation/select_test.rb +162 -3
  346. data/test/cases/relation/structural_compatibility_test.rb +38 -0
  347. data/test/cases/relation/update_all_test.rb +81 -27
  348. data/test/cases/relation/where_chain_test.rb +190 -3
  349. data/test/cases/relation/where_clause_test.rb +43 -1
  350. data/test/cases/relation/where_test.rb +95 -7
  351. data/test/cases/relation/with_test.rb +165 -0
  352. data/test/cases/relation_test.rb +42 -37
  353. data/test/cases/relations_test.rb +436 -138
  354. data/test/cases/reload_models_test.rb +18 -14
  355. data/test/cases/reserved_word_test.rb +2 -1
  356. data/test/cases/result_test.rb +14 -22
  357. data/test/cases/sanitize_test.rb +89 -27
  358. data/test/cases/schema_dumper_test.rb +535 -62
  359. data/test/cases/scoping/default_scoping_test.rb +219 -35
  360. data/test/cases/scoping/named_scoping_test.rb +25 -46
  361. data/test/cases/scoping/relation_scoping_test.rb +112 -4
  362. data/test/cases/secure_password_test.rb +108 -0
  363. data/test/cases/secure_token_test.rb +72 -0
  364. data/test/cases/serialization_test.rb +1 -1
  365. data/test/cases/serialized_attribute_test.rb +305 -60
  366. data/test/cases/shard_keys_test.rb +125 -0
  367. data/test/cases/shard_selector_test.rb +45 -0
  368. data/test/cases/signed_id_test.rb +57 -5
  369. data/test/cases/statement_cache_test.rb +31 -30
  370. data/test/cases/statement_invalid_test.rb +8 -4
  371. data/test/cases/store_test.rb +73 -9
  372. data/test/cases/strict_loading_test.rb +327 -13
  373. data/test/cases/table_metadata_test.rb +16 -0
  374. data/test/cases/tasks/database_tasks_test.rb +517 -244
  375. data/test/cases/test_case.rb +254 -60
  376. data/test/cases/test_case_test.rb +69 -0
  377. data/test/cases/test_databases_test.rb +7 -3
  378. data/test/cases/test_fixtures_test.rb +19 -40
  379. data/test/cases/time_precision_test.rb +17 -5
  380. data/test/cases/timestamp_test.rb +124 -16
  381. data/test/cases/token_for_test.rb +165 -0
  382. data/test/cases/touch_later_test.rb +43 -1
  383. data/test/cases/transaction_callbacks_test.rb +325 -8
  384. data/test/cases/transaction_instrumentation_test.rb +453 -0
  385. data/test/cases/transaction_isolation_test.rb +12 -8
  386. data/test/cases/transactions_test.rb +629 -112
  387. data/test/cases/type/date_time_test.rb +7 -1
  388. data/test/cases/type/time_test.rb +9 -0
  389. data/test/cases/type/type_map_test.rb +108 -73
  390. data/test/cases/type/unsigned_integer_test.rb +12 -0
  391. data/test/cases/type_caster/connection_test.rb +19 -0
  392. data/test/cases/type_test.rb +1 -1
  393. data/test/cases/unconnected_test.rb +7 -7
  394. data/test/cases/unsafe_raw_sql_test.rb +39 -8
  395. data/test/cases/validations/absence_validation_test.rb +1 -1
  396. data/test/cases/validations/association_validation_test.rb +25 -3
  397. data/test/cases/validations/numericality_validation_test.rb +3 -9
  398. data/test/cases/validations/presence_validation_test.rb +1 -1
  399. data/test/cases/validations/uniqueness_validation_test.rb +280 -40
  400. data/test/cases/validations_test.rb +2 -2
  401. data/test/cases/view_test.rb +33 -22
  402. data/test/cases/yaml_serialization_test.rb +23 -17
  403. data/test/config.example.yml +58 -56
  404. data/test/config.rb +1 -0
  405. data/test/fixtures/1_need_quoting.yml +2 -0
  406. data/test/fixtures/accounts.yml +5 -0
  407. data/test/fixtures/aircrafts.yml +7 -0
  408. data/test/fixtures/book_identifiers.yml +11 -0
  409. data/test/fixtures/books.yml +5 -4
  410. data/test/fixtures/cake_designers.yml +5 -0
  411. data/test/fixtures/cars.yml +6 -0
  412. data/test/fixtures/chefs.yml +5 -0
  413. data/test/fixtures/clothing_items.yml +23 -0
  414. data/test/fixtures/clubs.yml +1 -1
  415. data/test/fixtures/comments.yml +2 -1
  416. data/test/fixtures/cpk_authors.yml +8 -0
  417. data/test/fixtures/cpk_books.yml +21 -0
  418. data/test/fixtures/cpk_order_agreements.yml +13 -0
  419. data/test/fixtures/cpk_order_tags.yml +15 -0
  420. data/test/fixtures/cpk_orders.yml +11 -0
  421. data/test/fixtures/cpk_posts.yml +12 -0
  422. data/test/fixtures/cpk_reviews.yml +13 -0
  423. data/test/fixtures/cpk_tags.yml +11 -0
  424. data/test/fixtures/drink_designers.yml +5 -0
  425. data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
  426. data/test/fixtures/encrypted_books.yml +4 -0
  427. data/test/fixtures/fk_object_to_point_to.yml +2 -0
  428. data/test/fixtures/memberships.yml +15 -15
  429. data/test/fixtures/paragraphs.yml +5 -0
  430. data/test/fixtures/parrots.yml +4 -0
  431. data/test/fixtures/people.yml +2 -0
  432. data/test/fixtures/pirates.yml +2 -2
  433. data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
  434. data/test/fixtures/references.yml +3 -3
  435. data/test/fixtures/sharded_blog_posts.yml +14 -0
  436. data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
  437. data/test/fixtures/sharded_blogs.yml +8 -0
  438. data/test/fixtures/sharded_comments.yml +22 -0
  439. data/test/fixtures/sharded_tags.yml +34 -0
  440. data/test/fixtures/sponsors.yml +2 -2
  441. data/test/fixtures/topics.yml +1 -0
  442. data/test/fixtures/treasures.yml +4 -0
  443. data/test/fixtures/virtual_columns.yml +5 -0
  444. data/test/fixtures/warehouse_things.yml +1 -1
  445. data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
  446. data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
  447. data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
  448. data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
  449. data/test/migrations/scope/1_unscoped.rb +7 -0
  450. data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
  451. data/test/models/admin/user.rb +2 -0
  452. data/test/models/admin/user_json.rb +48 -0
  453. data/test/models/attachment.rb +7 -0
  454. data/test/models/author.rb +70 -3
  455. data/test/models/author_encrypted.rb +16 -0
  456. data/test/models/bird.rb +1 -1
  457. data/test/models/book.rb +18 -11
  458. data/test/models/book_destroy_async.rb +1 -1
  459. data/test/models/book_encrypted.rb +106 -0
  460. data/test/models/book_identifier.rb +5 -0
  461. data/test/models/branch.rb +11 -0
  462. data/test/models/bulb.rb +1 -1
  463. data/test/models/car.rb +8 -1
  464. data/test/models/cat.rb +1 -1
  465. data/test/models/category.rb +3 -1
  466. data/test/models/chat_message.rb +8 -0
  467. data/test/models/chef.rb +52 -0
  468. data/test/models/clothing_item.rb +12 -0
  469. data/test/models/club.rb +4 -1
  470. data/test/models/comment.rb +7 -4
  471. data/test/models/comment_overlapping_counter_cache.rb +15 -0
  472. data/test/models/company.rb +16 -2
  473. data/test/models/computer.rb +1 -0
  474. data/test/models/contact.rb +3 -3
  475. data/test/models/contract.rb +5 -1
  476. data/test/models/cpk/author.rb +9 -0
  477. data/test/models/cpk/book.rb +55 -0
  478. data/test/models/cpk/book_destroy_async.rb +9 -0
  479. data/test/models/cpk/car.rb +9 -0
  480. data/test/models/cpk/car_review.rb +9 -0
  481. data/test/models/cpk/chapter.rb +16 -0
  482. data/test/models/cpk/chapter_destroy_async.rb +10 -0
  483. data/test/models/cpk/comment.rb +9 -0
  484. data/test/models/cpk/order.rb +55 -0
  485. data/test/models/cpk/order_agreement.rb +10 -0
  486. data/test/models/cpk/order_tag.rb +10 -0
  487. data/test/models/cpk/post.rb +10 -0
  488. data/test/models/cpk/posts_tag.rb +10 -0
  489. data/test/models/cpk/review.rb +9 -0
  490. data/test/models/cpk/tag.rb +10 -0
  491. data/test/models/cpk.rb +15 -0
  492. data/test/models/customer.rb +3 -1
  493. data/test/models/destroy_async_parent.rb +1 -1
  494. data/test/models/developer.rb +44 -3
  495. data/test/models/discount.rb +4 -0
  496. data/test/models/drink_designer.rb +1 -0
  497. data/test/models/editor.rb +8 -0
  498. data/test/models/editorship.rb +6 -0
  499. data/test/models/entry.rb +5 -0
  500. data/test/models/essay.rb +6 -1
  501. data/test/models/essay_destroy_async.rb +1 -0
  502. data/test/models/eye.rb +87 -21
  503. data/test/models/face.rb +1 -1
  504. data/test/models/friendship.rb +3 -0
  505. data/test/models/hardback.rb +7 -0
  506. data/test/models/hotel.rb +2 -0
  507. data/test/models/human.rb +2 -2
  508. data/test/models/invoice.rb +2 -1
  509. data/test/models/invokes_an_undefined_method.rb +5 -0
  510. data/test/models/line_item.rb +6 -0
  511. data/test/models/member.rb +9 -4
  512. data/test/models/membership.rb +2 -2
  513. data/test/models/message.rb +2 -1
  514. data/test/models/need_quoting.rb +5 -0
  515. data/test/models/paragraph.rb +5 -0
  516. data/test/models/parrot.rb +6 -3
  517. data/test/models/person.rb +7 -4
  518. data/test/models/pirate.rb +4 -1
  519. data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
  520. data/test/models/post.rb +65 -2
  521. data/test/models/post_encrypted.rb +15 -0
  522. data/test/models/post_with_prefetched_pk.rb +15 -0
  523. data/test/models/project.rb +1 -0
  524. data/test/models/publication.rb +16 -0
  525. data/test/models/raises_argument_error.rb +5 -0
  526. data/test/models/raises_no_method_error.rb +5 -0
  527. data/test/models/recipient.rb +5 -0
  528. data/test/models/reference.rb +1 -1
  529. data/test/models/reply.rb +1 -1
  530. data/test/models/room.rb +3 -0
  531. data/test/models/sharded/blog.rb +12 -0
  532. data/test/models/sharded/blog_post.rb +17 -0
  533. data/test/models/sharded/blog_post_destroy_async.rb +14 -0
  534. data/test/models/sharded/blog_post_tag.rb +11 -0
  535. data/test/models/sharded/blog_post_with_revision.rb +11 -0
  536. data/test/models/sharded/comment.rb +12 -0
  537. data/test/models/sharded/comment_destroy_async.rb +12 -0
  538. data/test/models/sharded/tag.rb +11 -0
  539. data/test/models/sharded.rb +8 -0
  540. data/test/models/ship.rb +1 -1
  541. data/test/models/shipping_line.rb +11 -0
  542. data/test/models/subscriber.rb +1 -0
  543. data/test/models/subscription.rb +3 -1
  544. data/test/models/too_long_table_name.rb +5 -0
  545. data/test/models/topic.rb +3 -1
  546. data/test/models/traffic_light.rb +2 -2
  547. data/test/models/traffic_light_encrypted.rb +21 -0
  548. data/test/models/translation.rb +9 -0
  549. data/test/models/treasure.rb +1 -1
  550. data/test/models/tyre.rb +1 -1
  551. data/test/models/user.rb +16 -0
  552. data/test/models/user_with_invalid_relation.rb +28 -0
  553. data/test/models/uuid_comment.rb +5 -0
  554. data/test/models/uuid_entry.rb +5 -0
  555. data/test/models/uuid_message.rb +5 -0
  556. data/test/models/zine.rb +2 -1
  557. data/test/schema/mysql2_specific_schema.rb +26 -12
  558. data/test/schema/postgresql_specific_schema.rb +121 -13
  559. data/test/schema/schema.rb +361 -103
  560. data/test/schema/sqlite_specific_schema.rb +17 -6
  561. data/test/schema/trilogy_specific_schema.rb +96 -0
  562. data/test/support/adapter_helper.rb +104 -0
  563. data/test/support/async_helper.rb +15 -0
  564. data/test/support/config.rb +1 -1
  565. data/test/support/connection.rb +14 -2
  566. data/test/support/ddl_helper.rb +1 -1
  567. data/test/support/fake_adapter.rb +42 -0
  568. data/test/support/load_schema_helper.rb +22 -0
  569. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
  570. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
  571. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
  572. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
  573. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
  574. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
  575. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
  576. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
  577. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
  578. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
  579. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
  580. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
  581. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
  582. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
  583. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
  584. data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
  585. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
  586. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
  587. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
  588. data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
  589. data/test/support/schema_dumping_helper.rb +15 -9
  590. data/test/support/tools.rb +37 -0
  591. data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
  592. metadata +247 -15
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cases/helper"
4
+ require "models/attachment"
4
5
  require "models/developer"
5
6
  require "models/project"
6
7
  require "models/company"
@@ -27,16 +28,23 @@ require "models/treasure"
27
28
  require "models/parrot"
28
29
  require "models/book"
29
30
  require "models/citation"
31
+ require "models/tree"
32
+ require "models/node"
33
+ require "models/club"
34
+ require "models/cpk"
35
+ require "models/sharded/blog"
36
+ require "models/sharded/blog_post"
37
+ require "models/sharded/comment"
30
38
 
31
39
  class BelongsToAssociationsTest < ActiveRecord::TestCase
32
40
  fixtures :accounts, :companies, :developers, :projects, :topics,
33
41
  :developers_projects, :computers, :authors, :author_addresses,
34
- :essays, :posts, :tags, :taggings, :comments, :sponsors, :members
42
+ :essays, :posts, :tags, :taggings, :comments, :sponsors, :members, :nodes, :cpk_books
35
43
 
36
44
  def test_belongs_to
37
45
  client = Client.find(3)
38
46
  first_firm = companies(:first_firm)
39
- assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
47
+ assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
40
48
  assert_equal first_firm, client.firm
41
49
  assert_equal first_firm.name, client.firm.name
42
50
  end
@@ -59,6 +67,12 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
59
67
  assert_empty Comment.where(author: [])
60
68
  end
61
69
 
70
+ def test_where_on_polymorphic_association_with_cpk
71
+ post = Cpk::Post.create!(title: "Welcome", author: "Mary")
72
+ post.comments << Cpk::Comment.create!
73
+ assert_equal 1, Cpk::Comment.where(commentable: post).count
74
+ end
75
+
62
76
  def test_assigning_belongs_to_on_destroyed_object
63
77
  client = Client.create!(name: "Client")
64
78
  client.destroy!
@@ -90,16 +104,12 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
90
104
 
91
105
  def test_belongs_to_with_primary_key_joins_on_correct_column
92
106
  sql = Client.joins(:firm_with_primary_key).to_sql
93
- if current_adapter?(:Mysql2Adapter)
107
+ if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
94
108
  assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
95
109
  assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
96
- elsif current_adapter?(:OracleAdapter)
97
- # on Oracle aliases are truncated to 30 characters and are quoted in uppercase
98
- assert_no_match(/"firm_with_primary_keys_compani"\."id"/i, sql)
99
- assert_match(/"firm_with_primary_keys_compani"\."name"/i, sql)
100
110
  else
101
- assert_no_match(/firm_with_primary_keys_companies\.id/, sql)
102
- assert_match(/firm_with_primary_keys_companies\.name/, sql)
111
+ assert_no_match(/"?firm_with_primary_keys_companies"?\."?id"?/, sql)
112
+ assert_match(/"?firm_with_primary_keys_companies"?\."?name"?/, sql)
103
113
  end
104
114
  end
105
115
 
@@ -242,9 +252,9 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
242
252
  assert_equal 0, counter
243
253
  comment = comments.first
244
254
  assert_equal 0, counter
245
- sql = capture_sql { comment.post }
255
+ queries = capture_sql_and_binds { comment.post }
246
256
  comment.reload
247
- assert_not_equal sql, capture_sql { comment.post }
257
+ assert_not_equal queries, capture_sql_and_binds { comment.post }
248
258
  end
249
259
 
250
260
  def test_proxy_assignment
@@ -260,7 +270,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
260
270
  def test_raises_type_mismatch_with_namespaced_class
261
271
  assert_nil defined?(Region), "This test requires that there is no top-level Region class"
262
272
 
263
- ActiveRecord::Base.connection.instance_eval do
273
+ ActiveRecord::Base.lease_connection.instance_eval do
264
274
  create_table(:admin_regions, force: true) { |t| t.string :name }
265
275
  add_column :admin_users, :region_id, :integer
266
276
  end
@@ -275,7 +285,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
275
285
  Admin.send :remove_const, "Region" if Admin.const_defined?("Region")
276
286
  Admin.send :remove_const, "RegionalUser" if Admin.const_defined?("RegionalUser")
277
287
 
278
- ActiveRecord::Base.connection.instance_eval do
288
+ ActiveRecord::Base.lease_connection.instance_eval do
279
289
  remove_column :admin_users, :region_id if column_exists?(:admin_users, :region_id)
280
290
  drop_table :admin_regions, if_exists: true
281
291
  end
@@ -352,6 +362,82 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
352
362
  assert_equal apple.id, citibank.firm_id
353
363
  end
354
364
 
365
+ def test_building_the_belonging_object_for_composite_primary_key
366
+ cpk_book = cpk_books(:cpk_great_author_first_book)
367
+ order = cpk_book.build_order
368
+ cpk_book.save
369
+
370
+ _shop_id, id = order.id
371
+ assert_equal id, cpk_book.order_id
372
+ end
373
+
374
+ def test_belongs_to_with_explicit_composite_primary_key
375
+ cpk_book = cpk_books(:cpk_great_author_first_book)
376
+ order = cpk_book.build_order_explicit_fk_pk
377
+ order.shop_id = 123
378
+ cpk_book.save
379
+
380
+ shop_id, id = order.id
381
+ assert_equal id, cpk_book.order_id
382
+ assert_equal shop_id, cpk_book.shop_id
383
+ assert_equal order, cpk_book.reload.order_explicit_fk_pk
384
+ end
385
+
386
+ def test_belongs_to_with_inverse_association_for_composite_primary_key
387
+ author = Cpk::Author.new(name: "John")
388
+ book = author.books.build(id: [nil, 1], title: "The Rails Way")
389
+ order = Cpk::Order.new(book: book, status: "paid")
390
+ author.save!
391
+
392
+ _order_shop_id, order_id = order.id
393
+ assert order_id
394
+ assert_equal order_id, book.order_id
395
+ end
396
+
397
+ def test_should_set_composite_foreign_key_on_association_when_key_changes_on_associated_record
398
+ book = Cpk::Book.create!(id: [1, 2], title: "The Well-Grounded Rubyist")
399
+ order = Cpk::Order.create!(id: [1, 2], book: book)
400
+
401
+ order.shop_id = 3
402
+ order.save!
403
+
404
+ assert_equal 3, book.shop_id
405
+ end
406
+
407
+ def test_clearing_optional_cpk_belongs_to_should_preserve_shared_pk
408
+ if current_adapter?(:IBM_DBAdapter)
409
+ skip "IBM_DBAdapter does not preserve shared PK columns when nullifying optional CPK belongs_to"
410
+ end
411
+
412
+ book = Cpk::Book.create!(id: [1, 2], title: "The Well-Grounded Rubyist")
413
+ chapter = Cpk::OptionalChapter.create!(id: [1, 2], book: book)
414
+
415
+ assert_equal book, chapter.book
416
+ assert_equal [1, 2], chapter.id
417
+
418
+ chapter.update!(book: nil)
419
+
420
+ assert_equal [1, 2], chapter.id
421
+ assert_nil chapter.book_id
422
+ assert_equal chapter.author_id, book.author_id
423
+ end
424
+
425
+ def test_should_reload_association_on_model_with_query_constraints_when_foreign_key_changes
426
+ if current_adapter?(:IBM_DBAdapter)
427
+ skip "IBM_DBAdapter does not currently reload belongs_to with query_constraints after FK change"
428
+ end
429
+
430
+ blog = Sharded::Blog.create!
431
+ blog_post = Sharded::BlogPost.create!(blog: blog)
432
+ comment = Sharded::Comment.create!(blog: blog)
433
+
434
+ # Load the association once
435
+ comment.blog_post
436
+ comment.blog_post_id = blog_post.id
437
+
438
+ assert_equal blog_post, comment.blog_post
439
+ end
440
+
355
441
  def test_building_the_belonging_object_with_implicit_sti_base_class
356
442
  account = Account.new
357
443
  company = account.build_firm
@@ -411,13 +497,16 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
411
497
  Company.where(id: odegy_account.firm_id).update_all(name: "ODEGY")
412
498
  assert_equal "Odegy", odegy_account.firm.name
413
499
 
414
- assert_equal "ODEGY", odegy_account.reload_firm.name
500
+ assert_queries_count(1) { odegy_account.reload_firm }
501
+
502
+ assert_no_queries { odegy_account.firm }
503
+ assert_equal "ODEGY", odegy_account.firm.name
415
504
  end
416
505
 
417
506
  def test_reload_the_belonging_object_with_query_cache
418
507
  odegy_account_id = accounts(:odegy_account).id
419
508
 
420
- connection = ActiveRecord::Base.connection
509
+ connection = ActiveRecord::Base.lease_connection
421
510
  connection.enable_query_cache!
422
511
  connection.clear_query_cache
423
512
 
@@ -430,12 +519,24 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
430
519
  assert_equal 2, connection.query_cache.size
431
520
 
432
521
  # Clear the cache and fetch the firm again, populating the cache with a query
433
- assert_queries(1) { odegy_account.reload_firm }
522
+ assert_queries_count(1) { odegy_account.reload_firm }
434
523
 
435
524
  # This query is not cached anymore, so it should make a real SQL query
436
- assert_queries(1) { Account.find(odegy_account_id) }
525
+ assert_queries_count(1) { Account.find(odegy_account_id) }
437
526
  ensure
438
- ActiveRecord::Base.connection.disable_query_cache!
527
+ ActiveRecord::Base.lease_connection.disable_query_cache!
528
+ end
529
+
530
+ def test_resetting_the_association
531
+ odegy_account = accounts(:odegy_account)
532
+
533
+ assert_equal "Odegy", odegy_account.firm.name
534
+ Company.where(id: odegy_account.firm_id).update_all(name: "ODEGY")
535
+ assert_equal "Odegy", odegy_account.firm.name
536
+
537
+ assert_no_queries { odegy_account.reset_firm }
538
+ assert_queries_count(1) { odegy_account.firm }
539
+ assert_equal "ODEGY", odegy_account.firm.name
439
540
  end
440
541
 
441
542
  def test_natural_assignment_to_nil
@@ -491,7 +592,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
491
592
  assert_equal member, sponsor.sponsorable
492
593
  assert_nil sponsor.sponsorable_with_conditions
493
594
 
494
- sponsor = Sponsor.preload(:sponsorable, :sponsorable_with_conditions).last
595
+ sponsor = Sponsor.preload(:sponsorable, :sponsorable_with_conditions).find(sponsor.id)
495
596
 
496
597
  assert_equal member, sponsor.sponsorable
497
598
  assert_nil sponsor.sponsorable_with_conditions
@@ -662,7 +763,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
662
763
  def test_belongs_to_counter_after_save
663
764
  topic = Topic.create!(title: "monday night")
664
765
 
665
- assert_queries(2) do
766
+ assert_queries_count(4) do
666
767
  topic.replies.create!(title: "re: monday night", content: "football")
667
768
  end
668
769
 
@@ -699,7 +800,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
699
800
  debate.touch(time: time)
700
801
  debate2.touch(time: time)
701
802
 
702
- assert_queries(3) do
803
+ assert_queries_count(5) do
703
804
  reply.parent_title = "debate"
704
805
  reply.save!
705
806
  end
@@ -710,7 +811,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
710
811
  debate.touch(time: time)
711
812
  debate2.touch(time: time)
712
813
 
713
- assert_queries(3) do
814
+ assert_queries_count(5) do
714
815
  reply.topic_with_primary_key = debate2
715
816
  reply.save!
716
817
  end
@@ -723,7 +824,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
723
824
  line_item = LineItem.create!
724
825
  Invoice.create!(line_items: [line_item])
725
826
 
726
- assert_queries(1) { line_item.touch }
827
+ assert_queries_count(3) { line_item.touch }
727
828
  end
728
829
 
729
830
  def test_belongs_to_with_touch_on_multiple_records
@@ -731,14 +832,14 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
731
832
  line_item2 = LineItem.create!(amount: 2)
732
833
  Invoice.create!(line_items: [line_item, line_item2])
733
834
 
734
- assert_queries(1) do
835
+ assert_queries_count(3) do
735
836
  LineItem.transaction do
736
837
  line_item.touch
737
838
  line_item2.touch
738
839
  end
739
840
  end
740
841
 
741
- assert_queries(2) do
842
+ assert_queries_count(6) do
742
843
  line_item.touch
743
844
  line_item2.touch
744
845
  end
@@ -763,14 +864,14 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
763
864
 
764
865
  line_item.invoice = nil
765
866
 
766
- assert_queries(2) { line_item.touch }
867
+ assert_queries_count(4) { line_item.touch }
767
868
  end
768
869
 
769
870
  def test_belongs_to_with_touch_option_on_update
770
871
  line_item = LineItem.create!
771
872
  Invoice.create!(line_items: [line_item])
772
873
 
773
- assert_queries(2) { line_item.update amount: 10 }
874
+ assert_queries_count(4) { line_item.update amount: 10 }
774
875
  end
775
876
 
776
877
  def test_belongs_to_with_touch_option_on_empty_update
@@ -784,7 +885,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
784
885
  line_item = LineItem.create!
785
886
  Invoice.create!(line_items: [line_item])
786
887
 
787
- assert_queries(2) { line_item.destroy }
888
+ assert_queries_count(4) { line_item.destroy }
788
889
  end
789
890
 
790
891
  def test_belongs_to_with_touch_option_on_destroy_with_destroyed_parent
@@ -792,7 +893,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
792
893
  invoice = Invoice.create!(line_items: [line_item])
793
894
  invoice.destroy
794
895
 
795
- assert_queries(1) { line_item.destroy }
896
+ assert_queries_count(3) { line_item.destroy }
796
897
  end
797
898
 
798
899
  def test_belongs_to_with_touch_option_on_touch_and_reassigned_parent
@@ -801,7 +902,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
801
902
 
802
903
  line_item.invoice = Invoice.create!
803
904
 
804
- assert_queries(3) { line_item.touch }
905
+ assert_queries_count(5) { line_item.touch }
805
906
  end
806
907
 
807
908
  def test_belongs_to_counter_after_update
@@ -878,7 +979,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
878
979
  def test_dont_find_target_when_saving_foreign_key_after_stale_association_loaded
879
980
  client = Client.create!(name: "Test client", firm_with_basic_id: Firm.find(1))
880
981
  client.firm_id = Firm.create!(name: "Test firm").id
881
- assert_queries(1) { client.save! }
982
+ assert_queries_count(3) { client.save! }
882
983
  end
883
984
 
884
985
  def test_field_name_same_as_foreign_key
@@ -996,15 +1097,17 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
996
1097
 
997
1098
  def test_polymorphic_assignment_foreign_key_type_string
998
1099
  comment = Comment.first
999
- comment.author = Author.first
1000
- comment.resource = Member.first
1100
+ comment.author = authors(:david)
1101
+ comment.resource = members(:groucho)
1001
1102
  comment.save
1002
1103
 
1003
- assert_equal Comment.all.to_a,
1004
- Comment.includes(:author).to_a
1104
+ assert_equal 1, authors(:david).id
1105
+ assert_equal 1, comment.author_id
1106
+ assert_equal authors(:david), Comment.includes(:author).first.author
1005
1107
 
1006
- assert_equal Comment.all.to_a,
1007
- Comment.includes(:resource).to_a
1108
+ assert_equal 1, members(:groucho).id
1109
+ assert_equal "1", comment.resource_id
1110
+ assert_equal members(:groucho), Comment.includes(:resource).first.resource
1008
1111
  end
1009
1112
 
1010
1113
  def test_polymorphic_assignment_foreign_type_field_updating
@@ -1090,8 +1193,10 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1090
1193
  end
1091
1194
 
1092
1195
  def test_belongs_to_proxy_should_respond_to_private_methods_via_send
1093
- companies(:first_firm).send(:private_method)
1094
- companies(:second_client).firm.send(:private_method)
1196
+ assert_nothing_raised do
1197
+ companies(:first_firm).send(:private_method)
1198
+ companies(:second_client).firm.send(:private_method)
1199
+ end
1095
1200
  end
1096
1201
 
1097
1202
  def test_save_of_record_with_loaded_belongs_to
@@ -1129,7 +1234,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1129
1234
  error = assert_raise ArgumentError do
1130
1235
  Class.new(Author).belongs_to :special_author_address, dependent: :nullify
1131
1236
  end
1132
- assert_equal error.message, "The :dependent option must be one of [:destroy, :delete, :destroy_async], but is :nullify"
1237
+ assert_equal "The :dependent option must be one of [:destroy, :delete, :destroy_async], but is :nullify", error.message
1133
1238
  end
1134
1239
 
1135
1240
  class EssayDestroy < ActiveRecord::Base
@@ -1174,7 +1279,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1174
1279
 
1175
1280
  def test_attributes_are_being_set_when_initialized_from_belongs_to_association_with_where_clause
1176
1281
  new_firm = accounts(:signals37).build_firm(name: "Apple")
1177
- assert_equal new_firm.name, "Apple"
1282
+ assert_equal "Apple", new_firm.name
1178
1283
  end
1179
1284
 
1180
1285
  def test_attributes_are_set_without_error_when_initialized_from_belongs_to_association_with_array_in_where_clause
@@ -1203,6 +1308,33 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1203
1308
  assert_equal companies(:another_firm), client.firm_with_condition
1204
1309
  end
1205
1310
 
1311
+ def test_assigning_nil_on_an_association_clears_the_associations_inverse
1312
+ with_has_many_inversing do
1313
+ book = Book.create!
1314
+ citation = book.citations.create!
1315
+
1316
+ assert_same book, citation.book
1317
+
1318
+ assert_nothing_raised do
1319
+ citation.book = nil
1320
+ citation.save!
1321
+ end
1322
+ end
1323
+ end
1324
+
1325
+ def test_clearing_an_association_clears_the_associations_inverse
1326
+ author = Author.create(name: "Jimmy Tolkien")
1327
+ post = author.create_post(title: "The silly medallion", body: "")
1328
+ assert_equal post, author.post
1329
+ assert_equal author, post.author
1330
+
1331
+ author.update!(post: nil)
1332
+ assert_nil author.post
1333
+
1334
+ post.update!(title: "The Silmarillion")
1335
+ assert_nil author.post
1336
+ end
1337
+
1206
1338
  def test_destroying_child_with_unloaded_parent_and_foreign_key_and_touch_is_possible_with_has_many_inversing
1207
1339
  with_has_many_inversing do
1208
1340
  book = Book.create!
@@ -1299,6 +1431,61 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1299
1431
  assert_equal groucho, sponsor.thing
1300
1432
  end
1301
1433
 
1434
+ class WheelPolymorphicName < ActiveRecord::Base
1435
+ self.table_name = "wheels"
1436
+ belongs_to :wheelable, polymorphic: true, counter_cache: :wheels_count, touch: :wheels_owned_at
1437
+
1438
+ def self.polymorphic_class_for(name)
1439
+ raise "Unexpected name: #{name}" unless name == "polymorphic_car"
1440
+ CarPolymorphicName
1441
+ end
1442
+ end
1443
+
1444
+ class CarPolymorphicName < ActiveRecord::Base
1445
+ self.table_name = "cars"
1446
+ has_many :wheels, as: :wheelable
1447
+
1448
+ def self.polymorphic_name
1449
+ "polymorphic_car"
1450
+ end
1451
+ end
1452
+
1453
+ def test_polymorphic_with_custom_name_counter_cache
1454
+ car = CarPolymorphicName.create!
1455
+ wheel = WheelPolymorphicName.create!(wheelable_type: "polymorphic_car", wheelable_id: car.id)
1456
+ assert_equal 1, car.reload.wheels_count
1457
+
1458
+ wheel.update! wheelable: nil
1459
+
1460
+ assert_equal 0, car.reload.wheels_count
1461
+ end
1462
+
1463
+ def test_polymorphic_with_custom_name_touch_old_belongs_to_model
1464
+ car = CarPolymorphicName.create!
1465
+ wheel = WheelPolymorphicName.create!(wheelable: car)
1466
+
1467
+ touch_time = 1.day.ago.round
1468
+ travel_to(touch_time) do
1469
+ wheel.update!(wheelable: nil)
1470
+ end
1471
+
1472
+ assert_equal touch_time, car.reload.wheels_owned_at
1473
+ end
1474
+
1475
+ def test_polymorphic_stale_state_handles_nil_foreign_keys_correctly
1476
+ klass = Class.new(ActiveRecord::Base) do
1477
+ self.table_name = "records"
1478
+
1479
+ has_one :attachment, as: :record
1480
+
1481
+ def self.polymorphic_name
1482
+ "Blob"
1483
+ end
1484
+ end
1485
+
1486
+ assert_nothing_raised { Attachment.create!(record: klass.build, record_type: "Document") }
1487
+ end
1488
+
1302
1489
  def test_build_with_conditions
1303
1490
  client = companies(:second_client)
1304
1491
  firm = client.build_bob_firm
@@ -1355,6 +1542,31 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1355
1542
  assert_equal firm.id, client.client_of
1356
1543
  end
1357
1544
 
1545
+ def test_should_set_foreign_key_on_create_association_with_unpersisted_owner
1546
+ tagging = Tagging.new
1547
+ tag = tagging.create_tag
1548
+
1549
+ assert_not_predicate tagging, :persisted?
1550
+ assert_predicate tag, :persisted?
1551
+ assert_equal tag.id, tagging.tag_id
1552
+ end
1553
+
1554
+ def test_should_set_foreign_key_on_save
1555
+ client = Client.create! name: "fuu"
1556
+ firm = client.build_firm name: "baa"
1557
+
1558
+ firm.save
1559
+ assert_equal firm.id, client.client_of
1560
+ end
1561
+
1562
+ def test_should_set_foreign_key_on_save!
1563
+ client = Client.create! name: "fuu"
1564
+ firm = client.build_firm name: "baa"
1565
+
1566
+ firm.save!
1567
+ assert_equal firm.id, client.client_of
1568
+ end
1569
+
1358
1570
  def test_self_referential_belongs_to_with_counter_cache_assigning_nil
1359
1571
  comment = Comment.create! post: posts(:thinking), body: "fuu"
1360
1572
  comment.parent = nil
@@ -1479,6 +1691,218 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
1479
1691
  assert_equal 1, Comment.where(post_id: post.id).count
1480
1692
  assert_equal post.id, Comment.last.post.id
1481
1693
  end
1694
+
1695
+ test "tracking change from one persisted record to another" do
1696
+ node = nodes(:child_one_of_a)
1697
+ assert_not_nil node.parent
1698
+ assert_not node.parent_changed?
1699
+ assert_not node.parent_previously_changed?
1700
+
1701
+ node.parent = nodes(:grandparent)
1702
+ assert_predicate node, :parent_changed?
1703
+ assert_not node.parent_previously_changed?
1704
+
1705
+ node.save!
1706
+ assert_not node.parent_changed?
1707
+ assert_predicate node, :parent_previously_changed?
1708
+ end
1709
+
1710
+ test "tracking change from persisted record to new record" do
1711
+ node = nodes(:child_one_of_a)
1712
+ assert_not_nil node.parent
1713
+ assert_not node.parent_changed?
1714
+ assert_not node.parent_previously_changed?
1715
+
1716
+ node.parent = Node.new(tree: node.tree, parent: nodes(:parent_a), name: "Child three")
1717
+ assert_predicate node, :parent_changed?
1718
+ assert_not node.parent_previously_changed?
1719
+
1720
+ node.save!
1721
+ assert_not node.parent_changed?
1722
+ assert_predicate node, :parent_previously_changed?
1723
+ end
1724
+
1725
+ test "tracking change from persisted record to nil" do
1726
+ node = nodes(:child_one_of_a)
1727
+ assert_not_nil node.parent
1728
+ assert_not node.parent_changed?
1729
+ assert_not node.parent_previously_changed?
1730
+
1731
+ node.parent = nil
1732
+ assert_predicate node, :parent_changed?
1733
+ assert_not node.parent_previously_changed?
1734
+
1735
+ node.save!
1736
+ assert_not node.parent_changed?
1737
+ assert_predicate node, :parent_previously_changed?
1738
+ end
1739
+
1740
+ test "tracking change from nil to persisted record" do
1741
+ node = nodes(:grandparent)
1742
+ assert_nil node.parent
1743
+ assert_not node.parent_changed?
1744
+ assert_not node.parent_previously_changed?
1745
+
1746
+ node.parent = Node.create!(tree: node.tree, name: "Great-grandparent")
1747
+ assert_predicate node, :parent_changed?
1748
+ assert_not node.parent_previously_changed?
1749
+
1750
+ node.save!
1751
+ assert_not node.parent_changed?
1752
+ assert_predicate node, :parent_previously_changed?
1753
+ end
1754
+
1755
+ test "tracking change from nil to new record" do
1756
+ node = nodes(:grandparent)
1757
+ assert_nil node.parent
1758
+ assert_not node.parent_changed?
1759
+ assert_not node.parent_previously_changed?
1760
+
1761
+ node.parent = Node.new(tree: node.tree, name: "Great-grandparent")
1762
+ assert_predicate node, :parent_changed?
1763
+ assert_not node.parent_previously_changed?
1764
+
1765
+ node.save!
1766
+ assert_not node.parent_changed?
1767
+ assert_predicate node, :parent_previously_changed?
1768
+ end
1769
+
1770
+ test "tracking polymorphic changes" do
1771
+ comment = comments(:greetings)
1772
+ assert_nil comment.author
1773
+ assert_not comment.author_changed?
1774
+ assert_not comment.author_previously_changed?
1775
+
1776
+ comment.author = authors(:david)
1777
+ assert_predicate comment, :author_changed?
1778
+
1779
+ comment.save!
1780
+ assert_not comment.author_changed?
1781
+ assert_predicate comment, :author_previously_changed?
1782
+
1783
+ assert_equal authors(:david).id, companies(:first_firm).id
1784
+
1785
+ comment.author = companies(:first_firm)
1786
+ assert_predicate comment, :author_changed?
1787
+
1788
+ comment.save!
1789
+ assert_not comment.author_changed?
1790
+ assert_predicate comment, :author_previously_changed?
1791
+ end
1792
+
1793
+ class ShipRequired < ActiveRecord::Base
1794
+ self.table_name = "ships"
1795
+ belongs_to :developer, required: true
1796
+ end
1797
+
1798
+ test "runs parent presence check if parent changed or nil" do
1799
+ david = developers(:david)
1800
+ jamis = developers(:jamis)
1801
+
1802
+ ship = ShipRequired.create!(name: "Medusa", developer: david)
1803
+ assert_equal david, ship.developer
1804
+
1805
+ assert_queries_count(4) do # UPDATE and SELECT to check developer presence
1806
+ ship.update!(developer_id: jamis.id)
1807
+ end
1808
+
1809
+ ship.update_column(:developer_id, nil)
1810
+ ship.reload
1811
+
1812
+ assert_queries_count(4) do # UPDATE and SELECT to check developer presence
1813
+ ship.update!(developer_id: david.id)
1814
+ end
1815
+ end
1816
+
1817
+ test "skips parent presence check if parent has not changed" do
1818
+ david = developers(:david)
1819
+ ship = ShipRequired.create!(name: "Medusa", developer: david)
1820
+ ship.reload # unload developer association
1821
+
1822
+ assert_queries_count(3) do # UPDATE only, no SELECT to check developer presence
1823
+ ship.update!(name: "Leviathan")
1824
+ end
1825
+ end
1826
+
1827
+ test "skips parent presence check for composite foreign key if parent has not changed" do
1828
+ order = Cpk::Order.create!(id: [1, 2])
1829
+ book = Cpk::BookWithRequiredOrder.create!(id: [3, 4], order: order, title: "Book")
1830
+ book.reload
1831
+
1832
+ expected_queries = current_adapter?(:IBM_DBAdapter) ? 1 : 0
1833
+ assert_queries_count(expected_queries) do
1834
+ assert book.valid?
1835
+ end
1836
+ end
1837
+
1838
+ test "validates composite foreign key belongs_to when foreign key column is nil" do
1839
+ book = Cpk::BookWithRequiredOrder.new(id: [1, 1], shop_id: nil, order_id: nil, title: "Book")
1840
+ assert_not book.valid?
1841
+ assert_includes book.errors.full_messages, "Order must exist"
1842
+ end
1843
+
1844
+ test "validates composite foreign key belongs_to when foreign key column changes" do
1845
+ order = Cpk::Order.create!(id: [1, 2])
1846
+ book = Cpk::BookWithRequiredOrder.create!(id: [3, 4], order: order, title: "Book")
1847
+ book.reload
1848
+
1849
+ book.order_id = 999999
1850
+ assert_not book.valid?
1851
+ assert_includes book.errors.full_messages, "Order must exist"
1852
+ end
1853
+
1854
+ test "runs parent presence check if parent has not changed and belongs_to_required_validates_foreign_key is set" do
1855
+ original_value = ActiveRecord.belongs_to_required_validates_foreign_key
1856
+ ActiveRecord.belongs_to_required_validates_foreign_key = true
1857
+
1858
+ model = Class.new(ActiveRecord::Base) do
1859
+ self.table_name = "ships"
1860
+ def self.name; "Temp"; end
1861
+ belongs_to :developer, required: true
1862
+ end
1863
+
1864
+ david = developers(:david)
1865
+ ship = model.create!(name: "Medusa", developer: david)
1866
+ ship.reload # unload developer association
1867
+
1868
+ assert_queries_count(4) do # UPDATE and SELECT to check developer presence
1869
+ ship.update!(name: "Leviathan")
1870
+ end
1871
+ ensure
1872
+ ActiveRecord.belongs_to_required_validates_foreign_key = original_value
1873
+ end
1874
+
1875
+ test "composite primary key malformed association class" do
1876
+ error = assert_raises(ActiveRecord::CompositePrimaryKeyMismatchError) do
1877
+ book = Cpk::BrokenBook.new(title: "Some book", order: Cpk::Order.new(id: [1, 2]))
1878
+ book.save!
1879
+ end
1880
+
1881
+ assert_equal(<<~MESSAGE.squish, error.message)
1882
+ Association Cpk::BrokenBook#order primary key ["shop_id", "status"]
1883
+ doesn't match with foreign key order_id. Please specify query_constraints, or primary_key and foreign_key values.
1884
+ MESSAGE
1885
+ end
1886
+
1887
+ test "composite primary key malformed association owner class" do
1888
+ error = assert_raises(ActiveRecord::CompositePrimaryKeyMismatchError) do
1889
+ book = Cpk::BrokenBookWithNonCpkOrder.new(title: "Some book", order: Cpk::NonCpkOrder.new(id: 1))
1890
+ book.save!
1891
+ end
1892
+
1893
+ assert_equal(<<~MESSAGE.squish, error.message)
1894
+ Association Cpk::BrokenBookWithNonCpkOrder#order primary key ["id"]
1895
+ doesn't match with foreign key ["shop_id", "order_id"]. Please specify query_constraints, or primary_key and foreign_key values.
1896
+ MESSAGE
1897
+ end
1898
+
1899
+ test "association with query constraints assigns id on replacement" do
1900
+ book = Cpk::NonCpkBook.create!(id: 1, author_id: 2, non_cpk_order: Cpk::NonCpkOrder.new)
1901
+ other_order = Cpk::NonCpkOrder.create!
1902
+ book.non_cpk_order = other_order
1903
+
1904
+ assert_equal(other_order.id, book.order_id)
1905
+ end
1482
1906
  end
1483
1907
 
1484
1908
  class BelongsToWithForeignKeyTest < ActiveRecord::TestCase
@@ -1489,5 +1913,42 @@ class BelongsToWithForeignKeyTest < ActiveRecord::TestCase
1489
1913
  author = Author.create! name: "Author", author_address_id: address.id
1490
1914
 
1491
1915
  author.destroy!
1916
+
1917
+ assert_not AuthorAddress.exists?(address.id)
1918
+ assert_not Author.exists?(author.id)
1919
+ end
1920
+ end
1921
+
1922
+ class AsyncBelongsToAssociationsTest < ActiveRecord::TestCase
1923
+ include WaitForAsyncTestHelper
1924
+
1925
+ self.use_transactional_tests = false
1926
+
1927
+ fixtures :companies
1928
+
1929
+ unless in_memory_db?
1930
+ def test_async_load_belongs_to
1931
+ client = Client.find(3)
1932
+ first_firm = companies(:first_firm)
1933
+
1934
+ client.association(:firm).async_load_target
1935
+ wait_for_async_query
1936
+
1937
+ events = []
1938
+ callback = -> (event) do
1939
+ events << event unless event.payload[:name] == "SCHEMA"
1940
+ end
1941
+ ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
1942
+ client.firm
1943
+ end
1944
+
1945
+ assert_no_queries do
1946
+ assert_equal first_firm, client.firm
1947
+ assert_equal first_firm.name, client.firm.name
1948
+ end
1949
+
1950
+ assert_equal 1, events.size
1951
+ assert_equal true, events.first.payload[:async]
1952
+ end
1492
1953
  end
1493
1954
  end