ibm_db 5.6.1-arm64-darwin-24

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 (753) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +299 -0
  3. data/LICENSE +55 -0
  4. data/MANIFEST +14 -0
  5. data/ParameterizedQueries README +39 -0
  6. data/README +210 -0
  7. data/ext/Makefile +270 -0
  8. data/ext/Makefile.nt32 +181 -0
  9. data/ext/Makefile.nt32.191 +212 -0
  10. data/ext/extconf.rb +320 -0
  11. data/ext/gil_release_version.h +3 -0
  12. data/ext/ibm_db.bundle +0 -0
  13. data/ext/ibm_db.c +11865 -0
  14. data/ext/ibm_db.o +0 -0
  15. data/ext/mkmf.log +98 -0
  16. data/ext/ruby_ibm_db.h +241 -0
  17. data/ext/ruby_ibm_db_cli.c +867 -0
  18. data/ext/ruby_ibm_db_cli.h +508 -0
  19. data/ext/ruby_ibm_db_cli.o +0 -0
  20. data/ext/unicode_support_version.h +3 -0
  21. data/init.rb +42 -0
  22. data/lib/IBM_DB.rb +27 -0
  23. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4407 -0
  24. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1965 -0
  25. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -0
  26. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
  27. data/lib/ibm_db.bundle +0 -0
  28. data/test/active_record/connection_adapters/fake_adapter.rb +52 -0
  29. data/test/activejob/destroy_association_async_test.rb +305 -0
  30. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  31. data/test/activejob/helper.rb +15 -0
  32. data/test/assets/example.log +1 -0
  33. data/test/assets/flowers.jpg +0 -0
  34. data/test/assets/schema_dump_5_1.yml +345 -0
  35. data/test/assets/test.txt +1 -0
  36. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  37. data/test/cases/adapter_test.rb +565 -0
  38. data/test/cases/adapters/mysql2/active_schema_test.rb +203 -0
  39. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  40. data/test/cases/adapters/mysql2/bind_parameter_test.rb +52 -0
  41. data/test/cases/adapters/mysql2/boolean_test.rb +102 -0
  42. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +65 -0
  43. data/test/cases/adapters/mysql2/charset_collation_test.rb +57 -0
  44. data/test/cases/adapters/mysql2/connection_test.rb +208 -0
  45. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  46. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +49 -0
  47. data/test/cases/adapters/mysql2/enum_test.rb +47 -0
  48. data/test/cases/adapters/mysql2/explain_test.rb +23 -0
  49. data/test/cases/adapters/mysql2/json_test.rb +24 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  51. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +238 -0
  52. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  53. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  54. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  55. data/test/cases/adapters/mysql2/schema_migrations_test.rb +64 -0
  56. data/test/cases/adapters/mysql2/schema_test.rb +128 -0
  57. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  58. data/test/cases/adapters/mysql2/sp_test.rb +38 -0
  59. data/test/cases/adapters/mysql2/sql_types_test.rb +16 -0
  60. data/test/cases/adapters/mysql2/table_options_test.rb +125 -0
  61. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  62. data/test/cases/adapters/mysql2/unsigned_type_test.rb +68 -0
  63. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  64. data/test/cases/adapters/postgresql/active_schema_test.rb +113 -0
  65. data/test/cases/adapters/postgresql/array_test.rb +394 -0
  66. data/test/cases/adapters/postgresql/bit_string_test.rb +84 -0
  67. data/test/cases/adapters/postgresql/bytea_test.rb +135 -0
  68. data/test/cases/adapters/postgresql/case_insensitive_test.rb +27 -0
  69. data/test/cases/adapters/postgresql/change_schema_test.rb +40 -0
  70. data/test/cases/adapters/postgresql/cidr_test.rb +27 -0
  71. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  72. data/test/cases/adapters/postgresql/collation_test.rb +55 -0
  73. data/test/cases/adapters/postgresql/composite_test.rb +134 -0
  74. data/test/cases/adapters/postgresql/connection_test.rb +245 -0
  75. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  76. data/test/cases/adapters/postgresql/datatype_test.rb +89 -0
  77. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  78. data/test/cases/adapters/postgresql/domain_test.rb +49 -0
  79. data/test/cases/adapters/postgresql/enum_test.rb +93 -0
  80. data/test/cases/adapters/postgresql/explain_test.rb +22 -0
  81. data/test/cases/adapters/postgresql/extension_migration_test.rb +64 -0
  82. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  83. data/test/cases/adapters/postgresql/full_text_test.rb +46 -0
  84. data/test/cases/adapters/postgresql/geometric_test.rb +372 -0
  85. data/test/cases/adapters/postgresql/hstore_test.rb +390 -0
  86. data/test/cases/adapters/postgresql/infinity_test.rb +108 -0
  87. data/test/cases/adapters/postgresql/integer_test.rb +27 -0
  88. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  89. data/test/cases/adapters/postgresql/json_test.rb +52 -0
  90. data/test/cases/adapters/postgresql/ltree_test.rb +51 -0
  91. data/test/cases/adapters/postgresql/money_test.rb +127 -0
  92. data/test/cases/adapters/postgresql/network_test.rb +102 -0
  93. data/test/cases/adapters/postgresql/numbers_test.rb +51 -0
  94. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  95. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  96. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  97. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +447 -0
  98. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  99. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  100. data/test/cases/adapters/postgresql/quoting_test.rb +50 -0
  101. data/test/cases/adapters/postgresql/range_test.rb +457 -0
  102. data/test/cases/adapters/postgresql/referential_integrity_test.rb +112 -0
  103. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -0
  104. data/test/cases/adapters/postgresql/schema_authorization_test.rb +110 -0
  105. data/test/cases/adapters/postgresql/schema_test.rb +713 -0
  106. data/test/cases/adapters/postgresql/serial_test.rb +156 -0
  107. data/test/cases/adapters/postgresql/statement_pool_test.rb +61 -0
  108. data/test/cases/adapters/postgresql/timestamp_test.rb +92 -0
  109. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  110. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  111. data/test/cases/adapters/postgresql/type_lookup_test.rb +35 -0
  112. data/test/cases/adapters/postgresql/utils_test.rb +64 -0
  113. data/test/cases/adapters/postgresql/uuid_test.rb +411 -0
  114. data/test/cases/adapters/postgresql/xml_test.rb +50 -0
  115. data/test/cases/adapters/sqlite3/collation_test.rb +64 -0
  116. data/test/cases/adapters/sqlite3/copy_table_test.rb +101 -0
  117. data/test/cases/adapters/sqlite3/explain_test.rb +23 -0
  118. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  119. data/test/cases/adapters/sqlite3/quoting_test.rb +79 -0
  120. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  121. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +628 -0
  122. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  123. data/test/cases/adapters/sqlite3/statement_pool_test.rb +21 -0
  124. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  125. data/test/cases/aggregations_test.rb +170 -0
  126. data/test/cases/annotate_test.rb +46 -0
  127. data/test/cases/ar_schema_test.rb +213 -0
  128. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  129. data/test/cases/arel/attributes/math_test.rb +83 -0
  130. data/test/cases/arel/attributes_test.rb +27 -0
  131. data/test/cases/arel/collectors/bind_test.rb +40 -0
  132. data/test/cases/arel/collectors/composite_test.rb +47 -0
  133. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  134. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  135. data/test/cases/arel/crud_test.rb +65 -0
  136. data/test/cases/arel/delete_manager_test.rb +53 -0
  137. data/test/cases/arel/factory_methods_test.rb +46 -0
  138. data/test/cases/arel/helper.rb +45 -0
  139. data/test/cases/arel/insert_manager_test.rb +241 -0
  140. data/test/cases/arel/nodes/and_test.rb +30 -0
  141. data/test/cases/arel/nodes/as_test.rb +36 -0
  142. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  143. data/test/cases/arel/nodes/bin_test.rb +35 -0
  144. data/test/cases/arel/nodes/binary_test.rb +29 -0
  145. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  146. data/test/cases/arel/nodes/case_test.rb +96 -0
  147. data/test/cases/arel/nodes/casted_test.rb +18 -0
  148. data/test/cases/arel/nodes/comment_test.rb +22 -0
  149. data/test/cases/arel/nodes/count_test.rb +35 -0
  150. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  151. data/test/cases/arel/nodes/descending_test.rb +46 -0
  152. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  153. data/test/cases/arel/nodes/equality_test.rb +62 -0
  154. data/test/cases/arel/nodes/extract_test.rb +43 -0
  155. data/test/cases/arel/nodes/false_test.rb +21 -0
  156. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  157. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  158. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  159. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  160. data/test/cases/arel/nodes/node_test.rb +22 -0
  161. data/test/cases/arel/nodes/not_test.rb +31 -0
  162. data/test/cases/arel/nodes/or_test.rb +36 -0
  163. data/test/cases/arel/nodes/over_test.rb +69 -0
  164. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  165. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  166. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  167. data/test/cases/arel/nodes/sum_test.rb +35 -0
  168. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  169. data/test/cases/arel/nodes/true_test.rb +21 -0
  170. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  171. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  172. data/test/cases/arel/nodes/window_test.rb +81 -0
  173. data/test/cases/arel/nodes_test.rb +34 -0
  174. data/test/cases/arel/select_manager_test.rb +1238 -0
  175. data/test/cases/arel/support/fake_record.rb +135 -0
  176. data/test/cases/arel/table_test.rb +216 -0
  177. data/test/cases/arel/update_manager_test.rb +126 -0
  178. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  179. data/test/cases/arel/visitors/dot_test.rb +90 -0
  180. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  181. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  182. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  183. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  184. data/test/cases/associations/association_scope_test.rb +16 -0
  185. data/test/cases/associations/belongs_to_associations_test.rb +1493 -0
  186. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +43 -0
  187. data/test/cases/associations/callbacks_test.rb +208 -0
  188. data/test/cases/associations/cascaded_eager_loading_test.rb +245 -0
  189. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +156 -0
  190. data/test/cases/associations/eager_load_nested_include_test.rb +127 -0
  191. data/test/cases/associations/eager_singularization_test.rb +148 -0
  192. data/test/cases/associations/eager_test.rb +1658 -0
  193. data/test/cases/associations/extension_test.rb +93 -0
  194. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1025 -0
  195. data/test/cases/associations/has_many_associations_test.rb +3074 -0
  196. data/test/cases/associations/has_many_through_associations_test.rb +1580 -0
  197. data/test/cases/associations/has_one_associations_test.rb +872 -0
  198. data/test/cases/associations/has_one_through_associations_test.rb +429 -0
  199. data/test/cases/associations/inner_join_association_test.rb +215 -0
  200. data/test/cases/associations/inverse_associations_test.rb +941 -0
  201. data/test/cases/associations/join_model_test.rb +787 -0
  202. data/test/cases/associations/left_outer_join_association_test.rb +123 -0
  203. data/test/cases/associations/nested_through_associations_test.rb +636 -0
  204. data/test/cases/associations/required_test.rb +127 -0
  205. data/test/cases/associations_test.rb +516 -0
  206. data/test/cases/attribute_decorators_test.rb +126 -0
  207. data/test/cases/attribute_methods/read_test.rb +60 -0
  208. data/test/cases/attribute_methods_test.rb +1124 -0
  209. data/test/cases/attribute_set_test.rb +270 -0
  210. data/test/cases/attribute_test.rb +246 -0
  211. data/test/cases/attributes_test.rb +371 -0
  212. data/test/cases/autosave_association_test.rb +1953 -0
  213. data/test/cases/base_prevent_writes_test.rb +229 -0
  214. data/test/cases/base_test.rb +1770 -0
  215. data/test/cases/batches_test.rb +695 -0
  216. data/test/cases/binary_test.rb +39 -0
  217. data/test/cases/bind_parameter_test.rb +283 -0
  218. data/test/cases/boolean_test.rb +52 -0
  219. data/test/cases/cache_key_test.rb +131 -0
  220. data/test/cases/calculations_test.rb +1361 -0
  221. data/test/cases/callbacks_test.rb +503 -0
  222. data/test/cases/clone_test.rb +45 -0
  223. data/test/cases/coders/json_test.rb +17 -0
  224. data/test/cases/coders/yaml_column_test.rb +66 -0
  225. data/test/cases/collection_cache_key_test.rb +272 -0
  226. data/test/cases/column_alias_test.rb +19 -0
  227. data/test/cases/column_definition_test.rb +34 -0
  228. data/test/cases/comment_test.rb +204 -0
  229. data/test/cases/connection_adapters/adapter_leasing_test.rb +60 -0
  230. data/test/cases/connection_adapters/connection_handler_test.rb +467 -0
  231. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  232. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  233. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  234. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  235. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  236. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  237. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  238. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +436 -0
  239. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +81 -0
  240. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  241. data/test/cases/connection_adapters/schema_cache_test.rb +294 -0
  242. data/test/cases/connection_adapters/type_lookup_test.rb +119 -0
  243. data/test/cases/connection_management_test.rb +114 -0
  244. data/test/cases/connection_pool_test.rb +754 -0
  245. data/test/cases/connection_specification/resolver_test.rb +131 -0
  246. data/test/cases/core_test.rb +136 -0
  247. data/test/cases/counter_cache_test.rb +368 -0
  248. data/test/cases/custom_locking_test.rb +19 -0
  249. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  250. data/test/cases/database_configurations/resolver_test.rb +150 -0
  251. data/test/cases/database_configurations_test.rb +145 -0
  252. data/test/cases/database_selector_test.rb +296 -0
  253. data/test/cases/database_statements_test.rb +36 -0
  254. data/test/cases/date_test.rb +36 -0
  255. data/test/cases/date_time_precision_test.rb +129 -0
  256. data/test/cases/date_time_test.rb +76 -0
  257. data/test/cases/defaults_test.rb +254 -0
  258. data/test/cases/delegated_type_test.rb +57 -0
  259. data/test/cases/dirty_test.rb +959 -0
  260. data/test/cases/disconnected_test.rb +30 -0
  261. data/test/cases/dup_test.rb +184 -0
  262. data/test/cases/enum_test.rb +823 -0
  263. data/test/cases/errors_test.rb +16 -0
  264. data/test/cases/explain_subscriber_test.rb +66 -0
  265. data/test/cases/explain_test.rb +79 -0
  266. data/test/cases/filter_attributes_test.rb +153 -0
  267. data/test/cases/finder_respond_to_test.rb +60 -0
  268. data/test/cases/finder_test.rb +1676 -0
  269. data/test/cases/fixture_set/file_test.rb +152 -0
  270. data/test/cases/fixtures_test.rb +1645 -0
  271. data/test/cases/forbidden_attributes_protection_test.rb +130 -0
  272. data/test/cases/habtm_destroy_order_test.rb +61 -0
  273. data/test/cases/helper.rb +233 -0
  274. data/test/cases/hot_compatibility_test.rb +143 -0
  275. data/test/cases/i18n_test.rb +46 -0
  276. data/test/cases/inheritance_test.rb +671 -0
  277. data/test/cases/insert_all_test.rb +489 -0
  278. data/test/cases/instrumentation_test.rb +101 -0
  279. data/test/cases/integration_test.rb +243 -0
  280. data/test/cases/invalid_connection_test.rb +26 -0
  281. data/test/cases/invertible_migration_test.rb +527 -0
  282. data/test/cases/json_attribute_test.rb +35 -0
  283. data/test/cases/json_serialization_test.rb +310 -0
  284. data/test/cases/json_shared_test_cases.rb +290 -0
  285. data/test/cases/locking_test.rb +787 -0
  286. data/test/cases/log_subscriber_test.rb +267 -0
  287. data/test/cases/marshal_serialization_test.rb +39 -0
  288. data/test/cases/migration/change_schema_test.rb +504 -0
  289. data/test/cases/migration/change_table_test.rb +364 -0
  290. data/test/cases/migration/check_constraint_test.rb +162 -0
  291. data/test/cases/migration/column_attributes_test.rb +186 -0
  292. data/test/cases/migration/column_positioning_test.rb +68 -0
  293. data/test/cases/migration/columns_test.rb +326 -0
  294. data/test/cases/migration/command_recorder_test.rb +437 -0
  295. data/test/cases/migration/compatibility_test.rb +673 -0
  296. data/test/cases/migration/create_join_table_test.rb +167 -0
  297. data/test/cases/migration/foreign_key_test.rb +581 -0
  298. data/test/cases/migration/helper.rb +40 -0
  299. data/test/cases/migration/index_test.rb +267 -0
  300. data/test/cases/migration/logger_test.rb +39 -0
  301. data/test/cases/migration/pending_migrations_test.rb +106 -0
  302. data/test/cases/migration/references_foreign_key_test.rb +235 -0
  303. data/test/cases/migration/references_index_test.rb +120 -0
  304. data/test/cases/migration/references_statements_test.rb +137 -0
  305. data/test/cases/migration/rename_table_test.rb +116 -0
  306. data/test/cases/migration_test.rb +1525 -0
  307. data/test/cases/migrator_test.rb +527 -0
  308. data/test/cases/mixin_test.rb +64 -0
  309. data/test/cases/modules_test.rb +174 -0
  310. data/test/cases/multi_db_migrator_test.rb +223 -0
  311. data/test/cases/multiparameter_attributes_test.rb +399 -0
  312. data/test/cases/multiple_db_test.rb +116 -0
  313. data/test/cases/nested_attributes_test.rb +1119 -0
  314. data/test/cases/nested_attributes_with_callbacks_test.rb +146 -0
  315. data/test/cases/null_relation_test.rb +84 -0
  316. data/test/cases/numeric_data_test.rb +93 -0
  317. data/test/cases/persistence_test.rb +1093 -0
  318. data/test/cases/pooled_connections_test.rb +73 -0
  319. data/test/cases/prepared_statement_status_test.rb +48 -0
  320. data/test/cases/primary_keys_test.rb +482 -0
  321. data/test/cases/query_cache_test.rb +915 -0
  322. data/test/cases/quoting_test.rb +303 -0
  323. data/test/cases/readonly_test.rb +120 -0
  324. data/test/cases/reaper_test.rb +199 -0
  325. data/test/cases/reflection_test.rb +520 -0
  326. data/test/cases/relation/delegation_test.rb +76 -0
  327. data/test/cases/relation/delete_all_test.rb +117 -0
  328. data/test/cases/relation/merging_test.rb +434 -0
  329. data/test/cases/relation/mutation_test.rb +145 -0
  330. data/test/cases/relation/or_test.rb +192 -0
  331. data/test/cases/relation/predicate_builder_test.rb +31 -0
  332. data/test/cases/relation/record_fetch_warning_test.rb +42 -0
  333. data/test/cases/relation/select_test.rb +67 -0
  334. data/test/cases/relation/update_all_test.rb +317 -0
  335. data/test/cases/relation/where_chain_test.rb +141 -0
  336. data/test/cases/relation/where_clause_test.rb +257 -0
  337. data/test/cases/relation/where_test.rb +429 -0
  338. data/test/cases/relation_test.rb +482 -0
  339. data/test/cases/relations_test.rb +2251 -0
  340. data/test/cases/reload_models_test.rb +26 -0
  341. data/test/cases/reserved_word_test.rb +141 -0
  342. data/test/cases/result_test.rb +141 -0
  343. data/test/cases/sanitize_test.rb +192 -0
  344. data/test/cases/schema_dumper_test.rb +550 -0
  345. data/test/cases/schema_loading_test.rb +53 -0
  346. data/test/cases/scoping/default_scoping_test.rb +569 -0
  347. data/test/cases/scoping/named_scoping_test.rb +649 -0
  348. data/test/cases/scoping/relation_scoping_test.rb +522 -0
  349. data/test/cases/secure_token_test.rb +47 -0
  350. data/test/cases/serialization_test.rb +106 -0
  351. data/test/cases/serialized_attribute_test.rb +455 -0
  352. data/test/cases/signed_id_test.rb +168 -0
  353. data/test/cases/statement_cache_test.rb +153 -0
  354. data/test/cases/statement_invalid_test.rb +42 -0
  355. data/test/cases/store_test.rb +320 -0
  356. data/test/cases/strict_loading_test.rb +473 -0
  357. data/test/cases/suppressor_test.rb +77 -0
  358. data/test/cases/tasks/database_tasks_test.rb +1526 -0
  359. data/test/cases/tasks/mysql_rake_test.rb +417 -0
  360. data/test/cases/tasks/postgresql_rake_test.rb +534 -0
  361. data/test/cases/tasks/sqlite_rake_test.rb +267 -0
  362. data/test/cases/test_case.rb +142 -0
  363. data/test/cases/test_databases_test.rb +79 -0
  364. data/test/cases/test_fixtures_test.rb +96 -0
  365. data/test/cases/time_precision_test.rb +125 -0
  366. data/test/cases/timestamp_test.rb +504 -0
  367. data/test/cases/touch_later_test.rb +123 -0
  368. data/test/cases/transaction_callbacks_test.rb +772 -0
  369. data/test/cases/transaction_isolation_test.rb +106 -0
  370. data/test/cases/transactions_test.rb +1285 -0
  371. data/test/cases/type/adapter_specific_registry_test.rb +145 -0
  372. data/test/cases/type/date_time_test.rb +16 -0
  373. data/test/cases/type/integer_test.rb +29 -0
  374. data/test/cases/type/string_test.rb +24 -0
  375. data/test/cases/type/time_test.rb +28 -0
  376. data/test/cases/type/type_map_test.rb +178 -0
  377. data/test/cases/type/unsigned_integer_test.rb +19 -0
  378. data/test/cases/type_test.rb +41 -0
  379. data/test/cases/types_test.rb +26 -0
  380. data/test/cases/unconnected_test.rb +46 -0
  381. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  382. data/test/cases/validations/absence_validation_test.rb +75 -0
  383. data/test/cases/validations/association_validation_test.rb +99 -0
  384. data/test/cases/validations/i18n_generate_message_validation_test.rb +102 -0
  385. data/test/cases/validations/i18n_validation_test.rb +87 -0
  386. data/test/cases/validations/length_validation_test.rb +80 -0
  387. data/test/cases/validations/numericality_validation_test.rb +181 -0
  388. data/test/cases/validations/presence_validation_test.rb +105 -0
  389. data/test/cases/validations/uniqueness_validation_test.rb +618 -0
  390. data/test/cases/validations_repair_helper.rb +21 -0
  391. data/test/cases/validations_test.rb +229 -0
  392. data/test/cases/view_test.rb +222 -0
  393. data/test/cases/yaml_serialization_test.rb +166 -0
  394. data/test/config.example.yml +97 -0
  395. data/test/config.rb +7 -0
  396. data/test/config.yml +220 -0
  397. data/test/connections/native_ibm_db/connection.rb +44 -0
  398. data/test/fixtures/accounts.yml +29 -0
  399. data/test/fixtures/admin/accounts.yml +2 -0
  400. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  401. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  402. data/test/fixtures/admin/users.yml +10 -0
  403. data/test/fixtures/all/admin +1 -0
  404. data/test/fixtures/all/developers.yml +0 -0
  405. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  406. data/test/fixtures/all/people.yml +0 -0
  407. data/test/fixtures/all/tasks.yml +0 -0
  408. data/test/fixtures/author_addresses.yml +11 -0
  409. data/test/fixtures/author_favorites.yml +4 -0
  410. data/test/fixtures/authors.yml +17 -0
  411. data/test/fixtures/bad_posts.yml +9 -0
  412. data/test/fixtures/binaries.yml +137 -0
  413. data/test/fixtures/books.yml +38 -0
  414. data/test/fixtures/bulbs.yml +5 -0
  415. data/test/fixtures/cars.yml +9 -0
  416. data/test/fixtures/categories/special_categories.yml +9 -0
  417. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  418. data/test/fixtures/categories.yml +19 -0
  419. data/test/fixtures/categories_ordered.yml +7 -0
  420. data/test/fixtures/categories_posts.yml +34 -0
  421. data/test/fixtures/categorizations.yml +23 -0
  422. data/test/fixtures/citations.yml +5 -0
  423. data/test/fixtures/clubs.yml +8 -0
  424. data/test/fixtures/collections.yml +3 -0
  425. data/test/fixtures/colleges.yml +3 -0
  426. data/test/fixtures/comments.yml +72 -0
  427. data/test/fixtures/companies.yml +72 -0
  428. data/test/fixtures/computers.yml +12 -0
  429. data/test/fixtures/content.yml +3 -0
  430. data/test/fixtures/content_positions.yml +3 -0
  431. data/test/fixtures/courses.yml +8 -0
  432. data/test/fixtures/customers.yml +35 -0
  433. data/test/fixtures/dashboards.yml +6 -0
  434. data/test/fixtures/dead_parrots.yml +5 -0
  435. data/test/fixtures/developers.yml +22 -0
  436. data/test/fixtures/developers_projects.yml +17 -0
  437. data/test/fixtures/dog_lovers.yml +7 -0
  438. data/test/fixtures/dogs.yml +4 -0
  439. data/test/fixtures/doubloons.yml +3 -0
  440. data/test/fixtures/edges.yml +5 -0
  441. data/test/fixtures/entrants.yml +14 -0
  442. data/test/fixtures/essays.yml +16 -0
  443. data/test/fixtures/faces.yml +11 -0
  444. data/test/fixtures/fk_test_has_fk.yml +3 -0
  445. data/test/fixtures/fk_test_has_pk.yml +2 -0
  446. data/test/fixtures/friendships.yml +4 -0
  447. data/test/fixtures/funny_jokes.yml +10 -0
  448. data/test/fixtures/humans.yml +5 -0
  449. data/test/fixtures/interests.yml +33 -0
  450. data/test/fixtures/items.yml +3 -0
  451. data/test/fixtures/jobs.yml +7 -0
  452. data/test/fixtures/legacy_things.yml +3 -0
  453. data/test/fixtures/live_parrots.yml +4 -0
  454. data/test/fixtures/mateys.yml +4 -0
  455. data/test/fixtures/member_details.yml +8 -0
  456. data/test/fixtures/member_types.yml +6 -0
  457. data/test/fixtures/members.yml +11 -0
  458. data/test/fixtures/memberships.yml +41 -0
  459. data/test/fixtures/men.yml +5 -0
  460. data/test/fixtures/minimalistics.yml +5 -0
  461. data/test/fixtures/minivans.yml +5 -0
  462. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  463. data/test/fixtures/mixins.yml +29 -0
  464. data/test/fixtures/movies.yml +7 -0
  465. data/test/fixtures/naked/yml/accounts.yml +1 -0
  466. data/test/fixtures/naked/yml/companies.yml +1 -0
  467. data/test/fixtures/naked/yml/courses.yml +1 -0
  468. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  469. data/test/fixtures/naked/yml/parrots.yml +3 -0
  470. data/test/fixtures/naked/yml/trees.yml +3 -0
  471. data/test/fixtures/nodes.yml +29 -0
  472. data/test/fixtures/organizations.yml +5 -0
  473. data/test/fixtures/other_books.yml +26 -0
  474. data/test/fixtures/other_comments.yml +6 -0
  475. data/test/fixtures/other_dogs.yml +2 -0
  476. data/test/fixtures/other_posts.yml +8 -0
  477. data/test/fixtures/other_topics.yml +42 -0
  478. data/test/fixtures/owners.yml +9 -0
  479. data/test/fixtures/parrots.yml +33 -0
  480. data/test/fixtures/parrots_pirates.yml +7 -0
  481. data/test/fixtures/people.yml +24 -0
  482. data/test/fixtures/peoples_treasures.yml +3 -0
  483. data/test/fixtures/pets.yml +19 -0
  484. data/test/fixtures/pirates.yml +15 -0
  485. data/test/fixtures/posts.yml +88 -0
  486. data/test/fixtures/price_estimates.yml +16 -0
  487. data/test/fixtures/products.yml +4 -0
  488. data/test/fixtures/projects.yml +7 -0
  489. data/test/fixtures/randomly_named_a9.yml +7 -0
  490. data/test/fixtures/ratings.yml +14 -0
  491. data/test/fixtures/readers.yml +17 -0
  492. data/test/fixtures/references.yml +17 -0
  493. data/test/fixtures/reserved_words/distinct.yml +5 -0
  494. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  495. data/test/fixtures/reserved_words/group.yml +14 -0
  496. data/test/fixtures/reserved_words/select.yml +8 -0
  497. data/test/fixtures/reserved_words/values.yml +7 -0
  498. data/test/fixtures/ships.yml +6 -0
  499. data/test/fixtures/speedometers.yml +8 -0
  500. data/test/fixtures/sponsors.yml +15 -0
  501. data/test/fixtures/strict_zines.yml +2 -0
  502. data/test/fixtures/string_key_objects.yml +7 -0
  503. data/test/fixtures/subscribers.yml +11 -0
  504. data/test/fixtures/subscriptions.yml +12 -0
  505. data/test/fixtures/taggings.yml +78 -0
  506. data/test/fixtures/tags.yml +11 -0
  507. data/test/fixtures/tasks.yml +7 -0
  508. data/test/fixtures/teapots.yml +3 -0
  509. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  510. data/test/fixtures/to_be_linked/users.yml +10 -0
  511. data/test/fixtures/topics.yml +49 -0
  512. data/test/fixtures/toys.yml +14 -0
  513. data/test/fixtures/traffic_lights.yml +10 -0
  514. data/test/fixtures/treasures.yml +10 -0
  515. data/test/fixtures/trees.yml +3 -0
  516. data/test/fixtures/uuid_children.yml +3 -0
  517. data/test/fixtures/uuid_parents.yml +2 -0
  518. data/test/fixtures/variants.yml +4 -0
  519. data/test/fixtures/vegetables.yml +20 -0
  520. data/test/fixtures/vertices.yml +4 -0
  521. data/test/fixtures/warehouse-things.yml +3 -0
  522. data/test/fixtures/warehouse_things.yml +3 -0
  523. data/test/fixtures/zines.yml +5 -0
  524. data/test/ibm_db_test.rb +25 -0
  525. data/test/migrations/10_urban/9_add_expressions.rb +13 -0
  526. data/test/migrations/decimal/1_give_me_big_numbers.rb +17 -0
  527. data/test/migrations/magic/1_currencies_have_symbols.rb +13 -0
  528. data/test/migrations/missing/1000_people_have_middle_names.rb +11 -0
  529. data/test/migrations/missing/1_people_have_last_names.rb +11 -0
  530. data/test/migrations/missing/3_we_need_reminders.rb +14 -0
  531. data/test/migrations/missing/4_innocent_jointable.rb +14 -0
  532. data/test/migrations/rename/1_we_need_things.rb +13 -0
  533. data/test/migrations/rename/2_rename_things.rb +11 -0
  534. data/test/migrations/to_copy/1_people_have_hobbies.rb +11 -0
  535. data/test/migrations/to_copy/2_people_have_descriptions.rb +11 -0
  536. data/test/migrations/to_copy2/1_create_articles.rb +9 -0
  537. data/test/migrations/to_copy2/2_create_comments.rb +9 -0
  538. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +11 -0
  539. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +11 -0
  540. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +11 -0
  541. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +9 -0
  542. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +9 -0
  543. data/test/migrations/valid/1_valid_people_have_last_names.rb +11 -0
  544. data/test/migrations/valid/2_we_need_reminders.rb +14 -0
  545. data/test/migrations/valid/3_innocent_jointable.rb +14 -0
  546. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +11 -0
  547. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +14 -0
  548. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +14 -0
  549. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +11 -0
  550. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +14 -0
  551. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +14 -0
  552. data/test/migrations/version_check/20131219224947_migration_version_check.rb +10 -0
  553. data/test/models/account.rb +46 -0
  554. data/test/models/admin/account.rb +5 -0
  555. data/test/models/admin/randomly_named_c1.rb +9 -0
  556. data/test/models/admin/user.rb +48 -0
  557. data/test/models/admin.rb +7 -0
  558. data/test/models/aircraft.rb +7 -0
  559. data/test/models/arunit2_model.rb +5 -0
  560. data/test/models/author.rb +260 -0
  561. data/test/models/auto_id.rb +6 -0
  562. data/test/models/autoloadable/extra_firm.rb +4 -0
  563. data/test/models/binary.rb +4 -0
  564. data/test/models/binary_field.rb +6 -0
  565. data/test/models/bird.rb +24 -0
  566. data/test/models/book.rb +33 -0
  567. data/test/models/book_destroy_async.rb +24 -0
  568. data/test/models/boolean.rb +7 -0
  569. data/test/models/bulb.rb +61 -0
  570. data/test/models/cake_designer.rb +5 -0
  571. data/test/models/car.rb +36 -0
  572. data/test/models/carrier.rb +4 -0
  573. data/test/models/cart.rb +5 -0
  574. data/test/models/cat.rb +12 -0
  575. data/test/models/categorization.rb +21 -0
  576. data/test/models/category.rb +47 -0
  577. data/test/models/chef.rb +10 -0
  578. data/test/models/citation.rb +7 -0
  579. data/test/models/club.rb +28 -0
  580. data/test/models/college.rb +12 -0
  581. data/test/models/column.rb +5 -0
  582. data/test/models/column_name.rb +5 -0
  583. data/test/models/comment.rb +98 -0
  584. data/test/models/company.rb +226 -0
  585. data/test/models/company_in_module.rb +99 -0
  586. data/test/models/computer.rb +5 -0
  587. data/test/models/contact.rb +43 -0
  588. data/test/models/content.rb +42 -0
  589. data/test/models/contract.rb +38 -0
  590. data/test/models/country.rb +5 -0
  591. data/test/models/course.rb +8 -0
  592. data/test/models/customer.rb +85 -0
  593. data/test/models/customer_carrier.rb +16 -0
  594. data/test/models/dashboard.rb +5 -0
  595. data/test/models/default.rb +4 -0
  596. data/test/models/department.rb +6 -0
  597. data/test/models/destroy_async_parent.rb +15 -0
  598. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  599. data/test/models/developer.rb +341 -0
  600. data/test/models/dl_keyed_belongs_to.rb +13 -0
  601. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  602. data/test/models/dl_keyed_has_many.rb +5 -0
  603. data/test/models/dl_keyed_has_many_through.rb +5 -0
  604. data/test/models/dl_keyed_has_one.rb +5 -0
  605. data/test/models/dl_keyed_join.rb +10 -0
  606. data/test/models/dog.rb +7 -0
  607. data/test/models/dog_lover.rb +7 -0
  608. data/test/models/doubloon.rb +14 -0
  609. data/test/models/drink_designer.rb +20 -0
  610. data/test/models/edge.rb +7 -0
  611. data/test/models/electron.rb +7 -0
  612. data/test/models/engine.rb +5 -0
  613. data/test/models/entrant.rb +5 -0
  614. data/test/models/entry.rb +5 -0
  615. data/test/models/essay.rb +8 -0
  616. data/test/models/essay_destroy_async.rb +12 -0
  617. data/test/models/event.rb +5 -0
  618. data/test/models/eye.rb +39 -0
  619. data/test/models/face.rb +17 -0
  620. data/test/models/family.rb +6 -0
  621. data/test/models/family_tree.rb +6 -0
  622. data/test/models/friendship.rb +8 -0
  623. data/test/models/frog.rb +8 -0
  624. data/test/models/guid.rb +4 -0
  625. data/test/models/guitar.rb +6 -0
  626. data/test/models/hotel.rb +13 -0
  627. data/test/models/human.rb +39 -0
  628. data/test/models/image.rb +5 -0
  629. data/test/models/interest.rb +16 -0
  630. data/test/models/invoice.rb +6 -0
  631. data/test/models/item.rb +9 -0
  632. data/test/models/job.rb +9 -0
  633. data/test/models/joke.rb +9 -0
  634. data/test/models/keyboard.rb +5 -0
  635. data/test/models/legacy_thing.rb +5 -0
  636. data/test/models/lesson.rb +13 -0
  637. data/test/models/line_item.rb +5 -0
  638. data/test/models/liquid.rb +6 -0
  639. data/test/models/man.rb +11 -0
  640. data/test/models/matey.rb +6 -0
  641. data/test/models/measurement.rb +4 -0
  642. data/test/models/member.rb +45 -0
  643. data/test/models/member_detail.rb +11 -0
  644. data/test/models/member_type.rb +5 -0
  645. data/test/models/membership.rb +38 -0
  646. data/test/models/mentor.rb +5 -0
  647. data/test/models/message.rb +5 -0
  648. data/test/models/minimalistic.rb +4 -0
  649. data/test/models/minivan.rb +10 -0
  650. data/test/models/mixed_case_monkey.rb +5 -0
  651. data/test/models/mocktail_designer.rb +2 -0
  652. data/test/models/molecule.rb +8 -0
  653. data/test/models/mouse.rb +6 -0
  654. data/test/models/movie.rb +7 -0
  655. data/test/models/node.rb +7 -0
  656. data/test/models/non_primary_key.rb +4 -0
  657. data/test/models/notification.rb +5 -0
  658. data/test/models/numeric_data.rb +12 -0
  659. data/test/models/order.rb +6 -0
  660. data/test/models/organization.rb +16 -0
  661. data/test/models/other_dog.rb +7 -0
  662. data/test/models/owner.rb +39 -0
  663. data/test/models/parrot.rb +36 -0
  664. data/test/models/person.rb +147 -0
  665. data/test/models/personal_legacy_thing.rb +6 -0
  666. data/test/models/pet.rb +20 -0
  667. data/test/models/pet_treasure.rb +8 -0
  668. data/test/models/pirate.rb +116 -0
  669. data/test/models/possession.rb +5 -0
  670. data/test/models/post.rb +371 -0
  671. data/test/models/price_estimate.rb +14 -0
  672. data/test/models/professor.rb +7 -0
  673. data/test/models/project.rb +42 -0
  674. data/test/models/publisher/article.rb +6 -0
  675. data/test/models/publisher/magazine.rb +5 -0
  676. data/test/models/publisher.rb +4 -0
  677. data/test/models/randomly_named_c1.rb +5 -0
  678. data/test/models/rating.rb +8 -0
  679. data/test/models/reader.rb +25 -0
  680. data/test/models/recipe.rb +5 -0
  681. data/test/models/record.rb +4 -0
  682. data/test/models/reference.rb +25 -0
  683. data/test/models/reply.rb +79 -0
  684. data/test/models/room.rb +6 -0
  685. data/test/models/section.rb +6 -0
  686. data/test/models/seminar.rb +6 -0
  687. data/test/models/session.rb +6 -0
  688. data/test/models/ship.rb +42 -0
  689. data/test/models/ship_part.rb +10 -0
  690. data/test/models/shop.rb +19 -0
  691. data/test/models/shop_account.rb +8 -0
  692. data/test/models/speedometer.rb +8 -0
  693. data/test/models/sponsor.rb +10 -0
  694. data/test/models/squeak.rb +6 -0
  695. data/test/models/strict_zine.rb +7 -0
  696. data/test/models/string_key_object.rb +5 -0
  697. data/test/models/student.rb +6 -0
  698. data/test/models/subject.rb +16 -0
  699. data/test/models/subscriber.rb +10 -0
  700. data/test/models/subscription.rb +8 -0
  701. data/test/models/tag.rb +16 -0
  702. data/test/models/tagging.rb +20 -0
  703. data/test/models/task.rb +7 -0
  704. data/test/models/topic.rb +153 -0
  705. data/test/models/toy.rb +10 -0
  706. data/test/models/traffic_light.rb +6 -0
  707. data/test/models/treasure.rb +16 -0
  708. data/test/models/treaty.rb +5 -0
  709. data/test/models/tree.rb +5 -0
  710. data/test/models/tuning_peg.rb +6 -0
  711. data/test/models/tyre.rb +13 -0
  712. data/test/models/user.rb +22 -0
  713. data/test/models/uuid_child.rb +5 -0
  714. data/test/models/uuid_item.rb +8 -0
  715. data/test/models/uuid_parent.rb +5 -0
  716. data/test/models/vegetables.rb +33 -0
  717. data/test/models/vehicle.rb +7 -0
  718. data/test/models/vertex.rb +11 -0
  719. data/test/models/warehouse_thing.rb +7 -0
  720. data/test/models/wheel.rb +5 -0
  721. data/test/models/without_table.rb +5 -0
  722. data/test/models/zine.rb +5 -0
  723. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  724. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  725. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  726. data/test/schema/mysql2_specific_schema.rb +82 -0
  727. data/test/schema/oracle_specific_schema.rb +38 -0
  728. data/test/schema/postgresql_specific_schema.rb +125 -0
  729. data/test/schema/schema.rb +1237 -0
  730. data/test/schema/schema.rb.original +1057 -0
  731. data/test/schema/sqlite_specific_schema.rb +11 -0
  732. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  733. data/test/support/config.rb +43 -0
  734. data/test/support/connection.rb +29 -0
  735. data/test/support/connection_helper.rb +16 -0
  736. data/test/support/ddl_helper.rb +10 -0
  737. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  738. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  739. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  740. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  741. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  742. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  743. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  744. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  745. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  746. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  747. data/test/support/schema_dumping_helper.rb +22 -0
  748. data/test/support/stubs/strong_parameters.rb +40 -0
  749. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  750. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  751. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  752. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  753. metadata +876 -0
