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
@@ -10,14 +10,19 @@ require "models/categorization"
10
10
  require "models/person"
11
11
  require "models/tagging"
12
12
  require "models/tag"
13
+ require "models/sharded/blog_post"
14
+ require "models/sharded/comment"
15
+ require "models/friendship"
16
+ require "models/reference"
17
+ require "models/job"
13
18
 
14
19
  class InnerJoinAssociationTest < ActiveRecord::TestCase
15
20
  fixtures :authors, :author_addresses, :essays, :posts, :comments, :categories, :categories_posts, :categorizations,
16
- :taggings, :tags, :people
21
+ :taggings, :tags, :people, :sharded_comments, :sharded_blog_posts
17
22
 
18
23
  def test_construct_finder_sql_applies_aliases_tables_on_association_conditions
19
- result = Author.joins(:thinking_posts, :welcome_posts).to_a
20
- assert_equal authors(:david), result.first
24
+ result = Author.joins(:thinking_posts, :welcome_posts).first
25
+ assert_equal authors(:david), result
21
26
  end
22
27
 
23
28
  def test_construct_finder_sql_does_not_table_name_collide_on_duplicate_associations
@@ -41,7 +46,7 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase
41
46
  SQL
42
47
 
43
48
  expected = people(:susan)
44
- assert_sql(/agents_people_2/i) do
49
+ assert_queries_match(/agents_people_2/i) do
45
50
  assert_equal [expected], Person.joins(:agents).joins(string_join)
46
51
  end
47
52
  end
@@ -52,7 +57,7 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase
52
57
  constraint = agents[:primary_contact_id].eq(agents_2[:id]).and(agents[:id].gt(agents_2[:id]))
53
58
 
54
59
  expected = people(:susan)
55
- assert_sql(/agents_people_2/i) do
60
+ assert_queries_match(/agents_people_2/i) do
56
61
  assert_equal [expected], Person.joins(:agents).joins(agents.create_join(agents, agents.create_on(constraint)))
57
62
  end
58
63
  end
@@ -178,7 +183,7 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase
178
183
 
179
184
  def test_find_with_conditions_on_reflection
180
185
  assert_not_empty posts(:welcome).comments
181
- assert Post.joins(:nonexistent_comments).where(id: posts(:welcome).id).empty? # [sic!]
186
+ assert_predicate Post.joins(:nonexistent_comments).where(id: posts(:welcome).id), :empty? # [sic!]
182
187
  end
183
188
 
184
189
  def test_find_with_conditions_on_through_reflection
@@ -212,4 +217,29 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase
212
217
  assert_equal 0, categories.first.special_categorizations.size
213
218
  assert_equal 1, categories.second.special_categorizations.size
214
219
  end
220
+
221
+ test "joins a belongs_to association with a composite foreign key" do
222
+ first_post_comments = Sharded::Comment.joins(:blog_post).where(blog_post: { title: "My first post in my Blog1!" }).to_a
223
+ expected_blog_post = sharded_blog_posts(:great_post_blog_one)
224
+
225
+ assert_not_empty comments
226
+ assert_equal(expected_blog_post.comments.to_a.sort, first_post_comments.sort)
227
+ end
228
+
229
+ test "joins a has_many association with a composite foreign key" do
230
+ blog_posts = Sharded::BlogPost.joins(:comments).where(comments: { body: "Your first blog post is great!" }).to_a
231
+
232
+ expected_comment = sharded_comments(:unique_comment_blog_post_one)
233
+
234
+ assert_not_empty blog_posts
235
+ assert_equal(expected_comment.blog_post, blog_posts.first)
236
+ end
237
+
238
+ def test_inner_joins_includes_all_nested_associations
239
+ sql, = capture_sql { Friendship.joins(:friend_favorite_reference_job, :follower_favorite_reference_job).to_a }
240
+
241
+ # DB2 doesn't quote composite identifiers in JOIN conditions
242
+ assert_match %r(friendships\.friend_id)i, sql
243
+ assert_match %r(friendships\.follower_id)i, sql
244
+ end
215
245
  end
@@ -20,21 +20,26 @@ require "models/developer"
20
20
  require "models/company"
21
21
  require "models/project"
22
22
  require "models/author"
23
- require "models/post"
24
23
  require "models/user"
25
24
  require "models/room"
25
+ require "models/contract"
26
+ require "models/subscription"
27
+ require "models/subscriber"
28
+ require "models/book"
29
+ require "models/branch"
30
+ require "models/cpk"
26
31
 
27
32
  class AutomaticInverseFindingTests < ActiveRecord::TestCase
28
- fixtures :ratings, :comments, :cars
33
+ fixtures :ratings, :comments, :cars, :books
29
34
 
30
35
  def test_has_one_and_belongs_to_should_find_inverse_automatically_on_multiple_word_name
31
36
  monkey_reflection = MixedCaseMonkey.reflect_on_association(:human)
32
37
  human_reflection = Human.reflect_on_association(:mixed_case_monkey)
33
38
 
34
- assert monkey_reflection.has_inverse?, "The monkey reflection should have an inverse"
39
+ assert_predicate monkey_reflection, :has_inverse?, "The monkey reflection should have an inverse"
35
40
  assert_equal human_reflection, monkey_reflection.inverse_of, "The monkey reflection's inverse should be the human reflection"
36
41
 
37
- assert human_reflection.has_inverse?, "The human reflection should have an inverse"
42
+ assert_predicate human_reflection, :has_inverse?, "The human reflection should have an inverse"
38
43
  assert_equal monkey_reflection, human_reflection.inverse_of, "The human reflection's inverse should be the monkey reflection"
39
44
  end
40
45
 
@@ -42,7 +47,7 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
42
47
  account_reflection = Admin::Account.reflect_on_association(:users)
43
48
  user_reflection = Admin::User.reflect_on_association(:account)
44
49
 
45
- assert account_reflection.has_inverse?, "The Admin::Account reflection should have an inverse"
50
+ assert_predicate account_reflection, :has_inverse?, "The Admin::Account reflection should have an inverse"
46
51
  assert_equal user_reflection, account_reflection.inverse_of, "The Admin::Account reflection's inverse should be the Admin::User reflection"
47
52
  end
48
53
 
@@ -50,10 +55,10 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
50
55
  car_reflection = Car.reflect_on_association(:bulb)
51
56
  bulb_reflection = Bulb.reflect_on_association(:car)
52
57
 
53
- assert car_reflection.has_inverse?, "The Car reflection should have an inverse"
58
+ assert_predicate car_reflection, :has_inverse?, "The Car reflection should have an inverse"
54
59
  assert_equal bulb_reflection, car_reflection.inverse_of, "The Car reflection's inverse should be the Bulb reflection"
55
60
 
56
- assert bulb_reflection.has_inverse?, "The Bulb reflection should have an inverse"
61
+ assert_predicate bulb_reflection, :has_inverse?, "The Bulb reflection should have an inverse"
57
62
  assert_equal car_reflection, bulb_reflection.inverse_of, "The Bulb reflection's inverse should be the Car reflection"
58
63
  end
59
64
 
@@ -61,7 +66,7 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
61
66
  comment_reflection = Comment.reflect_on_association(:ratings)
62
67
  rating_reflection = Rating.reflect_on_association(:comment)
63
68
 
64
- assert comment_reflection.has_inverse?, "The Comment reflection should have an inverse"
69
+ assert_predicate comment_reflection, :has_inverse?, "The Comment reflection should have an inverse"
65
70
  assert_equal rating_reflection, comment_reflection.inverse_of, "The Comment reflection's inverse should be the Rating reflection"
66
71
  end
67
72
 
@@ -79,11 +84,11 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
79
84
  post_reflection = Post.reflect_on_association(:author)
80
85
 
81
86
  assert_respond_to author_reflection, :has_inverse?