@@ -0,0 +1,1493 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/developer"
5
+ require "models/project"
6
+ require "models/company"
7
+ require "models/topic"
8
+ require "models/reply"
9
+ require "models/computer"
10
+ require "models/post"
11
+ require "models/author"
12
+ require "models/tag"
13
+ require "models/tagging"
14
+ require "models/comment"
15
+ require "models/sponsor"
16
+ require "models/member"
17
+ require "models/essay"
18
+ require "models/toy"
19
+ require "models/invoice"
20
+ require "models/line_item"
21
+ require "models/column"
22
+ require "models/record"
23
+ require "models/admin"
24
+ require "models/admin/user"
25
+ require "models/ship"
26
+ require "models/treasure"
27
+ require "models/parrot"
28
+ require "models/book"
29
+ require "models/citation"
30
+
31
+ class BelongsToAssociationsTest < ActiveRecord::TestCase
32
+ fixtures :accounts, :companies, :developers, :projects, :topics,
33
+ :developers_projects, :computers, :authors, :author_addresses,
34
+ :essays, :posts, :tags, :taggings, :comments, :sponsors, :members
35
+
36
+ def test_belongs_to
37
+ client = Client.find(3)
38
+ first_firm = companies(:first_firm)
39
+ assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
40
+ assert_equal first_firm, client.firm
41
+ assert_equal first_firm.name, client.firm.name
42
+ end
43
+ end
44
+
45
+ def test_where_with_custom_primary_key
46
+ assert_equal [authors(:david)], Author.where(owned_essay: essays(:david_modest_proposal))
47
+ end
48
+
49
+ def test_find_by_with_custom_primary_key
50
+ assert_equal authors(:david), Author.find_by(owned_essay: essays(:david_modest_proposal))
51
+ end
52
+
53
+ def test_where_on_polymorphic_association_with_nil
54
+ assert_equal comments(:greetings), Comment.where(author: nil).first
55
+ assert_equal comments(:greetings), Comment.where(author: [nil]).first
56
+ end
57
+
58
+ def test_where_on_polymorphic_association_with_empty_array
59
+ assert_empty Comment.where(author: [])
60
+ end
61
+
62
+ def test_assigning_belongs_to_on_destroyed_object
63
+ client = Client.create!(name: "Client")
64
+ client.destroy!
65
+ assert_raise(FrozenError) { client.firm = nil }
66
+ assert_raise(FrozenError) { client.firm = Firm.new(name: "Firm") }
67
+ end
68
+
69
+ def test_eager_loading_wont_mutate_owner_record
70
+ client = Client.eager_load(:firm_with_basic_id).first
71
+ assert_not_predicate client, :firm_id_came_from_user?
72
+
73
+ client = Client.preload(:firm_with_basic_id).first
74
+ assert_not_predicate client, :firm_id_came_from_user?
75
+ end
76
+
77
+ def test_missing_attribute_error_is_raised_when_no_foreign_key_attribute
78
+ assert_raises(ActiveModel::MissingAttributeError) { Client.select(:id).first.firm }
79
+ end
80
+
81
+ def test_belongs_to_does_not_use_order_by
82
+ sql_log = capture_sql { Client.find(3).firm }
83
+ assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
84
+ end
85
+
86
+ def test_belongs_to_with_primary_key
87
+ client = Client.create(name: "Primary key client", firm_name: companies(:first_firm).name)
88
+ assert_equal companies(:first_firm).name, client.firm_with_primary_key.name
89
+ end
90
+
91
+ def test_belongs_to_with_primary_key_joins_on_correct_column
92
+ sql = Client.joins(:firm_with_primary_key).to_sql
93
+ if current_adapter?(:Mysql2Adapter)
94
+ assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
95
+ 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
+ else
101
+ assert_no_match(/firm_with_primary_keys_companies\.id/, sql)
102
+ assert_match(/firm_with_primary_keys_companies\.name/, sql)
103
+ end
104
+ end
105
+
106
+ def test_optional_relation_can_be_set_per_model
107
+ model1 = Class.new(ActiveRecord::Base) do
108
+ self.table_name = "accounts"
109
+ self.belongs_to_required_by_default = false
110
+
111
+ belongs_to :company
112
+
113
+ def self.name
114
+ "FirstModel"
115
+ end
116
+ end.new
117
+
118
+ model2 = Class.new(ActiveRecord::Base) do
119
+ self.table_name = "accounts"
120
+ self.belongs_to_required_by_default = true
121
+
122
+ belongs_to :company
123
+
124
+ def self.name
125
+ "SecondModel"
126
+ end
127
+ end.new
128
+
129
+ assert_predicate model1, :valid?
130
+ assert_not_predicate model2, :valid?
131
+ end
132
+
133
+ def test_optional_relation
134
+ original_value = ActiveRecord::Base.belongs_to_required_by_default
135
+ ActiveRecord::Base.belongs_to_required_by_default = true
136
+
137
+ model = Class.new(ActiveRecord::Base) do
138
+ self.table_name = "accounts"
139
+ def self.name; "Temp"; end
140
+ belongs_to :company, optional: true
141
+ end
142
+
143
+ account = model.new
144
+ assert_predicate account, :valid?
145
+ ensure
146
+ ActiveRecord::Base.belongs_to_required_by_default = original_value
147
+ end
148
+
149
+ def test_not_optional_relation
150
+ original_value = ActiveRecord::Base.belongs_to_required_by_default
151
+ ActiveRecord::Base.belongs_to_required_by_default = true
152
+
153
+ model = Class.new(ActiveRecord::Base) do
154
+ self.table_name = "accounts"
155
+ def self.name; "Temp"; end
156
+ belongs_to :company, optional: false
157
+ end
158
+
159
+ account = model.new
160
+ assert_not_predicate account, :valid?
161
+ assert_equal [{ error: :blank }], account.errors.details[:company]
162
+ ensure
163
+ ActiveRecord::Base.belongs_to_required_by_default = original_value
164
+ end
165
+
166
+ def test_required_belongs_to_config
167
+ original_value = ActiveRecord::Base.belongs_to_required_by_default
168
+ ActiveRecord::Base.belongs_to_required_by_default = true
169
+
170
+ model = Class.new(ActiveRecord::Base) do
171
+ self.table_name = "accounts"
172
+ def self.name; "Temp"; end
173
+ belongs_to :company
174
+ end
175
+
176
+ account = model.new
177
+ assert_not_predicate account, :valid?
178
+ assert_equal [{ error: :blank }], account.errors.details[:company]
179
+ ensure
180
+ ActiveRecord::Base.belongs_to_required_by_default = original_value
181
+ end
182
+
183
+ def test_default
184
+ david = developers(:david)
185
+ jamis = developers(:jamis)
186
+
187
+ model = Class.new(ActiveRecord::Base) do
188
+ self.table_name = "ships"
189
+ def self.name; "Temp"; end
190
+ belongs_to :developer, default: -> { david }
191
+ end
192
+
193
+ ship = model.create!
194
+ assert_equal david, ship.developer
195
+
196
+ ship = model.create!(developer: jamis)
197
+ assert_equal jamis, ship.developer
198
+
199
+ ship.update!(developer: nil)
200
+ assert_equal david, ship.developer
201
+ end
202
+
203
+ def test_default_with_lambda
204
+ model = Class.new(ActiveRecord::Base) do
205
+ self.table_name = "ships"
206
+ def self.name; "Temp"; end
207
+ belongs_to :developer, default: -> { default_developer }
208
+
209
+ def default_developer
210
+ Developer.first
211
+ end
212
+ end
213
+
214
+ ship = model.create!
215
+ assert_equal developers(:david), ship.developer
216
+
217
+ ship = model.create!(developer: developers(:jamis))
218
+ assert_equal developers(:jamis), ship.developer
219
+ end
220
+
221
+ def test_default_scope_on_relations_is_not_cached
222
+ counter = 0
223
+
224
+ comments = Class.new(ActiveRecord::Base) {
225
+ self.table_name = "comments"
226
+ self.inheritance_column = "not_there"
227
+
228
+ posts = Class.new(ActiveRecord::Base) {
229
+ self.table_name = "posts"
230
+ self.inheritance_column = "not_there"
231
+
232
+ default_scope -> {
233
+ counter += 1
234
+ where("id = :inc", inc: counter)
235
+ }
236
+
237
+ has_many :comments, anonymous_class: comments
238
+ }
239
+ belongs_to :post, anonymous_class: posts, inverse_of: false
240
+ }
241
+
242
+ assert_equal 0, counter
243
+ comment = comments.first
244
+ assert_equal 0, counter
245
+ sql = capture_sql { comment.post }
246
+ comment.reload
247
+ assert_not_equal sql, capture_sql { comment.post }
248
+ end
249
+
250
+ def test_proxy_assignment
251
+ account = Account.find(1)
252
+ assert_nothing_raised { account.firm = account.firm }
253
+ end
254
+
255
+ def test_type_mismatch
256
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
257
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
258
+ end
259
+
260
+ def test_raises_type_mismatch_with_namespaced_class
261
+ assert_nil defined?(Region), "This test requires that there is no top-level Region class"
262
+
263
+ ActiveRecord::Base.connection.instance_eval do
264
+ create_table(:admin_regions, force: true) { |t| t.string :name }
265
+ add_column :admin_users, :region_id, :integer
266
+ end
267
+ Admin.const_set "RegionalUser", Class.new(Admin::User) { belongs_to(:region) }
268
+ Admin.const_set "Region", Class.new(ActiveRecord::Base)
269
+
270
+ e = assert_raise(ActiveRecord::AssociationTypeMismatch) {
271
+ Admin::RegionalUser.new(region: "wrong value")
272
+ }
273
+ assert_match(/^Region\([^)]+\) expected, got "wrong value" which is an instance of String\([^)]+\)$/, e.message)
274
+ ensure
275
+ Admin.send :remove_const, "Region" if Admin.const_defined?("Region")
276
+ Admin.send :remove_const, "RegionalUser" if Admin.const_defined?("RegionalUser")
277
+
278
+ ActiveRecord::Base.connection.instance_eval do
279
+ remove_column :admin_users, :region_id if column_exists?(:admin_users, :region_id)
280
+ drop_table :admin_regions, if_exists: true
281
+ end
282
+
283
+ Admin::User.reset_column_information
284
+ end
285
+
286
+ def test_natural_assignment
287
+ apple = Firm.create("name" => "Apple")
288
+ citibank = Account.create("credit_limit" => 10)
289
+ citibank.firm = apple
290
+ assert_equal apple.id, citibank.firm_id
291
+ end
292
+
293
+ def test_id_assignment
294
+ apple = Firm.create("name" => "Apple")
295
+ citibank = Account.create("credit_limit" => 10)
296
+ citibank.firm_id = apple
297
+ assert_nil citibank.firm_id
298
+ end
299
+
300
+ def test_natural_assignment_with_primary_key
301
+ apple = Firm.create("name" => "Apple")
302
+ citibank = Client.create("name" => "Primary key client")
303
+ citibank.firm_with_primary_key = apple
304
+ assert_equal apple.name, citibank.firm_name
305
+ end
306
+
307
+ def test_eager_loading_with_primary_key
308
+ Firm.create("name" => "Apple")
309
+ Client.create("name" => "Citibank", :firm_name => "Apple")
310
+ citibank_result = Client.all.merge!(where: { name: "Citibank" }, includes: :firm_with_primary_key).first
311
+ assert_predicate citibank_result.association(:firm_with_primary_key), :loaded?
312
+ end
313
+
314
+ def test_eager_loading_with_primary_key_as_symbol
315
+ Firm.create("name" => "Apple")
316
+ Client.create("name" => "Citibank", :firm_name => "Apple")
317
+ citibank_result = Client.all.merge!(where: { name: "Citibank" }, includes: :firm_with_primary_key_symbols).first
318
+ assert_predicate citibank_result.association(:firm_with_primary_key_symbols), :loaded?
319
+ end
320
+
321
+ def test_creating_the_belonging_object
322
+ citibank = Account.create("credit_limit" => 10)
323
+ apple = citibank.create_firm("name" => "Apple")
324
+ assert_equal apple, citibank.firm
325
+ citibank.save
326
+ citibank.reload
327
+ assert_equal apple, citibank.firm
328
+ end
329
+
330
+ def test_creating_the_belonging_object_from_new_record
331
+ citibank = Account.new("credit_limit" => 10)
332
+ apple = citibank.create_firm("name" => "Apple")
333
+ assert_equal apple, citibank.firm
334
+ citibank.save
335
+ citibank.reload
336
+ assert_equal apple, citibank.firm
337
+ end
338
+
339
+ def test_creating_the_belonging_object_with_primary_key
340
+ client = Client.create(name: "Primary key client")
341
+ apple = client.create_firm_with_primary_key("name" => "Apple")
342
+ assert_equal apple, client.firm_with_primary_key
343
+ client.save
344
+ client.reload
345
+ assert_equal apple, client.firm_with_primary_key
346
+ end
347
+
348
+ def test_building_the_belonging_object
349
+ citibank = Account.create("credit_limit" => 10)
350
+ apple = citibank.build_firm("name" => "Apple")
351
+ citibank.save
352
+ assert_equal apple.id, citibank.firm_id
353
+ end
354
+
355
+ def test_building_the_belonging_object_with_implicit_sti_base_class
356
+ account = Account.new
357
+ company = account.build_firm
358
+ assert_kind_of Company, company, "Expected #{company.class} to be a Company"
359
+ end
360
+
361
+ def test_building_the_belonging_object_with_explicit_sti_base_class
362
+ account = Account.new
363
+ company = account.build_firm(type: "Company")
364
+ assert_kind_of Company, company, "Expected #{company.class} to be a Company"
365
+ end
366
+
367
+ def test_building_the_belonging_object_with_sti_subclass
368
+ account = Account.new
369
+ company = account.build_firm(type: "Firm")
370
+ assert_kind_of Firm, company, "Expected #{company.class} to be a Firm"
371
+ end
372
+
373
+ def test_building_the_belonging_object_with_an_invalid_type
374
+ account = Account.new
375
+ assert_raise(ActiveRecord::SubclassNotFound) { account.build_firm(type: "InvalidType") }
376
+ end
377
+
378
+ def test_building_the_belonging_object_with_an_unrelated_type
379
+ account = Account.new
380
+ assert_raise(ActiveRecord::SubclassNotFound) { account.build_firm(type: "Account") }
381
+ end
382
+
383
+ def test_building_the_belonging_object_with_primary_key
384
+ client = Client.create(name: "Primary key client")
385
+ apple = client.build_firm_with_primary_key("name" => "Apple")
386
+ client.save
387
+ assert_equal apple.name, client.firm_name
388
+ end
389
+
390
+ def test_create!
391
+ client = Client.create!(name: "Jimmy")
392
+ account = client.create_account!(credit_limit: 10)
393
+ assert_equal account, client.account
394
+ assert_predicate account, :persisted?
395
+ client.save
396
+ client.reload
397
+ assert_equal account, client.account
398
+ end
399
+
400
+ def test_failing_create!
401
+ client = Client.create!(name: "Jimmy")
402
+ assert_raise(ActiveRecord::RecordInvalid) { client.create_account! }
403
+ assert_not_nil client.account
404
+ assert_predicate client.account, :new_record?
405
+ end
406
+
407
+ def test_reloading_the_belonging_object
408
+ odegy_account = accounts(:odegy_account)
409
+
410
+ assert_equal "Odegy", odegy_account.firm.name
411
+ Company.where(id: odegy_account.firm_id).update_all(name: "ODEGY")
412
+ assert_equal "Odegy", odegy_account.firm.name
413
+
414
+ assert_equal "ODEGY", odegy_account.reload_firm.name
415
+ end
416
+
417
+ def test_reload_the_belonging_object_with_query_cache
418
+ odegy_account_id = accounts(:odegy_account).id
419
+
420
+ connection = ActiveRecord::Base.connection
421
+ connection.enable_query_cache!
422
+ connection.clear_query_cache
423
+
424
+ # Populate the cache with a query
425
+ odegy_account = Account.find(odegy_account_id)
426
+
427
+ # Populate the cache with a second query
428
+ odegy_account.firm
429
+
430
+ assert_equal 2, connection.query_cache.size
431
+
432
+ # Clear the cache and fetch the firm again, populating the cache with a query
433
+ assert_queries(1) { odegy_account.reload_firm }
434
+
435
+ # This query is not cached anymore, so it should make a real SQL query
436
+ assert_queries(1) { Account.find(odegy_account_id) }
437
+ ensure
438
+ ActiveRecord::Base.connection.disable_query_cache!
439
+ end
440
+
441
+ def test_natural_assignment_to_nil
442
+ client = Client.find(3)
443
+ client.firm = nil
444
+ client.save
445
+ client.association(:firm).reload
446
+ assert_nil client.firm
447
+ assert_nil client.client_of
448
+ end
449
+
450
+ def test_natural_assignment_to_nil_with_primary_key
451
+ client = Client.create(name: "Primary key client", firm_name: companies(:first_firm).name)
452
+ client.firm_with_primary_key = nil
453
+ client.save
454
+ client.association(:firm_with_primary_key).reload
455
+ assert_nil client.firm_with_primary_key
456
+ assert_nil client.client_of
457
+ end
458
+
459
+ def test_with_different_class_name
460
+ assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
461
+ assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
462
+ end
463
+
464
+ def test_with_condition
465
+ assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
466
+ assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
467
+ end
468
+
469
+ def test_polymorphic_association_class
470
+ sponsor = Sponsor.new
471
+ assert_nil sponsor.association(:sponsorable).klass
472
+ sponsor.association(:sponsorable).reload
473
+ assert_nil sponsor.sponsorable
474
+
475
+ sponsor.sponsorable_type = "" # the column doesn't have to be declared NOT NULL
476
+ assert_nil sponsor.association(:sponsorable).klass
477
+ sponsor.association(:sponsorable).reload
478
+ assert_nil sponsor.sponsorable
479
+
480
+ sponsor.sponsorable = Member.new name: "Bert"
481
+ assert_equal Member, sponsor.association(:sponsorable).klass
482
+ end
483
+
484
+ def test_with_polymorphic_and_condition
485
+ sponsor = Sponsor.create
486
+ member = Member.create name: "Bert"
487
+
488
+ sponsor.sponsorable = member
489
+ sponsor.save!
490
+
491
+ assert_equal member, sponsor.sponsorable
492
+ assert_nil sponsor.sponsorable_with_conditions
493
+
494
+ sponsor = Sponsor.preload(:sponsorable, :sponsorable_with_conditions).last
495
+
496
+ assert_equal member, sponsor.sponsorable
497
+ assert_nil sponsor.sponsorable_with_conditions
498
+ end
499
+
500
+ def test_with_select
501
+ assert_equal 1, Post.find(2).author_with_select.attributes.size
502
+ assert_equal 1, Post.includes(:author_with_select).find(2).author_with_select.attributes.size
503
+ end
504
+
505
+ def test_custom_attribute_with_select
506
+ assert_equal 2, Company.find(2).firm_with_select.attributes.size
507
+ assert_equal 2, Company.includes(:firm_with_select).find(2).firm_with_select.attributes.size
508
+ end
509
+
510
+ def test_belongs_to_without_counter_cache_option
511
+ # Ship has a conventionally named `treasures_count` column, but the counter_cache
512
+ # option is not given on the association.
513
+ ship = Ship.create(name: "Countless")
514
+
515
+ assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed unless counter_cache is given on the relation" do
516
+ treasure = Treasure.new(name: "Gold", ship: ship)
517
+ treasure.save
518
+ end
519
+
520
+ assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed unless counter_cache is given on the relation" do
521
+ treasure = ship.treasures.first
522
+ treasure.destroy
523
+ end
524
+ end
525
+
526
+ def test_belongs_to_counter
527
+ debate = Topic.create("title" => "debate")
528
+ assert_equal 0, debate.read_attribute("replies_count"), "No replies yet"
529
+
530
+ trash = debate.replies.create("title" => "blah!", "content" => "world around!")
531
+ assert_equal 1, Topic.find(debate.id).read_attribute("replies_count"), "First reply created"
532
+
533
+ trash.destroy
534
+ assert_equal 0, Topic.find(debate.id).read_attribute("replies_count"), "First reply deleted"
535
+ end
536
+
537
+ def test_belongs_to_counter_with_assigning_nil
538
+ topic = Topic.create!(title: "debate")
539
+ reply = Reply.create!(title: "blah!", content: "world around!", topic: topic)
540
+
541
+ assert_equal topic.id, reply.parent_id
542
+ assert_equal 1, topic.reload.replies.size
543
+
544
+ reply.topic = nil
545
+ reply.reload
546
+
547
+ assert_equal topic.id, reply.parent_id
548
+ assert_equal 1, topic.reload.replies.size
549
+
550
+ reply.topic = nil
551
+ reply.save!
552
+
553
+ assert_equal 0, topic.reload.replies.size
554
+ end
555
+
556
+ def test_belongs_to_counter_with_assigning_new_object
557
+ topic = Topic.create!(title: "debate")
558
+ reply = Reply.create!(title: "blah!", content: "world around!", topic: topic)
559
+
560
+ assert_equal topic.id, reply.parent_id
561
+ assert_equal 1, topic.reload.replies_count
562
+
563
+ topic2 = reply.build_topic(title: "debate2")
564
+ reply.save!
565
+
566
+ assert_not_equal topic.id, reply.parent_id
567
+ assert_equal topic2.id, reply.parent_id
568
+
569
+ assert_equal 0, topic.reload.replies_count
570
+ assert_equal 1, topic2.reload.replies_count
571
+ end
572
+
573
+ def test_belongs_to_with_primary_key_counter
574
+ debate = Topic.create("title" => "debate")
575
+ debate2 = Topic.create("title" => "debate2")
576
+ reply = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate2")
577
+
578
+ assert_equal 0, debate.reload.replies_count
579
+ assert_equal 1, debate2.reload.replies_count
580
+
581
+ reply.parent_title = "debate"
582
+ reply.save!
583
+
584
+ assert_equal 1, debate.reload.replies_count
585
+ assert_equal 0, debate2.reload.replies_count
586
+
587
+ assert_no_queries do
588
+ reply.topic_with_primary_key = debate
589
+ end
590
+
591
+ assert_equal 1, debate.reload.replies_count
592
+ assert_equal 0, debate2.reload.replies_count
593
+
594
+ reply.topic_with_primary_key = debate2
595
+ reply.save!
596
+
597
+ assert_equal 0, debate.reload.replies_count
598
+ assert_equal 1, debate2.reload.replies_count
599
+
600
+ reply.topic_with_primary_key = nil
601
+ reply.save!
602
+
603
+ assert_equal 0, debate.reload.replies_count
604
+ assert_equal 0, debate2.reload.replies_count
605
+ end
606
+
607
+ def test_belongs_to_counter_with_reassigning
608
+ topic1 = Topic.create("title" => "t1")
609
+ topic2 = Topic.create("title" => "t2")
610
+ reply1 = Reply.new("title" => "r1", "content" => "r1")
611
+ reply1.topic = topic1
612
+
613
+ assert reply1.save
614
+ assert_equal 1, Topic.find(topic1.id).replies.size
615
+ assert_equal 0, Topic.find(topic2.id).replies.size
616
+
617
+ reply1.topic = Topic.find(topic2.id)
618
+
619
+ assert_no_queries do
620
+ reply1.topic = topic2
621
+ end
622
+
623
+ assert reply1.save
624
+ assert_equal 0, Topic.find(topic1.id).replies.size
625
+ assert_equal 1, Topic.find(topic2.id).replies.size
626
+
627
+ reply1.topic = nil
628
+ reply1.save!
629
+
630
+ assert_equal 0, Topic.find(topic1.id).replies.size
631
+ assert_equal 0, Topic.find(topic2.id).replies.size
632
+
633
+ reply1.topic = topic1
634
+ reply1.save!
635
+
636
+ assert_equal 1, Topic.find(topic1.id).replies.size
637
+ assert_equal 0, Topic.find(topic2.id).replies.size
638
+
639
+ reply1.destroy
640
+
641
+ assert_equal 0, Topic.find(topic1.id).replies.size
642
+ assert_equal 0, Topic.find(topic2.id).replies.size
643
+ end
644
+
645
+ def test_belongs_to_reassign_with_namespaced_models_and_counters
646
+ topic1 = Web::Topic.create("title" => "t1")
647
+ topic2 = Web::Topic.create("title" => "t2")
648
+ reply1 = Web::Reply.new("title" => "r1", "content" => "r1")
649
+ reply1.topic = topic1
650
+
651
+ assert reply1.save
652
+ assert_equal 1, Web::Topic.find(topic1.id).replies.size
653
+ assert_equal 0, Web::Topic.find(topic2.id).replies.size
654
+
655
+ reply1.topic = Web::Topic.find(topic2.id)
656
+
657
+ assert reply1.save
658
+ assert_equal 0, Web::Topic.find(topic1.id).replies.size
659
+ assert_equal 1, Web::Topic.find(topic2.id).replies.size
660
+ end
661
+
662
+ def test_belongs_to_counter_after_save
663
+ topic = Topic.create!(title: "monday night")
664
+
665
+ assert_queries(2) do
666
+ topic.replies.create!(title: "re: monday night", content: "football")
667
+ end
668
+
669
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
670
+
671
+ topic.save!
672
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
673
+ end
674
+
675
+ def test_belongs_to_counter_after_touch
676
+ topic = Topic.create!(title: "topic")
677
+
678
+ assert_equal 0, topic.replies_count
679
+ assert_equal 0, topic.after_touch_called
680
+
681
+ reply = Reply.create!(title: "blah!", content: "world around!", topic_with_primary_key: topic)
682
+
683
+ assert_equal 1, topic.replies_count
684
+ assert_equal 1, topic.after_touch_called
685
+
686
+ reply.destroy!
687
+
688
+ assert_equal 0, topic.replies_count
689
+ assert_equal 2, topic.after_touch_called
690
+ end
691
+
692
+ def test_belongs_to_touch_with_reassigning
693
+ debate = Topic.create!(title: "debate")
694
+ debate2 = Topic.create!(title: "debate2")
695
+ reply = Reply.create!(title: "blah!", content: "world around!", parent_title: "debate2")
696
+
697
+ time = 1.day.ago
698
+
699
+ debate.touch(time: time)
700
+ debate2.touch(time: time)
701
+
702
+ assert_queries(3) do
703
+ reply.parent_title = "debate"
704
+ reply.save!
705
+ end
706
+
707
+ assert_operator debate.reload.updated_at, :>, time
708
+ assert_operator debate2.reload.updated_at, :>, time
709
+
710
+ debate.touch(time: time)
711
+ debate2.touch(time: time)
712
+
713
+ assert_queries(3) do
714
+ reply.topic_with_primary_key = debate2
715
+ reply.save!
716
+ end
717
+
718
+ assert_operator debate.reload.updated_at, :>, time
719
+ assert_operator debate2.reload.updated_at, :>, time
720
+ end
721
+
722
+ def test_belongs_to_with_touch_option_on_touch
723
+ line_item = LineItem.create!
724
+ Invoice.create!(line_items: [line_item])
725
+
726
+ assert_queries(1) { line_item.touch }
727
+ end
728
+
729
+ def test_belongs_to_with_touch_on_multiple_records
730
+ line_item = LineItem.create!(amount: 1)
731
+ line_item2 = LineItem.create!(amount: 2)
732
+ Invoice.create!(line_items: [line_item, line_item2])
733
+
734
+ assert_queries(1) do
735
+ LineItem.transaction do
736
+ line_item.touch
737
+ line_item2.touch
738
+ end
739
+ end
740
+
741
+ assert_queries(2) do
742
+ line_item.touch
743
+ line_item2.touch
744
+ end
745
+ end
746
+
747
+ def test_belongs_to_with_touch_option_on_touch_without_updated_at_attributes
748
+ assert_not LineItem.column_names.include?("updated_at")
749
+
750
+ line_item = LineItem.create!
751
+ invoice = Invoice.create!(line_items: [line_item])
752
+ initial = invoice.updated_at
753
+ travel(1.second) do
754
+ line_item.touch
755
+ end
756
+
757
+ assert_not_equal initial, invoice.reload.updated_at
758
+ end
759
+
760
+ def test_belongs_to_with_touch_option_on_touch_and_removed_parent
761
+ line_item = LineItem.create!
762
+ Invoice.create!(line_items: [line_item])
763
+
764
+ line_item.invoice = nil
765
+
766
+ assert_queries(2) { line_item.touch }
767
+ end
768
+
769
+ def test_belongs_to_with_touch_option_on_update
770
+ line_item = LineItem.create!
771
+ Invoice.create!(line_items: [line_item])
772
+
773
+ assert_queries(2) { line_item.update amount: 10 }
774
+ end
775
+
776
+ def test_belongs_to_with_touch_option_on_empty_update
777
+ line_item = LineItem.create!
778
+ Invoice.create!(line_items: [line_item])
779
+
780
+ assert_no_queries { line_item.save }
781
+ end
782
+
783
+ def test_belongs_to_with_touch_option_on_destroy
784
+ line_item = LineItem.create!
785
+ Invoice.create!(line_items: [line_item])
786
+
787
+ assert_queries(2) { line_item.destroy }
788
+ end
789
+
790
+ def test_belongs_to_with_touch_option_on_destroy_with_destroyed_parent
791
+ line_item = LineItem.create!
792
+ invoice = Invoice.create!(line_items: [line_item])
793
+ invoice.destroy
794
+
795
+ assert_queries(1) { line_item.destroy }
796
+ end
797
+
798
+ def test_belongs_to_with_touch_option_on_touch_and_reassigned_parent
799
+ line_item = LineItem.create!
800
+ Invoice.create!(line_items: [line_item])
801
+
802
+ line_item.invoice = Invoice.create!
803
+
804
+ assert_queries(3) { line_item.touch }
805
+ end
806
+
807
+ def test_belongs_to_counter_after_update
808
+ topic = Topic.create!(title: "37s")
809
+ topic.replies.create!(title: "re: 37s", content: "rails")
810
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
811
+
812
+ topic.update(title: "37signals")
813
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
814
+ end
815
+
816
+ def test_belongs_to_counter_when_update_columns
817
+ topic = Topic.create!(title: "37s")
818
+ topic.replies.create!(title: "re: 37s", content: "rails")
819
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
820
+
821
+ topic.update_columns(content: "rails is wonderful")
822
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
823
+ end
824
+
825
+ def test_assignment_before_child_saved
826
+ final_cut = Client.new("name" => "Final Cut")
827
+ firm = Firm.find(1)
828
+ final_cut.firm = firm
829
+ assert_not_predicate final_cut, :persisted?
830
+ assert final_cut.save
831
+ assert_predicate final_cut, :persisted?
832
+ assert_predicate firm, :persisted?
833
+ assert_equal firm, final_cut.firm
834
+ final_cut.association(:firm).reload
835
+ assert_equal firm, final_cut.firm
836
+ end
837
+
838
+ def test_assignment_before_child_saved_with_primary_key
839
+ final_cut = Client.new("name" => "Final Cut")
840
+ firm = Firm.find(1)
841
+ final_cut.firm_with_primary_key = firm
842
+ assert_not_predicate final_cut, :persisted?
843
+ assert final_cut.save
844
+ assert_predicate final_cut, :persisted?
845
+ assert_predicate firm, :persisted?
846
+ assert_equal firm, final_cut.firm_with_primary_key
847
+ final_cut.association(:firm_with_primary_key).reload
848
+ assert_equal firm, final_cut.firm_with_primary_key
849
+ end
850
+
851
+ def test_new_record_with_foreign_key_but_no_object
852
+ client = Client.new("firm_id" => 1)
853
+ assert_equal Firm.first, client.firm_with_basic_id
854
+ end
855
+
856
+ def test_setting_foreign_key_after_nil_target_loaded
857
+ client = Client.new
858
+ client.firm_with_basic_id
859
+ client.firm_id = 1
860
+
861
+ assert_equal companies(:first_firm), client.firm_with_basic_id
862
+ end
863
+
864
+ def test_polymorphic_setting_foreign_key_after_nil_target_loaded
865
+ sponsor = Sponsor.new
866
+ sponsor.sponsorable
867
+ sponsor.sponsorable_id = 1
868
+ sponsor.sponsorable_type = "Member"
869
+
870
+ assert_equal members(:groucho), sponsor.sponsorable
871
+ end
872
+
873
+ def test_dont_find_target_when_foreign_key_is_null
874
+ tagging = taggings(:thinking_general)
875
+ assert_no_queries { tagging.super_tag }
876
+ end
877
+
878
+ def test_dont_find_target_when_saving_foreign_key_after_stale_association_loaded
879
+ client = Client.create!(name: "Test client", firm_with_basic_id: Firm.find(1))
880
+ client.firm_id = Firm.create!(name: "Test firm").id
881
+ assert_queries(1) { client.save! }
882
+ end
883
+
884
+ def test_field_name_same_as_foreign_key
885
+ computer = Computer.find(1)
886
+ assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
887
+ end
888
+
889
+ def test_counter_cache
890
+ topic = Topic.create title: "Zoom-zoom-zoom"
891
+ assert_equal 0, topic[:replies_count]
892
+
893
+ reply = Reply.create(title: "re: zoom", content: "speedy quick!")
894
+ reply.topic = topic
895
+ reply.save!
896
+
897
+ assert_equal 1, topic.reload[:replies_count]
898
+ assert_equal 1, topic.replies.size
899
+
900
+ topic[:replies_count] = 15
901
+ assert_equal 15, topic.replies.size
902
+ end
903
+
904
+ def test_counter_cache_double_destroy
905
+ topic = Topic.create title: "Zoom-zoom-zoom"
906
+
907
+ 5.times do
908
+ topic.replies.create(title: "re: zoom", content: "speedy quick!")
909
+ end
910
+
911
+ assert_equal 5, topic.reload[:replies_count]
912
+ assert_equal 5, topic.replies.size
913
+
914
+ reply = topic.replies.first
915
+
916
+ reply.destroy
917
+ assert_equal 4, topic.reload[:replies_count]
918
+
919
+ reply.destroy
920
+ assert_equal 4, topic.reload[:replies_count]
921
+ assert_equal 4, topic.replies.size
922
+ end
923
+
924
+ def test_concurrent_counter_cache_double_destroy
925
+ topic = Topic.create title: "Zoom-zoom-zoom"
926
+
927
+ 5.times do
928
+ topic.replies.create(title: "re: zoom", content: "speedy quick!")
929
+ end
930
+
931
+ assert_equal 5, topic.reload[:replies_count]
932
+ assert_equal 5, topic.replies.size
933
+
934
+ reply = topic.replies.first
935
+ reply_clone = Reply.find(reply.id)
936
+
937
+ reply.destroy
938
+ assert_equal 4, topic.reload[:replies_count]
939
+
940
+ reply_clone.destroy
941
+ assert_equal 4, topic.reload[:replies_count]
942
+ assert_equal 4, topic.replies.size
943
+ end
944
+
945
+ def test_custom_counter_cache
946
+ reply = Reply.create(title: "re: zoom", content: "speedy quick!")
947
+ assert_equal 0, reply[:replies_count]
948
+
949
+ silly = SillyReply.create(title: "gaga", content: "boo-boo")
950
+ silly.reply = reply
951
+ silly.save!
952
+
953
+ assert_equal 1, reply.reload[:replies_count]
954
+ assert_equal 1, reply.replies.size
955
+
956
+ reply[:replies_count] = 17
957
+ assert_equal 17, reply.replies.size
958
+ end
959
+
960
+ def test_replace_counter_cache
961
+ topic = Topic.create(title: "Zoom-zoom-zoom")
962
+ reply = Reply.create(title: "re: zoom", content: "speedy quick!")
963
+
964
+ reply.topic = topic
965
+ reply.save
966
+ topic.reload
967
+
968
+ assert_equal 1, topic.replies_count
969
+ end
970
+
971
+ def test_association_assignment_sticks
972
+ post = Post.first
973
+
974
+ author1, author2 = Author.all.merge!(limit: 2).to_a
975
+ assert_not_nil author1
976
+ assert_not_nil author2
977
+
978
+ # make sure the association is loaded
979
+ post.author
980
+
981
+ # set the association by id, directly
982
+ post.author_id = author2.id
983
+
984
+ # save and reload
985
+ post.save!
986
+ post.reload
987
+
988
+ # the author id of the post should be the id we set
989
+ assert_equal post.author_id, author2.id
990
+ end
991
+
992
+ def test_cant_save_readonly_association
993
+ assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
994
+ assert_predicate companies(:first_client).readonly_firm, :readonly?
995
+ end
996
+
997
+ def test_polymorphic_assignment_foreign_key_type_string
998
+ comment = Comment.first
999
+ comment.author = Author.first
1000
+ comment.resource = Member.first
1001
+ comment.save
1002
+
1003
+ assert_equal Comment.all.to_a,
1004
+ Comment.includes(:author).to_a
1005
+
1006
+ assert_equal Comment.all.to_a,
1007
+ Comment.includes(:resource).to_a
1008
+ end
1009
+
1010
+ def test_polymorphic_assignment_foreign_type_field_updating
1011
+ # should update when assigning a saved record
1012
+ sponsor = Sponsor.new
1013
+ member = Member.create
1014
+ sponsor.sponsorable = member
1015
+ assert_equal "Member", sponsor.sponsorable_type
1016
+
1017
+ # should update when assigning a new record
1018
+ sponsor = Sponsor.new
1019
+ member = Member.new
1020
+ sponsor.sponsorable = member
1021
+ assert_equal "Member", sponsor.sponsorable_type
1022
+ end
1023
+
1024
+ def test_polymorphic_assignment_with_primary_key_foreign_type_field_updating
1025
+ # should update when assigning a saved record
1026
+ essay = Essay.new
1027
+ writer = Author.create(name: "David")
1028
+ essay.writer = writer
1029
+ assert_equal "Author", essay.writer_type
1030
+
1031
+ # should update when assigning a new record
1032
+ essay = Essay.new
1033
+ writer = Author.new
1034
+ essay.writer = writer
1035
+ assert_equal "Author", essay.writer_type
1036
+ end
1037
+
1038
+ def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
1039
+ sponsor = Sponsor.new
1040
+ saved_member = Member.create
1041
+ new_member = Member.new
1042
+
1043
+ sponsor.sponsorable = saved_member
1044
+ assert_equal saved_member.id, sponsor.sponsorable_id
1045
+
1046
+ sponsor.sponsorable = new_member
1047
+ assert_nil sponsor.sponsorable_id
1048
+ end
1049
+
1050
+ def test_assignment_updates_foreign_id_field_for_new_and_saved_records
1051
+ client = Client.new
1052
+ saved_firm = Firm.create name: "Saved"
1053
+ new_firm = Firm.new
1054
+
1055
+ client.firm = saved_firm
1056
+ assert_equal saved_firm.id, client.client_of
1057
+
1058
+ client.firm = new_firm
1059
+ assert_nil client.client_of
1060
+ end
1061
+
1062
+ def test_polymorphic_assignment_with_primary_key_updates_foreign_id_field_for_new_and_saved_records
1063
+ essay = Essay.new
1064
+ saved_writer = Author.create(name: "David")
1065
+ new_writer = Author.new
1066
+
1067
+ essay.writer = saved_writer
1068
+ assert_equal saved_writer.name, essay.writer_id
1069
+
1070
+ essay.writer = new_writer
1071
+ assert_nil essay.writer_id
1072
+ end
1073
+
1074
+ def test_polymorphic_assignment_with_nil
1075
+ essay = Essay.new
1076
+ assert_nil essay.writer_id
1077
+ assert_nil essay.writer_type
1078
+
1079
+ essay.writer_id = 1
1080
+ essay.writer_type = "Author"
1081
+
1082
+ essay.writer = nil
1083
+ assert_nil essay.writer_id
1084
+ assert_nil essay.writer_type
1085
+ end
1086
+
1087
+ def test_belongs_to_proxy_should_not_respond_to_private_methods
1088
+ assert_raise(NoMethodError) { companies(:first_firm).private_method }
1089
+ assert_raise(NoMethodError) { companies(:second_client).firm.private_method }
1090
+ end
1091
+
1092
+ 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)
1095
+ end
1096
+
1097
+ def test_save_of_record_with_loaded_belongs_to
1098
+ @account = companies(:first_firm).account
1099
+
1100
+ assert_nothing_raised do
1101
+ Account.find(@account.id).save!
1102
+ Account.all.merge!(includes: :firm).find(@account.id).save!
1103
+ end
1104
+
1105
+ @account.firm.delete
1106
+
1107
+ assert_nothing_raised do
1108
+ Account.find(@account.id).save!
1109
+ Account.all.merge!(includes: :firm).find(@account.id).save!
1110
+ end
1111
+ end
1112
+
1113
+ def test_dependent_delete_and_destroy_with_belongs_to
1114
+ AuthorAddress.destroyed_author_address_ids.clear
1115
+
1116
+ author_address = author_addresses(:david_address)
1117
+ author_address_extra = author_addresses(:david_address_extra)
1118
+ assert_equal [], AuthorAddress.destroyed_author_address_ids
1119
+
1120
+ assert_difference "AuthorAddress.count", -2 do
1121
+ authors(:david).destroy
1122
+ end
1123
+
1124
+ assert_equal [], AuthorAddress.where(id: [author_address.id, author_address_extra.id])
1125
+ assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids
1126
+ end
1127
+
1128
+ def test_belongs_to_invalid_dependent_option_raises_exception
1129
+ error = assert_raise ArgumentError do
1130
+ Class.new(Author).belongs_to :special_author_address, dependent: :nullify
1131
+ end
1132
+ assert_equal error.message, "The :dependent option must be one of [:destroy, :delete, :destroy_async], but is :nullify"
1133
+ end
1134
+
1135
+ class EssayDestroy < ActiveRecord::Base
1136
+ self.table_name = "essays"
1137
+ belongs_to :book, dependent: :destroy, class_name: "DestroyableBook"
1138
+ end
1139
+
1140
+ class DestroyableBook < ActiveRecord::Base
1141
+ self.table_name = "books"
1142
+ belongs_to :author, class_name: "UndestroyableAuthor", dependent: :destroy
1143
+ end
1144
+
1145
+ class UndestroyableAuthor < ActiveRecord::Base
1146
+ self.table_name = "authors"
1147
+ has_one :book, class_name: "DestroyableBook", foreign_key: "author_id"
1148
+ before_destroy :dont
1149
+
1150
+ def dont
1151
+ throw(:abort)
1152
+ end
1153
+ end
1154
+
1155
+ def test_dependency_should_halt_parent_destruction
1156
+ author = UndestroyableAuthor.create!(name: "Test")
1157
+ book = DestroyableBook.create!(author: author)
1158
+
1159
+ assert_no_difference ["UndestroyableAuthor.count", "DestroyableBook.count"] do
1160
+ assert_not book.destroy
1161
+ end
1162
+ end
1163
+
1164
+ def test_dependency_should_halt_parent_destruction_with_cascaded_three_levels
1165
+ author = UndestroyableAuthor.create!(name: "Test")
1166
+ book = DestroyableBook.create!(author: author)
1167
+ essay = EssayDestroy.create!(book: book)
1168
+
1169
+ assert_no_difference ["UndestroyableAuthor.count", "DestroyableBook.count", "EssayDestroy.count"] do
1170
+ assert_not essay.destroy
1171
+ assert_not essay.destroyed?
1172
+ end
1173
+ end
1174
+
1175
+ def test_attributes_are_being_set_when_initialized_from_belongs_to_association_with_where_clause
1176
+ new_firm = accounts(:signals37).build_firm(name: "Apple")
1177
+ assert_equal new_firm.name, "Apple"
1178
+ end
1179
+
1180
+ def test_attributes_are_set_without_error_when_initialized_from_belongs_to_association_with_array_in_where_clause
1181
+ new_account = Account.where(credit_limit: [ 50, 60 ]).new
1182
+ assert_nil new_account.credit_limit
1183
+ end
1184
+
1185
+ def test_reassigning_the_parent_id_updates_the_object
1186
+ client = companies(:second_client)
1187
+
1188
+ client.firm
1189
+ client.firm_with_condition
1190
+ firm_proxy = client.send(:association_instance_get, :firm)
1191
+ firm_with_condition_proxy = client.send(:association_instance_get, :firm_with_condition)
1192
+
1193
+ assert_not_predicate firm_proxy, :stale_target?
1194
+ assert_not_predicate firm_with_condition_proxy, :stale_target?
1195
+ assert_equal companies(:first_firm), client.firm
1196
+ assert_equal companies(:first_firm), client.firm_with_condition
1197
+
1198
+ client.client_of = companies(:another_firm).id
1199
+
1200
+ assert_predicate firm_proxy, :stale_target?
1201
+ assert_predicate firm_with_condition_proxy, :stale_target?
1202
+ assert_equal companies(:another_firm), client.firm
1203
+ assert_equal companies(:another_firm), client.firm_with_condition
1204
+ end
1205
+
1206
+ def test_destroying_child_with_unloaded_parent_and_foreign_key_and_touch_is_possible_with_has_many_inversing
1207
+ with_has_many_inversing do
1208
+ book = Book.create!
1209
+ citation = book.citations.create!
1210
+
1211
+ assert_difference "Citation.count", -1 do
1212
+ Citation.find(citation.id).destroy
1213
+ end
1214
+ end
1215
+ end
1216
+
1217
+ def test_polymorphic_reassignment_of_associated_id_updates_the_object
1218
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
1219
+
1220
+ sponsor.sponsorable
1221
+ proxy = sponsor.send(:association_instance_get, :sponsorable)
1222
+
1223
+ assert_not_predicate proxy, :stale_target?
1224
+ assert_equal members(:groucho), sponsor.sponsorable
1225
+
1226
+ sponsor.sponsorable_id = members(:some_other_guy).id
1227
+
1228
+ assert_predicate proxy, :stale_target?
1229
+ assert_equal members(:some_other_guy), sponsor.sponsorable
1230
+ end
1231
+
1232
+ def test_polymorphic_reassignment_of_associated_type_updates_the_object
1233
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
1234
+
1235
+ sponsor.sponsorable
1236
+ proxy = sponsor.send(:association_instance_get, :sponsorable)
1237
+
1238
+ assert_not_predicate proxy, :stale_target?
1239
+ assert_equal members(:groucho), sponsor.sponsorable
1240
+
1241
+ sponsor.sponsorable_type = "Firm"
1242
+
1243
+ assert_predicate proxy, :stale_target?
1244
+ assert_equal companies(:first_firm), sponsor.sponsorable
1245
+ end
1246
+
1247
+ def test_reloading_association_with_key_change
1248
+ client = companies(:second_client)
1249
+ firm = client.association(:firm)
1250
+
1251
+ client.firm = companies(:another_firm)
1252
+ firm.reload
1253
+ assert_equal companies(:another_firm), firm.target
1254
+
1255
+ client.client_of = companies(:first_firm).id
1256
+ firm.reload
1257
+ assert_equal companies(:first_firm), firm.target
1258
+ end
1259
+
1260
+ def test_polymorphic_counter_cache
1261
+ tagging = taggings(:welcome_general)
1262
+ post = posts(:welcome)
1263
+ comment = comments(:greetings)
1264
+
1265
+ assert_equal post.id, comment.id
1266
+
1267
+ assert_difference "post.reload.tags_count", -1 do
1268
+ assert_difference "comment.reload.tags_count", +1 do
1269
+ tagging.taggable = comment
1270
+ tagging.save!
1271
+ end
1272
+ end
1273
+
1274
+ assert_difference "comment.reload.tags_count", -1 do
1275
+ assert_difference "post.reload.tags_count", +1 do
1276
+ tagging.taggable_type = post.class.polymorphic_name
1277
+ tagging.taggable_id = post.id
1278
+ tagging.save!
1279
+ end
1280
+ end
1281
+ end
1282
+
1283
+ def test_polymorphic_with_custom_foreign_type
1284
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
1285
+ groucho = members(:groucho)
1286
+ other = members(:some_other_guy)
1287
+
1288
+ assert_equal groucho, sponsor.sponsorable
1289
+ assert_equal groucho, sponsor.thing
1290
+
1291
+ sponsor.thing = other
1292
+
1293
+ assert_equal other, sponsor.sponsorable
1294
+ assert_equal other, sponsor.thing
1295
+
1296
+ sponsor.sponsorable = groucho
1297
+
1298
+ assert_equal groucho, sponsor.sponsorable
1299
+ assert_equal groucho, sponsor.thing
1300
+ end
1301
+
1302
+ def test_build_with_conditions
1303
+ client = companies(:second_client)
1304
+ firm = client.build_bob_firm
1305
+
1306
+ assert_equal "Bob", firm.name
1307
+ end
1308
+
1309
+ def test_create_with_conditions
1310
+ client = companies(:second_client)
1311
+ firm = client.create_bob_firm
1312
+
1313
+ assert_equal "Bob", firm.name
1314
+ end
1315
+
1316
+ def test_create_bang_with_conditions
1317
+ client = companies(:second_client)
1318
+ firm = client.create_bob_firm!
1319
+
1320
+ assert_equal "Bob", firm.name
1321
+ end
1322
+
1323
+ def test_build_with_block
1324
+ client = Client.create(name: "Client Company")
1325
+
1326
+ firm = client.build_firm { |f| f.name = "Agency Company" }
1327
+ assert_equal "Agency Company", firm.name
1328
+ end
1329
+
1330
+ def test_create_with_block
1331
+ client = Client.create(name: "Client Company")
1332
+
1333
+ firm = client.create_firm { |f| f.name = "Agency Company" }
1334
+ assert_equal "Agency Company", firm.name
1335
+ end
1336
+
1337
+ def test_create_bang_with_block
1338
+ client = Client.create(name: "Client Company")
1339
+
1340
+ firm = client.create_firm! { |f| f.name = "Agency Company" }
1341
+ assert_equal "Agency Company", firm.name
1342
+ end
1343
+
1344
+ def test_should_set_foreign_key_on_create_association
1345
+ client = Client.create! name: "fuu"
1346
+
1347
+ firm = client.create_firm name: "baa"
1348
+ assert_equal firm.id, client.client_of
1349
+ end
1350
+
1351
+ def test_should_set_foreign_key_on_create_association!
1352
+ client = Client.create! name: "fuu"
1353
+
1354
+ firm = client.create_firm! name: "baa"
1355
+ assert_equal firm.id, client.client_of
1356
+ end
1357
+
1358
+ def test_self_referential_belongs_to_with_counter_cache_assigning_nil
1359
+ comment = Comment.create! post: posts(:thinking), body: "fuu"
1360
+ comment.parent = nil
1361
+ comment.save!
1362
+
1363
+ assert_nil comment.reload.parent
1364
+ assert_equal 0, comments(:greetings).reload.children_count
1365
+ end
1366
+
1367
+ def test_belongs_to_with_id_assigning
1368
+ post = posts(:welcome)
1369
+ comment = Comment.create! body: "foo", post: post
1370
+ parent = comments(:greetings)
1371
+ assert_equal 0, parent.reload.children_count
1372
+ comment.parent_id = parent.id
1373
+
1374
+ comment.save!
1375
+ assert_equal 1, parent.reload.children_count
1376
+ end
1377
+
1378
+ def test_belongs_to_with_out_of_range_value_assigning
1379
+ model = Class.new(Author) do
1380
+ def self.name; "Temp"; end
1381
+ validates :author_address, presence: true
1382
+ end
1383
+
1384
+ author = model.new
1385
+ author.author_address_id = 9223372036854775808 # out of range in the bigint
1386
+
1387
+ assert_nil author.author_address
1388
+ assert_not_predicate author, :valid?
1389
+ assert_equal [{ error: :blank }], author.errors.details[:author_address]
1390
+ end
1391
+
1392
+ def test_polymorphic_with_custom_primary_key
1393
+ toy = Toy.create!
1394
+ sponsor = Sponsor.create!(sponsorable: toy)
1395
+
1396
+ assert_equal toy, sponsor.reload.sponsorable
1397
+ end
1398
+
1399
+ class SponsorWithTouchInverse < Sponsor
1400
+ belongs_to :sponsorable, polymorphic: true, inverse_of: :sponsors, touch: true
1401
+ end
1402
+
1403
+ def test_destroying_polymorphic_child_with_unloaded_parent_and_touch_is_possible_with_has_many_inversing
1404
+ with_has_many_inversing do
1405
+ toy = Toy.create!
1406
+ sponsor = toy.sponsors.create!
1407
+
1408
+ assert_difference "Sponsor.count", -1 do
1409
+ SponsorWithTouchInverse.find(sponsor.id).destroy
1410
+ end
1411
+ end
1412
+ end
1413
+
1414
+ def test_polymorphic_with_false
1415
+ assert_nothing_raised do
1416
+ Class.new(ActiveRecord::Base) do
1417
+ def self.name; "Post"; end
1418
+ belongs_to :category, polymorphic: false
1419
+ end
1420
+ end
1421
+ end
1422
+
1423
+ test "stale tracking doesn't care about the type" do
1424
+ apple = Firm.create("name" => "Apple")
1425
+ citibank = Account.create("credit_limit" => 10)
1426
+
1427
+ citibank.firm_id = apple.id
1428
+ citibank.firm # load it
1429
+
1430
+ citibank.firm_id = apple.id.to_s
1431
+
1432
+ assert_not_predicate citibank.association(:firm), :stale_target?
1433
+ end
1434
+
1435
+ def test_reflect_the_most_recent_change
1436
+ author1, author2 = Author.limit(2)
1437
+ post = Post.new(title: "foo", body: "bar")
1438
+
1439
+ post.author = author1
1440
+ post.author_id = author2.id
1441
+
1442
+ assert post.save
1443
+ assert_equal post.author_id, author2.id
1444
+ end
1445
+
1446
+ test "dangerous association name raises ArgumentError" do
1447
+ [:errors, "errors", :save, "save"].each do |name|
1448
+ assert_raises(ArgumentError, "Association #{name} should not be allowed") do
1449
+ Class.new(ActiveRecord::Base) do
1450
+ belongs_to name
1451
+ end
1452
+ end
1453
+ end
1454
+ end
1455
+
1456
+ test "belongs_to works with model called Record" do
1457
+ record = Record.create!
1458
+ Column.create! record: record
1459
+ assert_equal 1, Column.count
1460
+ end
1461
+
1462
+ def test_multiple_counter_cache_with_after_create_update
1463
+ post = posts(:welcome)
1464
+ parent = comments(:greetings)
1465
+
1466
+ assert_difference "parent.reload.children_count", +1 do
1467
+ assert_difference "post.reload.comments_count", +1 do
1468
+ CommentWithAfterCreateUpdate.create(body: "foo", post: post, parent: parent)
1469
+ end
1470
+ end
1471
+ end
1472
+
1473
+ test "assigning an association doesn't result in duplicate objects" do
1474
+ post = Post.create!(title: "title", body: "body")
1475
+ post.comments = [post.comments.build(body: "body")]
1476
+ post.save!
1477
+
1478
+ assert_equal 1, post.comments.size
1479
+ assert_equal 1, Comment.where(post_id: post.id).count
1480
+ assert_equal post.id, Comment.last.post.id
1481
+ end
1482
+ end
1483
+
1484
+ class BelongsToWithForeignKeyTest < ActiveRecord::TestCase
1485
+ fixtures :authors, :author_addresses
1486
+
1487
+ def test_destroy_linked_models
1488
+ address = AuthorAddress.create!
1489
+ author = Author.create! name: "Author", author_address_id: address.id
1490
+
1491
+ author.destroy!
1492
+ end
1493
+ end