82
- assert author_reflection.has_inverse?, "The Author reflection should have an inverse"
87
+ assert_predicate author_reflection, :has_inverse?, "The Author reflection should have an inverse"
83
88
  assert_equal post_reflection, author_reflection.inverse_of, "The Author reflection's inverse should be the Post reflection"
84
89
 
85
90
  assert_respond_to author_child_reflection, :has_inverse?
86
- assert author_child_reflection.has_inverse?, "The Author reflection should have an inverse"
91
+ assert_predicate author_child_reflection, :has_inverse?, "The Author reflection should have an inverse"
87
92
  assert_equal post_reflection, author_child_reflection.inverse_of, "The Author reflection's inverse should be the Post reflection"
88
93
  end
89
94
 
@@ -110,6 +115,51 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
110
115
  assert_not_equal room_reflection, owner_reflection.inverse_of
111
116
  end
112
117
 
118
+ def test_has_many_and_belongs_to_with_a_scope_and_automatic_scope_inversing_should_find_inverse_automatically
119
+ contacts_reflection = Company.reflect_on_association(:special_contracts)
120
+ company_reflection = SpecialContract.reflect_on_association(:company)
121
+
122
+ assert contacts_reflection.scope
123
+ assert_not company_reflection.scope
124
+
125
+ with_automatic_scope_inversing(contacts_reflection, company_reflection) do
126
+ assert_predicate contacts_reflection, :has_inverse?
127
+ assert_equal company_reflection, contacts_reflection.inverse_of
128
+ assert_not_equal contacts_reflection, company_reflection.inverse_of
129
+ end
130
+ end
131
+
132
+ def test_has_one_and_belongs_to_with_a_scope_and_automatic_scope_inversing_should_find_inverse_automatically
133
+ post_reflection = Author.reflect_on_association(:recent_post)
134
+ author_reflection = Post.reflect_on_association(:author)
135
+
136
+ assert post_reflection.scope
137
+ assert_not author_reflection.scope
138
+
139
+ with_automatic_scope_inversing(post_reflection, author_reflection) do
140
+ assert_predicate post_reflection, :has_inverse?
141
+ assert_equal author_reflection, post_reflection.inverse_of
142
+ assert_not_equal post_reflection, author_reflection.inverse_of
143
+ end
144
+ end
145
+
146
+ def test_has_many_with_scoped_belongs_to_does_not_find_inverse_automatically
147
+ book = books(:tlg)
148
+ book.update_attribute(:author_visibility, :invisible)
149
+
150
+ assert_nil book.subscriptions.new.book
151
+
152
+ subscription_reflection = Book.reflect_on_association(:subscriptions)
153
+ book_reflection = Subscription.reflect_on_association(:book)
154
+
155
+ assert_not subscription_reflection.scope
156
+ assert book_reflection.scope
157
+
158
+ with_automatic_scope_inversing(book_reflection, subscription_reflection) do
159
+ assert_nil book.subscriptions.new.book
160
+ end
161
+ end
162
+
113
163
  def test_has_one_and_belongs_to_automatic_inverse_shares_objects
114
164
  car = Car.first
115
165
  bulb = Bulb.create!(car: car)
@@ -150,6 +200,18 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
150
200
  assert_equal comment.body, rating.comment.body, "Changing the original Comment's body should change the Comment's body on the association"
151
201
  end
152
202
 
203
+ def test_belongs_to_should_find_inverse_has_many_automatically
204
+ assert_equal true, Subscription.automatically_invert_plural_associations
205
+
206
+ book = Book.create!
207
+ subscriber = book.subscribers.new nick: "Nickname"
208
+
209
+ subscriber.save!
210
+
211
+ assert_equal [subscriber], book.reload.subscribers
212
+ assert_equal 1, book.reload.subscribers.count
213
+ end
214
+
153
215
  def test_polymorphic_and_has_many_through_relationships_should_not_have_inverses
154
216
  sponsor_reflection = Sponsor.reflect_on_association(:sponsorable)
155
217
 
@@ -165,6 +227,20 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
165
227
 
166
228
  assert_predicate human_reflection, :has_inverse?
167
229
  end
230
+
231
+ def test_has_many_inverse_of_derived_automatically_despite_of_composite_foreign_key
232
+ car_review_reflection = Cpk::Car.reflect_on_association(:car_reviews)
233
+
234
+ assert_predicate car_review_reflection, :has_inverse?
235
+ assert_equal Cpk::CarReview.reflect_on_association(:car), car_review_reflection.inverse_of
236
+ end
237
+
238
+ def test_belongs_to_inverse_of_derived_automatically_despite_of_composite_foreign_key
239
+ car_reflection = Cpk::CarReview.reflect_on_association(:car)
240
+
241
+ assert_predicate car_reflection, :has_inverse?
242
+ assert_equal Cpk::Car.reflect_on_association(:car_reviews), car_reflection.inverse_of
243
+ end
168
244
  end
169
245
 
170
246
  class InverseAssociationTests < ActiveRecord::TestCase
@@ -240,8 +316,8 @@ class InverseAssociationTests < ActiveRecord::TestCase
240
316
  Developer.create!(name: "Gorbypuff", firm: firm)
241
317
 
242
318
  new_project = Project.last
243
- assert Project.reflect_on_association(:lead_developer).inverse_of.present?, "Expected inverse of to be present"
244
- assert new_project.lead_developer.present?, "Expected lead developer to be present on the project"
319
+ assert_predicate Project.reflect_on_association(:lead_developer).inverse_of, :present?, "Expected inverse of to be present"
320
+ assert_predicate new_project.lead_developer, :present?, "Expected lead developer to be present on the project"
245
321
  end
246
322
  end
247
323
 
@@ -328,7 +404,7 @@ class InverseHasOneTests < ActiveRecord::TestCase
328
404
  assert_equal face, human.face
329
405
  assert_equal face.description, human.face.description, "Description of the face should be the same before changes to child instance"
330
406
  face.description = "Bongo"
331
- assert_equal face.description, human.face.description, "Description of the face should be the same after changes to chield instance"
407
+ assert_equal face.description, human.face.description, "Description of the face should be the same after changes to child instance"
332
408
  human.face.description = "Mungo"
333
409
  assert_equal face.description, human.face.description, "Description of the face should be the same after changes to replaced-parent-owned instance"
334
410
  end
@@ -337,15 +413,13 @@ class InverseHasOneTests < ActiveRecord::TestCase
337
413
  assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Human.first.confused_face }
338
414
  end
339
415
 
340
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
341
- def test_trying_to_use_inverses_that_dont_exist_should_have_suggestions_for_fix
342
- error = assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) {
343
- Human.first.confused_face
344
- }
416
+ def test_trying_to_use_inverses_that_dont_exist_should_have_suggestions_for_fix
417
+ error = assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) {
418
+ Human.first.confused_face
419
+ }
345
420
 
346
- assert_match "Did you mean?", error.message
347
- assert_equal "super_human", error.corrections.first
348
- end
421
+ assert_match "Did you mean?", error.detailed_message
422
+ assert_equal "confused_human", error.corrections.first
349
423
  end
350
424
  end
351
425
 
@@ -552,6 +626,15 @@ class InverseHasManyTests < ActiveRecord::TestCase
552
626
  end
553
627
  end
554
628
 
629
+ def test_inverse_should_be_set_on_composite_primary_key_child
630
+ author = Cpk::Author.new(name: "John")
631
+ book = author.books.build(id: [nil, 1], title: "The Rails Way")
632
+ Cpk::Order.new(book: book, status: "paid")
633
+ author.save!
634
+
635
+ assert_predicate book.association(:order), :loaded?
636
+ end
637
+
555
638
  def test_raise_record_not_found_error_when_invalid_ids_are_passed
556
639
  # delete all interest records to ensure that hard coded invalid_id(s)
557
640
  # are indeed invalid.
@@ -571,8 +654,8 @@ class InverseHasManyTests < ActiveRecord::TestCase
571
654
 
572
655
  exception = assert_raise(ActiveRecord::RecordNotFound) { human.interests.load.find() }
573
656
 
574
- assert_equal exception.model, "Interest"
575
- assert_equal exception.primary_key, "id"
657
+ assert_equal "Interest", exception.model
658
+ assert_equal "id", exception.primary_key
576
659
  end
577
660
 
578
661
  def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
@@ -619,6 +702,18 @@ class InverseHasManyTests < ActiveRecord::TestCase
619
702
  comment.body = "OMG"
620
703
  assert_equal comment.body, comment.children.first.parent.body
621
704
  end
705
+
706
+ def test_changing_the_association_id_makes_the_inversed_association_target_stale
707
+ post1 = Post.first
708
+ post2 = Post.second
709
+ comment = post1.comments.first
710
+
711
+ assert_same post1, comment.post
712
+
713
+ comment.update!(post_id: post2.id)
714
+
715
+ assert_equal post2, comment.post
716
+ end
622
717
  end
623
718
 
624
719
  class InverseBelongsToTests < ActiveRecord::TestCase
@@ -688,7 +783,7 @@ class InverseBelongsToTests < ActiveRecord::TestCase
688
783
  end
689
784
 
690
785
  def test_with_has_many_inversing_should_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
691
- with_has_many_inversing do
786
+ with_has_many_inversing(Interest) do
692
787
  interest = interests(:trainspotting)
693
788
  human = interest.human
694
789
  assert_not_nil human.interests
@@ -703,7 +798,7 @@ class InverseBelongsToTests < ActiveRecord::TestCase
703
798
  end
704
799
 
705
800
  def test_with_has_many_inversing_should_have_single_record_when_setting_record_through_attribute_in_build_method
706
- with_has_many_inversing do
801
+ with_has_many_inversing(Interest) do
707
802
  human = Human.create!
708
803
  human.interests.build(
709
804
  human: human
@@ -715,14 +810,14 @@ class InverseBelongsToTests < ActiveRecord::TestCase
715
810
  end
716
811
 
717
812
  def test_with_has_many_inversing_does_not_trigger_association_callbacks_on_set_when_the_inverse_is_a_has_many
718
- with_has_many_inversing do
813
+ with_has_many_inversing(Interest) do
719
814
  human = interests(:trainspotting).human_with_callbacks
720
815
  assert_not_predicate human, :add_callback_called?
721
816
  end
722
817
  end
723
818
 
724
- def test_with_hash_many_inversing_does_not_add_duplicate_associated_objects
725
- with_has_many_inversing do
819
+ def test_with_has_many_inversing_does_not_add_duplicate_associated_objects
820
+ with_has_many_inversing(Interest) do
726
821
  human = Human.new
727
822
  interest = Interest.new(human: human)
728
823
  human.interests << interest
@@ -730,6 +825,50 @@ class InverseBelongsToTests < ActiveRecord::TestCase
730
825
  end
731
826
  end
732
827
 
828
+ def test_with_has_many_inversing_does_not_add_unsaved_duplicate_records_when_collection_is_loaded
829
+ with_has_many_inversing(Interest) do
830
+ human = Human.create!
831
+ human.interests.load
832
+ interest = Interest.new(human: human)
833
+ human.interests << interest
834
+ assert_equal 1, human.interests.size
835
+ end
836
+ end
837
+
838
+ def test_with_has_many_inversing_does_not_add_saved_duplicate_records_when_collection_is_loaded
839
+ with_has_many_inversing(Interest) do
840
+ human = Human.create!
841
+ human.interests.load
842
+ interest = Interest.create!(human: human)
843
+ human.interests << interest
844
+ assert_equal 1, human.interests.size
845
+ end
846
+ end
847
+
848
+ def test_recursive_model_has_many_inversing
849
+ with_has_many_inversing do
850
+ main = Branch.create!
851
+ feature = main.branches.create!
852
+ topic = feature.branches.build
853
+
854
+ assert_equal(main, topic.branch.branch)
855
+ end
856
+ end
857
+
858
+ def test_recursive_inverse_on_recursive_model_has_many_inversing
859
+ with_has_many_inversing do
860
+ main = BrokenBranch.create!
861
+ feature = main.branches.create!
862
+ topic = feature.branches.build
863
+
864
+ error = assert_raises(ActiveRecord::InverseOfAssociationRecursiveError) do
865
+ topic.branch.branch
866
+ end
867
+
868
+ assert_equal("Inverse association branch (:branch in BrokenBranch) is recursive.", error.message)
869
+ end
870
+ end
871
+
733
872
  def test_unscope_does_not_set_inverse_when_incorrect
734
873
  interest = interests(:trainspotting)
735
874
  human = interest.human
@@ -761,22 +900,20 @@ class InverseBelongsToTests < ActiveRecord::TestCase
761
900
  end
762
901
 
763
902
  def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
764
- assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.first.puzzled_human }
903
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.first.confused_human }
765
904
  end
766
905
 
767
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
768
- def test_trying_to_use_inverses_that_dont_exist_should_have_suggestions_for_fix
769
- error = assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) {
770
- Face.first.puzzled_human
771
- }
906
+ def test_trying_to_use_inverses_that_dont_exist_should_have_suggestions_for_fix
907
+ error = assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) {
908
+ Face.first.confused_human
909
+ }
772
910
 
773
- assert_match "Did you mean?", error.message
774
- assert_equal "confused_face", error.corrections.first
775
- end
911
+ assert_match "Did you mean?", error.detailed_message
912
+ assert_equal "confused_face", error.corrections.first
776
913
  end
777
914
 
778
915
  def test_building_has_many_parent_association_inverses_one_record
779
- with_has_many_inversing do
916
+ with_has_many_inversing(Interest) do
780
917
  interest = Interest.new
781
918
  interest.build_human
782
919
  assert_equal 1, interest.human.interests.size
@@ -878,7 +1015,7 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase
878
1015
  end
879
1016
 
880
1017
  def test_with_has_many_inversing_should_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
881
- with_has_many_inversing do
1018
+ with_has_many_inversing(Interest) do
882
1019
  interest = interests(:llama_wrangling)
883
1020
  human = interest.polymorphic_human
884
1021
  assert_not_nil human.polymorphic_interests
@@ -893,7 +1030,7 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase
893
1030
  end
894
1031
 
895
1032
  def test_with_has_many_inversing_does_not_trigger_association_callbacks_on_set_when_the_inverse_is_a_has_many
896
- with_has_many_inversing do
1033
+ with_has_many_inversing(Interest) do
897
1034
  human = interests(:llama_wrangling).polymorphic_human_with_callbacks
898
1035
  assert_not_predicate human, :add_callback_called?
899
1036
  end
@@ -45,9 +45,9 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
45
45
  def test_has_many_distinct_through_count
46
46
  author = authors(:mary)
47
47
  assert_not_predicate authors(:mary).unique_categorized_posts, :loaded?
48
- assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
49
- assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
50
- assert_queries(1) { assert_equal 0, author.unique_categorized_posts.where(title: nil).count(:title) }
48
+ assert_queries_count(1) { assert_equal 1, author.unique_categorized_posts.count }
49
+ assert_queries_count(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
50
+ assert_queries_count(1) { assert_equal 0, author.unique_categorized_posts.where(title: nil).count(:title) }
51
51
  assert_not_predicate authors(:mary).unique_categorized_posts, :loaded?
52
52
  end
53
53
 
@@ -341,13 +341,11 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
341
341
  assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
342
342
  end
343
343
 
344
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
345
- def test_exceptions_have_suggestions_for_fix
346
- error = assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) {
347
- authors(:david).nothings
348
- }
349
- assert_match "Did you mean?", error.message
350
- end
344
+ def test_exceptions_have_suggestions_for_fix
345
+ error = assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) {
346
+ authors(:david).nothings
347
+ }
348
+ assert_match "Did you mean?", error.detailed_message
351
349
  end
352
350
 
353
351
  def test_has_many_through_join_model_with_conditions
@@ -476,7 +474,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
476
474
  new_tag = Tag.new(name: "new")
477
475
 
478
476
  saved_post.tags << new_tag
479
- assert new_tag.persisted? # consistent with habtm!
477
+ assert_predicate new_tag, :persisted? # consistent with habtm!
480
478
  assert_predicate saved_post, :persisted?
481
479
  assert_includes saved_post.tags, new_tag
482
480
 
@@ -730,7 +728,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
730
728
 
731
729
  david.reload
732
730
  assert_not_predicate david.categories, :loaded?
733
- assert_queries(1) do
731
+ assert_queries_count(1) do
734
732
  assert_includes david.categories, category
735
733
  end
736
734
  assert_not_predicate david.categories, :loaded?
@@ -774,6 +772,13 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
774
772
  assert_equal("Can't join 'Post' to association named 'nonexistent_relation'; perhaps you misspelled it?", includes_and_eager_load_error.message)
775
773
  end
776
774
 
775
+ def test_eager_association_with_scope_with_string_joins
776
+ skip "DB2-specific: string-based joins in eager association scope are unsupported in this scenario" if (defined?(ibm_db?) && ibm_db?) || current_adapter?(:IBM_DBAdapter)
777
+ assert_nothing_raised do
778
+ Post.joins(:very_special_comment_with_string_joins).first
779
+ end
780
+ end
781
+
777
782
  private
778
783
  # create dynamic Post models to allow different dependency options
779
784
  def find_post_with_dependency(post_id, association, association_name, dependency)
@@ -9,6 +9,9 @@ require "models/essay"
9
9
  require "models/category"
10
10
  require "models/categorization"
11
11
  require "models/person"
12
+ require "models/friendship"
13
+ require "models/reference"
14
+ require "models/job"
12
15
 
13
16
  class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
14
17
  fixtures :authors, :author_addresses, :essays, :posts, :comments, :ratings, :categorizations, :people
@@ -22,8 +25,8 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
22
25
  end
23
26
 
24
27
  def test_construct_finder_sql_applies_aliases_tables_on_association_conditions
25
- result = Author.left_outer_joins(:thinking_posts, :welcome_posts).to_a
26
- assert_equal authors(:david), result.first
28
+ result = Author.left_outer_joins(:thinking_posts, :welcome_posts).first
29
+ assert_equal authors(:david), result
27
30
  end
28
31
 
29
32
  def test_construct_finder_sql_does_not_table_name_collide_on_duplicate_associations
@@ -94,7 +97,7 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
94
97
 
95
98
  def test_join_conditions_added_to_join_clause
96
99
  queries = capture_sql { Author.left_outer_joins(:essays).to_a }
97
- assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|\:a1)/i.match?(sql) }
100
+ assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|:a1)/i.match?(sql) }
98
101
  assert queries.none? { |sql| /WHERE/i.match?(sql) }
99
102
  end
100
103
 
@@ -120,4 +123,12 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
120
123
 
121
124
  assert_equal [author], Author.where(id: author).left_outer_joins(:special_categorizations)
122
125
  end
126
+
127
+ def test_left_outer_joins_includes_all_nested_associations
128
+ sql, = capture_sql { Friendship.left_outer_joins(:friend_favorite_reference_job, :follower_favorite_reference_job).to_a }
129
+
130
+ # DB2 doesn't quote composite identifiers in JOIN conditions
131
+ assert_match %r(friendships\.friend_id)i, sql
132
+ assert_match %r(friendships\.follower_id)i, sql
133
+ end
123
134
  end