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,2251 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/tag"
5
+ require "models/tagging"
6
+ require "models/post"
7
+ require "models/topic"
8
+ require "models/comment"
9
+ require "models/author"
10
+ require "models/entrant"
11
+ require "models/developer"
12
+ require "models/project"
13
+ require "models/person"
14
+ require "models/computer"
15
+ require "models/reply"
16
+ require "models/company"
17
+ require "models/contract"
18
+ require "models/bird"
19
+ require "models/car"
20
+ require "models/engine"
21
+ require "models/tyre"
22
+ require "models/minivan"
23
+ require "models/possession"
24
+ require "models/reader"
25
+ require "models/category"
26
+ require "models/categorization"
27
+ require "models/edge"
28
+ require "models/subscriber"
29
+
30
+ class RelationTest < ActiveRecord::TestCase
31
+ fixtures :authors, :author_addresses, :topics, :entrants, :developers, :people, :companies, :developers_projects, :accounts, :categories, :categorizations, :categories_posts, :posts, :comments, :tags, :taggings, :cars, :minivans
32
+
33
+ def test_do_not_double_quote_string_id
34
+ van = Minivan.last
35
+ assert van
36
+ assert_equal van.id, Minivan.where(minivan_id: van).to_a.first.minivan_id
37
+ end
38
+
39
+ def test_do_not_double_quote_string_id_with_array
40
+ van = Minivan.last
41
+ assert van
42
+ assert_equal van, Minivan.where(minivan_id: [van]).to_a.first
43
+ end
44
+
45
+ def test_two_scopes_with_includes_should_not_drop_any_include
46
+ # heat habtm cache
47
+ car = Car.incl_engines.incl_tyres.first
48
+ car.tyres.length
49
+ car.engines.length
50
+
51
+ car = Car.incl_engines.incl_tyres.first
52
+ assert_no_queries { car.tyres.length }
53
+ assert_no_queries { car.engines.length }
54
+ end
55
+
56
+ def test_dynamic_finder
57
+ x = Post.where("author_id = ?", 1)
58
+ assert_respond_to x.klass, :find_by_id
59
+ end
60
+
61
+ def test_multivalue_where
62
+ posts = Post.where("author_id = ? AND id = ?", 1, 1)
63
+ assert_equal 1, posts.to_a.size
64
+ end
65
+
66
+ def test_scoped
67
+ topics = Topic.all
68
+ assert_kind_of ActiveRecord::Relation, topics
69
+ assert_equal 5, topics.size
70
+ end
71
+
72
+ def test_to_json
73
+ assert_nothing_raised { Bird.all.to_json }
74
+ assert_nothing_raised { Bird.all.to_a.to_json }
75
+ end
76
+
77
+ def test_to_yaml
78
+ assert_nothing_raised { Bird.all.to_yaml }
79
+ assert_nothing_raised { Bird.all.to_a.to_yaml }
80
+ end
81
+
82
+ def test_to_xml
83
+ assert_nothing_raised { Bird.all.to_xml }
84
+ assert_nothing_raised { Bird.all.to_a.to_xml }
85
+ end
86
+
87
+ def test_scoped_all
88
+ topics = Topic.all.to_a
89
+ assert_kind_of Array, topics
90
+ assert_no_queries { assert_equal 5, topics.size }
91
+ end
92
+
93
+ def test_loaded_all
94
+ topics = Topic.all
95
+
96
+ assert_not_predicate topics, :loaded?
97
+ assert_not_predicate topics, :loaded
98
+
99
+ assert_queries(1) do
100
+ 2.times { assert_equal 5, topics.to_a.size }
101
+ end
102
+
103
+ assert_predicate topics, :loaded?
104
+ assert_predicate topics, :loaded
105
+ end
106
+
107
+ def test_scoped_first
108
+ topics = Topic.all.order("id ASC")
109
+
110
+ assert_queries(1) do
111
+ 2.times { assert_equal "The First Topic", topics.first.title }
112
+ end
113
+
114
+ assert_not_predicate topics, :loaded?
115
+ end
116
+
117
+ def test_loaded_first
118
+ topics = Topic.all.order("id ASC")
119
+ topics.load # force load
120
+
121
+ assert_no_queries do
122
+ assert_equal "The First Topic", topics.first.title
123
+ end
124
+
125
+ assert_predicate topics, :loaded?
126
+ end
127
+
128
+ def test_loaded_first_with_limit
129
+ topics = Topic.all.order("id ASC")
130
+ topics.load # force load
131
+
132
+ assert_no_queries do
133
+ assert_equal ["The First Topic",
134
+ "The Second Topic of the day"], topics.first(2).map(&:title)
135
+ end
136
+
137
+ assert_predicate topics, :loaded?
138
+ end
139
+
140
+ def test_first_get_more_than_available
141
+ topics = Topic.all.order("id ASC")
142
+ unloaded_first = topics.first(10)
143
+ topics.load # force load
144
+
145
+ assert_no_queries do
146
+ loaded_first = topics.first(10)
147
+ assert_equal unloaded_first, loaded_first
148
+ end
149
+ end
150
+
151
+ def test_reload
152
+ topics = Topic.all
153
+
154
+ assert_queries(1) do
155
+ 2.times { topics.to_a }
156
+ end
157
+
158
+ assert_predicate topics, :loaded?
159
+
160
+ original_size = topics.to_a.size
161
+ Topic.create! title: "fake"
162
+
163
+ assert_queries(1) { topics.reload }
164
+ assert_equal original_size + 1, topics.size
165
+ assert_predicate topics, :loaded?
166
+ end
167
+
168
+ def test_finding_with_subquery
169
+ relation = Topic.where(approved: true)
170
+ assert_equal relation.to_a, Topic.select("*").from(relation).to_a
171
+ assert_equal relation.to_a, Topic.select("subquery.*").from(relation).to_a
172
+ assert_equal relation.to_a, Topic.select("a.*").from(relation, :a).to_a
173
+ end
174
+
175
+ def test_finding_with_subquery_with_binds
176
+ relation = Post.first.comments
177
+ assert_equal relation.to_a, Comment.select("*").from(relation).to_a
178
+ assert_equal relation.to_a, Comment.select("subquery.*").from(relation).to_a
179
+ assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).to_a
180
+ end
181
+
182
+ def test_finding_with_subquery_without_select_does_not_change_the_select
183
+ relation = Topic.where(approved: true)
184
+ assert_raises(ActiveRecord::StatementInvalid) do
185
+ Topic.from(relation).to_a
186
+ end
187
+ end
188
+
189
+ def test_select_with_from_includes_original_table_name
190
+ relation = Comment.joins(:post).select(:id).order(:id)
191
+ subquery = Comment.from("#{Comment.table_name} /*! USE INDEX (PRIMARY) */").joins(:post).select(:id).order(:id)
192
+ assert_equal relation.map(&:id), subquery.map(&:id)
193
+ end
194
+
195
+ def test_pluck_with_from_includes_original_table_name
196
+ relation = Comment.joins(:post).order(:id)
197
+ subquery = Comment.from("#{Comment.table_name} /*! USE INDEX (PRIMARY) */").joins(:post).order(:id)
198
+ assert_equal relation.pluck(:id), subquery.pluck(:id)
199
+ end
200
+
201
+ def test_select_with_from_includes_quoted_original_table_name
202
+ relation = Comment.joins(:post).select(:id).order(:id)
203
+ subquery = Comment.from("#{Comment.quoted_table_name} /*! USE INDEX (PRIMARY) */").joins(:post).select(:id).order(:id)
204
+ assert_equal relation.map(&:id), subquery.map(&:id)
205
+ end
206
+
207
+ def test_pluck_with_from_includes_quoted_original_table_name
208
+ relation = Comment.joins(:post).order(:id)
209
+ subquery = Comment.from("#{Comment.quoted_table_name} /*! USE INDEX (PRIMARY) */").joins(:post).order(:id)
210
+ assert_equal relation.pluck(:id), subquery.pluck(:id)
211
+ end
212
+
213
+ def test_select_with_subquery_in_from_uses_original_table_name
214
+ puts "test_select_with_subquery_in_from_uses_original_table_name"
215
+ relation = Comment.joins(:post).select(:id).order(:id)
216
+ puts "After relation"
217
+ # Avoid subquery flattening by adding distinct to work with SQLite < 3.20.0.
218
+ subquery = Comment.from(Comment.all.distinct, Comment.quoted_table_name).joins(:post).select(:id).order(:id)
219
+ puts "After subquery"
220
+ assert_equal relation.map(&:id), subquery.map(&:id)
221
+ end
222
+
223
+ def test_pluck_with_subquery_in_from_uses_original_table_name
224
+ relation = Comment.joins(:post).order(:id)
225
+ subquery = Comment.from(Comment.all, Comment.quoted_table_name).joins(:post).order(:id)
226
+ assert_equal relation.pluck(:id), subquery.pluck(:id)
227
+ end
228
+
229
+ def test_select_with_subquery_in_from_does_not_use_original_table_name
230
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count, type")
231
+ subquery = Comment.from(relation, "grouped_#{Comment.table_name}").select("type", "post_count")
232
+ assert_equal(relation.map(&:post_count).sort, subquery.map(&:post_count).sort)
233
+ end
234
+
235
+ def test_group_with_subquery_in_from_does_not_use_original_table_name
236
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count,type")
237
+ subquery = Comment.from(relation, "grouped_#{Comment.table_name}").group("type").average("post_count")
238
+ assert_equal(relation.map(&:post_count).sort, subquery.values.sort)
239
+ end
240
+
241
+ def test_select_with_subquery_string_in_from_does_not_use_original_table_name
242
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count, type")
243
+ subquery = Comment.from("(#{relation.to_sql}) #{Comment.table_name}_grouped").select("type", "post_count")
244
+ assert_equal(relation.map(&:post_count).sort, subquery.map(&:post_count).sort)
245
+ end
246
+
247
+ def test_group_with_subquery_string_in_from_does_not_use_original_table_name
248
+ puts "test_group_with_subquery_string_in_from_does_not_use_original_table_name"
249
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count,type")
250
+ subquery = Comment.from("(#{relation.to_sql}) #{Comment.table_name}_grouped").group("type").average("post_count")
251
+ assert_equal(relation.map(&:post_count).sort, subquery.values.sort)
252
+ end
253
+
254
+ def test_finding_with_subquery_with_eager_loading_in_from
255
+ relation = Comment.includes(:post).where("posts.type": "Post").order(:id)
256
+ assert_equal relation.to_a, Comment.select("*").from(relation).to_a
257
+ assert_equal relation.to_a, Comment.select("subquery.*").from(relation).to_a
258
+ assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).to_a
259
+ end
260
+
261
+ def test_finding_with_subquery_with_eager_loading_in_where
262
+ relation = Comment.includes(:post).where("posts.type": "Post")
263
+ assert_equal relation.sort_by(&:id), Comment.where(id: relation).sort_by(&:id)
264
+ end
265
+
266
+ def test_finding_with_conditions
267
+ assert_equal ["David"], Author.where(name: "David").map(&:name)
268
+ assert_equal ["Mary"], Author.where(["name = ?", "Mary"]).map(&:name)
269
+ assert_equal ["Mary"], Author.where("name = ?", "Mary").map(&:name)
270
+ end
271
+
272
+ def test_finding_with_order
273
+ topics = Topic.order("id")
274
+ assert_equal 5, topics.to_a.size
275
+ assert_equal topics(:first).title, topics.first.title
276
+ end
277
+
278
+ def test_finding_with_arel_order
279
+ topics = Topic.order(Topic.arel_table[:id].asc)
280
+ assert_equal 5, topics.to_a.size
281
+ assert_equal topics(:first).title, topics.first.title
282
+ end
283
+
284
+ def test_finding_with_assoc_order
285
+ topics = Topic.order(id: :desc)
286
+ assert_equal 5, topics.to_a.size
287
+ assert_equal topics(:fifth).title, topics.first.title
288
+ end
289
+
290
+ def test_finding_with_arel_assoc_order
291
+ topics = Topic.order(Arel.sql("id") => :desc)
292
+ assert_equal 5, topics.to_a.size
293
+ assert_equal topics(:fifth).title, topics.first.title
294
+ end
295
+
296
+ def test_finding_with_reversed_assoc_order
297
+ topics = Topic.order(id: :asc).reverse_order
298
+ assert_equal 5, topics.to_a.size
299
+ assert_equal topics(:fifth).title, topics.first.title
300
+ end
301
+
302
+ def test_finding_with_reversed_arel_assoc_order
303
+ topics = Topic.order(Arel.sql("id") => :asc).reverse_order
304
+ assert_equal 5, topics.to_a.size
305
+ assert_equal topics(:fifth).title, topics.first.title
306
+ end
307
+
308
+ def test_reverse_order_with_function
309
+ topics = Topic.order("lower(title)").reverse_order
310
+ assert_equal topics(:third).title, topics.first.title
311
+ end
312
+
313
+ def test_reverse_arel_order_with_function
314
+ topics = Topic.order(Topic.arel_table[:title].lower).reverse_order
315
+ assert_equal topics(:third).title, topics.first.title
316
+ end
317
+
318
+ def test_reverse_arel_assoc_order_with_function
319
+ topics = Topic.order(Arel.sql("lower(title)") => :asc).reverse_order
320
+ assert_equal topics(:third).title, topics.first.title
321
+ end
322
+
323
+ def test_reverse_order_with_function_other_predicates
324
+ topics = Topic.order("author_name, length(title), id").reverse_order
325
+ assert_equal topics(:second).title, topics.first.title
326
+ topics = Topic.order("length(author_name), id, length(title)").reverse_order
327
+ assert_equal topics(:fifth).title, topics.first.title
328
+ end
329
+
330
+ def test_reverse_order_with_multiargument_function
331
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
332
+ Topic.order(Arel.sql("concat(author_name, title)")).reverse_order
333
+ end
334
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
335
+ Topic.order(Arel.sql("concat(lower(author_name), title)")).reverse_order
336
+ end
337
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
338
+ Topic.order(Arel.sql("concat(author_name, lower(title))")).reverse_order
339
+ end
340
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
341
+ Topic.order(Arel.sql("concat(lower(author_name), title, length(title)")).reverse_order
342
+ end
343
+ end
344
+
345
+ def test_reverse_arel_assoc_order_with_multiargument_function
346
+ assert_nothing_raised do
347
+ Topic.order(Arel.sql("REPLACE(title, '', '')") => :asc).reverse_order
348
+ end
349
+ end
350
+
351
+ def test_reverse_order_with_nulls_first_or_last
352
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
353
+ Topic.order("title NULLS FIRST").reverse_order
354
+ end
355
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
356
+ Topic.order("title NULLS FIRST").reverse_order
357
+ end
358
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
359
+ Topic.order("title nulls last").reverse_order
360
+ end
361
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
362
+ Topic.order("title NULLS FIRST, author_name").reverse_order
363
+ end
364
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
365
+ Topic.order("author_name, title nulls last").reverse_order
366
+ end
367
+ end if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
368
+
369
+ def test_default_reverse_order_on_table_without_primary_key
370
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
371
+ Edge.all.reverse_order
372
+ end
373
+ end
374
+
375
+ def test_order_with_hash_and_symbol_generates_the_same_sql
376
+ assert_equal Topic.order(:id).to_sql, Topic.order(id: :asc).to_sql
377
+ end
378
+
379
+ def test_finding_with_desc_order_with_string
380
+ topics = Topic.order(id: "desc")
381
+ assert_equal 5, topics.to_a.size
382
+ assert_equal [topics(:fifth), topics(:fourth), topics(:third), topics(:second), topics(:first)], topics.to_a
383
+ end
384
+
385
+ def test_finding_with_asc_order_with_string
386
+ topics = Topic.order(id: "asc")
387
+ assert_equal 5, topics.to_a.size
388
+ assert_equal [topics(:first), topics(:second), topics(:third), topics(:fourth), topics(:fifth)], topics.to_a
389
+ end
390
+
391
+ def test_support_upper_and_lower_case_directions
392
+ assert_includes Topic.order(id: "ASC").to_sql, "ASC"
393
+ assert_includes Topic.order(id: "asc").to_sql, "ASC"
394
+ assert_includes Topic.order(id: :ASC).to_sql, "ASC"
395
+ assert_includes Topic.order(id: :asc).to_sql, "ASC"
396
+
397
+ assert_includes Topic.order(id: "DESC").to_sql, "DESC"
398
+ assert_includes Topic.order(id: "desc").to_sql, "DESC"
399
+ assert_includes Topic.order(id: :DESC).to_sql, "DESC"
400
+ assert_includes Topic.order(id: :desc).to_sql, "DESC"
401
+ end
402
+
403
+ def test_raising_exception_on_invalid_hash_params
404
+ e = assert_raise(ArgumentError) { Topic.order(:name, "id DESC", id: :asfsdf) }
405
+ assert_equal 'Direction "asfsdf" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]', e.message
406
+ end
407
+
408
+ def test_finding_last_with_arel_order
409
+ topics = Topic.order(Topic.arel_table[:id].asc)
410
+ assert_equal topics(:fifth).title, topics.last.title
411
+ end
412
+
413
+ def test_finding_with_order_concatenated
414
+ topics = Topic.order("author_name").order("title")
415
+ assert_equal 5, topics.to_a.size
416
+ assert_equal topics(:fourth).title, topics.first.title
417
+ end
418
+
419
+ def test_finding_with_order_by_aliased_attributes
420
+ topics = Topic.order(:heading)
421
+ assert_equal 5, topics.to_a.size
422
+ assert_equal topics(:fifth).title, topics.first.title
423
+ end
424
+
425
+ def test_finding_with_assoc_order_by_aliased_attributes
426
+ topics = Topic.order(heading: :desc)
427
+ assert_equal 5, topics.to_a.size
428
+ assert_equal topics(:third).title, topics.first.title
429
+ end
430
+
431
+ def test_finding_with_reorder
432
+ topics = Topic.order("author_name").order("title").reorder("id").to_a
433
+ topics_titles = topics.map(&:title)
434
+ assert_equal ["The First Topic", "The Second Topic of the day", "The Third Topic of the day", "The Fourth Topic of the day", "The Fifth Topic of the day"], topics_titles
435
+ end
436
+
437
+ def test_reorder_deduplication
438
+ topics = Topic.reorder("id desc", "id desc")
439
+ assert_equal ["id desc"], topics.order_values
440
+ end
441
+
442
+ def test_finding_with_reorder_by_aliased_attributes
443
+ topics = Topic.order("author_name").reorder(:heading)
444
+ assert_equal 5, topics.to_a.size
445
+ assert_equal topics(:fifth).title, topics.first.title
446
+ end
447
+
448
+ def test_finding_with_assoc_reorder_by_aliased_attributes
449
+ topics = Topic.order("author_name").reorder(heading: :desc)
450
+ assert_equal 5, topics.to_a.size
451
+ assert_equal topics(:third).title, topics.first.title
452
+ end
453
+
454
+ def test_finding_with_order_and_take
455
+ entrants = Entrant.order("id ASC").limit(2).to_a
456
+
457
+ assert_equal 2, entrants.size
458
+ assert_equal entrants(:first).name, entrants.first.name
459
+ end
460
+
461
+ def test_finding_with_cross_table_order_and_limit
462
+ tags = Tag.includes(:taggings).
463
+ order("tags.name asc", "taggings.taggable_id asc", Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).
464
+ limit(1).to_a
465
+ assert_equal 1, tags.length
466
+ end
467
+
468
+ def test_finding_with_complex_order_and_limit
469
+ tags = Tag.includes(:taggings).references(:taggings).order(Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).limit(1).to_a
470
+ assert_equal 1, tags.length
471
+ end
472
+
473
+ def test_finding_with_complex_order
474
+ tags = Tag.includes(:taggings).references(:taggings).order(Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).to_a
475
+ assert_equal 3, tags.length
476
+ end
477
+
478
+ def test_finding_with_sanitized_order
479
+ query = Tag.order([Arel.sql("field(id, ?)"), [1, 3, 2]]).to_sql
480
+ assert_match(/field\(id, 1,3,2\)/, query)
481
+
482
+ query = Tag.order([Arel.sql("field(id, ?)"), []]).to_sql
483
+ assert_match(/field\(id, NULL\)/, query)
484
+
485
+ query = Tag.order([Arel.sql("field(id, ?)"), nil]).to_sql
486
+ assert_match(/field\(id, NULL\)/, query)
487
+ end
488
+
489
+ def test_finding_with_order_limit_and_offset
490
+ entrants = Entrant.order("id ASC").limit(2).offset(1)
491
+
492
+ assert_equal 2, entrants.to_a.size
493
+ assert_equal entrants(:second).name, entrants.first.name
494
+
495
+ entrants = Entrant.order("id ASC").limit(2).offset(2)
496
+ assert_equal 1, entrants.to_a.size
497
+ assert_equal entrants(:third).name, entrants.first.name
498
+ end
499
+
500
+ def test_finding_with_group
501
+ developers = Developer.group("salary").select("salary").to_a
502
+ assert_equal 4, developers.size
503
+ assert_equal 4, developers.map(&:salary).uniq.size
504
+ end
505
+
506
+ def test_select_with_block
507
+ even_ids = Developer.all.select { |d| d.id % 2 == 0 }.map(&:id)
508
+ assert_equal [2, 4, 6, 8, 10], even_ids.sort
509
+ end
510
+
511
+ def test_joins_with_nil_argument
512
+ assert_nothing_raised { DependentFirm.joins(nil).first }
513
+ end
514
+
515
+ def test_finding_with_hash_conditions_on_joined_table
516
+ firms = DependentFirm.joins(:account).where(name: "RailsCore", accounts: { credit_limit: 55..60 }).to_a
517
+ assert_equal 1, firms.size
518
+ assert_equal companies(:rails_core), firms.first
519
+ end
520
+
521
+ def test_find_all_with_join
522
+ developers_on_project_one = Developer.joins("LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id").
523
+ where("project_id=1").to_a
524
+
525
+ assert_equal 3, developers_on_project_one.length
526
+ developer_names = developers_on_project_one.map(&:name)
527
+ assert_includes developer_names, "David"
528
+ assert_includes developer_names, "Jamis"
529
+ end
530
+
531
+ def test_find_on_hash_conditions
532
+ assert_equal Topic.all.merge!(where: { approved: false }).to_a, Topic.where(approved: false).to_a
533
+ end
534
+
535
+ def test_joins_with_string_array
536
+ person_with_reader_and_post = Post.joins([
537
+ "INNER JOIN categorizations ON categorizations.post_id = posts.id",
538
+ "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
539
+ ]
540
+ ).to_a
541
+ assert_equal 1, person_with_reader_and_post.size
542
+ end
543
+
544
+ def test_no_arguments_to_query_methods_raise_errors
545
+ assert_raises(ArgumentError) { Topic.references() }
546
+ assert_raises(ArgumentError) { Topic.includes() }
547
+ assert_raises(ArgumentError) { Topic.preload() }
548
+ assert_raises(ArgumentError) { Topic.group() }
549
+ assert_raises(ArgumentError) { Topic.reorder() }
550
+ assert_raises(ArgumentError) { Topic.order() }
551
+ assert_raises(ArgumentError) { Topic.eager_load() }
552
+ assert_raises(ArgumentError) { Topic.reselect() }
553
+ assert_raises(ArgumentError) { Topic.unscope() }
554
+ assert_raises(ArgumentError) { Topic.joins() }
555
+ assert_raises(ArgumentError) { Topic.left_joins() }
556
+ assert_raises(ArgumentError) { Topic.optimizer_hints() }
557
+ assert_raises(ArgumentError) { Topic.annotate() }
558
+ end
559
+
560
+ def test_blank_like_arguments_to_query_methods_dont_raise_errors
561
+ assert_nothing_raised { Topic.references([]) }
562
+ assert_nothing_raised { Topic.includes([]) }
563
+ assert_nothing_raised { Topic.preload([]) }
564
+ assert_nothing_raised { Topic.group([]) }
565
+ assert_nothing_raised { Topic.reorder([]) }
566
+ assert_nothing_raised { Topic.order([]) }
567
+ assert_nothing_raised { Topic.eager_load([]) }
568
+ assert_nothing_raised { Topic.reselect([]) }
569
+ assert_nothing_raised { Topic.unscope([]) }
570
+ assert_nothing_raised { Topic.joins([]) }
571
+ assert_nothing_raised { Topic.left_joins([]) }
572
+ assert_nothing_raised { Topic.optimizer_hints([]) }
573
+ assert_nothing_raised { Topic.annotate([]) }
574
+ end
575
+
576
+ def test_respond_to_dynamic_finders
577
+ relation = Topic.all
578
+
579
+ ["find_by_title", "find_by_title_and_author_name"].each do |method|
580
+ assert_respond_to relation, method
581
+ end
582
+ end
583
+
584
+ def test_respond_to_class_methods_and_scopes
585
+ assert_respond_to Topic.all, :by_lifo
586
+ end
587
+
588
+ def test_find_with_readonly_option
589
+ Developer.all.each { |d| assert_not d.readonly? }
590
+ Developer.all.readonly.each { |d| assert d.readonly? }
591
+ end
592
+
593
+ def test_eager_association_loading_of_stis_with_multiple_references
594
+ authors = Author.eager_load(posts: { special_comments: { post: [ :special_comments, :very_special_comment ] } }).
595
+ order("comments.body, very_special_comments_posts.body").where("posts.id = 4").to_a
596
+
597
+ assert_equal [authors(:david)], authors
598
+ assert_no_queries do
599
+ authors.first.posts.first.special_comments.first.post.special_comments
600
+ authors.first.posts.first.special_comments.first.post.very_special_comment
601
+ end
602
+ end
603
+
604
+ def test_find_with_preloaded_associations
605
+ assert_queries(2) do
606
+ posts = Post.preload(:comments).order("posts.id")
607
+ assert posts.first.comments.first
608
+ end
609
+
610
+ assert_queries(2) do
611
+ posts = Post.preload(:comments).order("posts.id")
612
+ assert posts.first.comments.first
613
+ end
614
+
615
+ assert_queries(2) do
616
+ posts = Post.preload(:author).order("posts.id")
617
+ assert posts.first.author
618
+ end
619
+
620
+ assert_queries(2) do
621
+ posts = Post.preload(:author).order("posts.id")
622
+ assert posts.first.author
623
+ end
624
+
625
+ assert_queries(3) do
626
+ posts = Post.preload(:author, :comments).order("posts.id")
627
+ assert posts.first.author
628
+ assert posts.first.comments.first
629
+ end
630
+ end
631
+
632
+ def test_preload_applies_to_all_chained_preloaded_scopes
633
+ assert_queries(3) do
634
+ post = Post.with_comments.with_tags.first
635
+ assert post
636
+ end
637
+ end
638
+
639
+ def test_extracted_association
640
+ relation_authors = assert_queries(2) { Post.all.extract_associated(:author) }
641
+ root_authors = assert_queries(2) { Post.extract_associated(:author) }
642
+ assert_equal relation_authors, root_authors
643
+ assert_equal Post.all.collect(&:author), relation_authors
644
+ end
645
+
646
+ def test_find_with_included_associations
647
+ assert_queries(2) do
648
+ posts = Post.includes(:comments).order("posts.id")
649
+ assert posts.first.comments.first
650
+ end
651
+
652
+ assert_queries(2) do
653
+ posts = Post.all.includes(:comments).order("posts.id")
654
+ assert posts.first.comments.first
655
+ end
656
+
657
+ assert_queries(2) do
658
+ posts = Post.includes(:author).order("posts.id")
659
+ assert posts.first.author
660
+ end
661
+
662
+ assert_queries(3) do
663
+ posts = Post.includes(:author, :comments).order("posts.id")
664
+ assert posts.first.author
665
+ assert posts.first.comments.first
666
+ end
667
+ end
668
+
669
+ def test_default_scoping_finder_methods
670
+ developers = DeveloperCalledDavid.order("id").map(&:id).sort
671
+ assert_equal Developer.where(name: "David").map(&:id).sort, developers
672
+ end
673
+
674
+ def test_includes_with_select
675
+ query = Post.select("legacy_comments_count AS ranking").order("ranking").includes(:comments)
676
+ .where(comments: { id: 1 })
677
+
678
+ assert_equal ["legacy_comments_count AS ranking"], query.select_values
679
+ assert_equal 1, query.to_a.size
680
+ end
681
+
682
+ def test_preloading_with_associations_and_merges
683
+ post = Post.create! title: "Uhuu", body: "body"
684
+ reader = Reader.create! post_id: post.id, person_id: 1
685
+ comment = Comment.create! post_id: post.id, body: "body"
686
+
687
+ assert_not_respond_to comment, :readers
688
+
689
+ post_rel = Post.preload(:readers).joins(:readers).where(title: "Uhuu")
690
+ result_comment = Comment.joins(:post).merge(post_rel).to_a.first
691
+ assert_equal comment, result_comment
692
+
693
+ assert_no_queries do
694
+ assert_equal post, result_comment.post
695
+ assert_equal [reader], result_comment.post.readers.to_a
696
+ end
697
+
698
+ post_rel = Post.includes(:readers).where(title: "Uhuu")
699
+ result_comment = Comment.joins(:post).merge(post_rel).first
700
+ assert_equal comment, result_comment
701
+
702
+ assert_no_queries do
703
+ assert_equal post, result_comment.post
704
+ assert_equal [reader], result_comment.post.readers.to_a
705
+ end
706
+ end
707
+
708
+ def test_preloading_with_associations_default_scopes_and_merges
709
+ post = Post.create! title: "Uhuu", body: "body"
710
+ reader = Reader.create! post_id: post.id, person_id: 1
711
+
712
+ post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: "Uhuu")
713
+ result_post = PostWithPreloadDefaultScope.all.merge(post_rel).to_a.first
714
+
715
+ assert_no_queries do
716
+ assert_equal [reader], result_post.readers.to_a
717
+ end
718
+
719
+ post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: "Uhuu")
720
+ result_post = PostWithIncludesDefaultScope.all.merge(post_rel).to_a.first
721
+
722
+ assert_no_queries do
723
+ assert_equal [reader], result_post.readers.to_a
724
+ end
725
+ end
726
+
727
+ def test_loading_with_one_association
728
+ posts = Post.preload(:comments)
729
+ post = posts.find { |p| p.id == 1 }
730
+ assert_equal 2, post.comments.size
731
+ assert_includes post.comments, comments(:greetings)
732
+
733
+ post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
734
+ assert_equal 2, post.comments.size
735
+ assert_includes post.comments, comments(:greetings)
736
+
737
+ posts = Post.preload(:last_comment)
738
+ post = posts.find { |p| p.id == 1 }
739
+ assert_equal Post.find(1).last_comment, post.last_comment
740
+ end
741
+
742
+ def test_to_sql_on_eager_join
743
+ expected = capture_sql {
744
+ Post.eager_load(:last_comment).order("comments.id DESC").to_a
745
+ }.first
746
+ actual = Post.eager_load(:last_comment).order("comments.id DESC").to_sql
747
+ assert_equal expected, actual
748
+ end
749
+
750
+ def test_to_sql_on_scoped_proxy
751
+ auth = Author.first
752
+ Post.where("1=1").written_by(auth)
753
+ assert_not auth.posts.to_sql.include?("1=1")
754
+ end
755
+
756
+ def test_loading_with_one_association_with_non_preload
757
+ posts = Post.eager_load(:last_comment).order("comments.id DESC")
758
+ post = posts.find { |p| p.id == 1 }
759
+ assert_equal Post.find(1).last_comment, post.last_comment
760
+ end
761
+
762
+ def test_dynamic_find_by_attributes
763
+ david = authors(:david)
764
+ author = Author.preload(:taggings).find_by_id(david.id)
765
+ expected_taggings = taggings(:welcome_general, :thinking_general)
766
+
767
+ assert_no_queries do
768
+ assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id)
769
+ end
770
+
771
+ authors = Author.all
772
+ assert_equal david, authors.find_by_id_and_name(david.id, david.name)
773
+ assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
774
+ end
775
+
776
+ def test_dynamic_find_by_attributes_bang
777
+ author = Author.all.find_by_id!(authors(:david).id)
778
+ assert_equal "David", author.name
779
+
780
+ assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, "invalid") }
781
+ end
782
+
783
+ def test_find_id
784
+ authors = Author.all
785
+
786
+ david = authors.find(authors(:david).id)
787
+ assert_equal "David", david.name
788
+
789
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(name: "lifo").find("42") }
790
+ end
791
+
792
+ def test_find_ids
793
+ authors = Author.order("id ASC")
794
+
795
+ results = authors.find(authors(:david).id, authors(:mary).id)
796
+ assert_kind_of Array, results
797
+ assert_equal 2, results.size
798
+ assert_equal "David", results[0].name
799
+ assert_equal "Mary", results[1].name
800
+ assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
801
+
802
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(name: "lifo").find(authors(:david).id, "42") }
803
+ assert_raises(ActiveRecord::RecordNotFound) { authors.find(["42", 43]) }
804
+ end
805
+
806
+ def test_find_in_empty_array
807
+ authors = Author.all.where(id: [])
808
+ assert_predicate authors.to_a, :blank?
809
+ end
810
+
811
+ def test_where_with_ar_object
812
+ author = Author.first
813
+ authors = Author.all.where(id: author)
814
+ assert_equal 1, authors.to_a.length
815
+ end
816
+
817
+ def test_where_with_ar_relation
818
+ author = Post.last.author
819
+ posts = Post.all.where(author: author)
820
+ assert_equal 3, posts.to_a.length
821
+ end
822
+
823
+ def test_where_id_with_delegated_ar_object
824
+ decorator = Class.new(SimpleDelegator)
825
+ author = Author.first
826
+ assert_equal 1, Author.where(id: decorator.new(author)).to_a.length
827
+ assert_equal 1, Author.where(id: [decorator.new(author)]).to_a.length
828
+ end
829
+
830
+ def test_where_relation_with_delegated_ar_object
831
+ decorator = Class.new(SimpleDelegator)
832
+ author = Post.last.author
833
+ assert_equal 3, Post.where(author: decorator.new(author)).to_a.length
834
+ assert_equal 3, Post.where(author: [decorator.new(author)]).to_a.length
835
+ end
836
+
837
+ def test_find_by_with_delegated_ar_object
838
+ decorator = Class.new(SimpleDelegator)
839
+ author = Author.first
840
+ assert_equal author, Author.find_by(id: decorator.new(author))
841
+ assert_equal author, Author.find_by(id: [decorator.new(author)])
842
+ end
843
+
844
+ def test_find_with_list_of_ar
845
+ author = Author.first
846
+ authors = Author.find([author.id])
847
+ assert_equal author, authors.first
848
+ end
849
+
850
+ def test_find_by_id_with_list_of_ar
851
+ author = Author.first
852
+ authors = Author.find_by_id([author])
853
+ assert_equal author, authors
854
+ end
855
+
856
+ def test_find_all_using_where_twice_should_or_the_relation
857
+ david = authors(:david)
858
+ relation = Author.unscoped
859
+ relation = relation.where(name: david.name)
860
+ relation = relation.where(name: "Santiago")
861
+ relation = relation.where(id: david.id)
862
+ assert_equal [], relation.to_a
863
+ end
864
+
865
+ def test_multi_where_ands_queries
866
+ relation = Author.unscoped
867
+ david = authors(:david)
868
+ sql = relation.where(name: david.name).where(name: "Santiago").to_sql
869
+ assert_match("AND", sql)
870
+ end
871
+
872
+ def test_find_all_with_multiple_should_use_and
873
+ david = authors(:david)
874
+ relation = [
875
+ { name: david.name },
876
+ { name: "Santiago" },
877
+ { name: "tenderlove" },
878
+ ].inject(Author.unscoped) do |memo, param|
879
+ memo.where(param)
880
+ end
881
+ assert_equal [], relation.to_a
882
+ end
883
+
884
+ def test_typecasting_where_with_array
885
+ ids = Author.pluck(:id)
886
+ slugs = ids.map { |id| "#{id}-as-a-slug" }
887
+
888
+ assert_equal Author.all.to_a, Author.where(id: slugs).to_a
889
+ end
890
+
891
+ def test_find_all_using_where_with_relation
892
+ david = authors(:david)
893
+ assert_queries(1) {
894
+ relation = Author.where(id: Author.where(id: david.id))
895
+ assert_equal [david], relation.to_a
896
+ }
897
+
898
+ assert_queries(1) {
899
+ relation = Author.where("id in (?)", Author.where(id: david).select(:id))
900
+ assert_equal [david], relation.to_a
901
+ }
902
+
903
+ assert_queries(1) do
904
+ relation = Author.where("id in (:author_ids)", author_ids: Author.where(id: david).select(:id))
905
+ assert_equal [david], relation.to_a
906
+ end
907
+ end
908
+
909
+ def test_find_all_using_where_with_relation_with_bound_values
910
+ david = authors(:david)
911
+ davids_posts = david.posts.order(:id).to_a
912
+
913
+ assert_queries(1) do
914
+ relation = Post.where(id: david.posts.select(:id))
915
+ assert_equal davids_posts, relation.order(:id).to_a
916
+ end
917
+
918
+ assert_queries(1) do
919
+ relation = Post.where("id in (?)", david.posts.select(:id))
920
+ assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as bind variables"
921
+ end
922
+
923
+ assert_queries(1) do
924
+ relation = Post.where("id in (:post_ids)", post_ids: david.posts.select(:id))
925
+ assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as named bind variables"
926
+ end
927
+ end
928
+
929
+ def test_find_all_using_where_with_relation_and_alternate_primary_key
930
+ cool_first = minivans(:cool_first)
931
+ assert_queries(1) {
932
+ relation = Minivan.where(minivan_id: Minivan.where(name: cool_first.name))
933
+ assert_equal [cool_first], relation.to_a
934
+ }
935
+ end
936
+
937
+ def test_find_all_using_where_with_relation_does_not_alter_select_values
938
+ david = authors(:david)
939
+
940
+ subquery = Author.where(id: david.id)
941
+
942
+ assert_queries(1) {
943
+ relation = Author.where(id: subquery)
944
+ assert_equal [david], relation.to_a
945
+ }
946
+
947
+ assert_equal 0, subquery.select_values.size
948
+ end
949
+
950
+ def test_find_all_using_where_with_relation_with_joins
951
+ david = authors(:david)
952
+ assert_queries(1) {
953
+ relation = Author.where(id: Author.joins(:posts).where(id: david.id))
954
+ assert_equal [david], relation.to_a
955
+ }
956
+ end
957
+
958
+ def test_find_all_using_where_with_relation_with_select_to_build_subquery
959
+ david = authors(:david)
960
+ assert_queries(1) {
961
+ relation = Author.where(name: Author.where(id: david.id).select(:name))
962
+ assert_equal [david], relation.to_a
963
+ }
964
+ end
965
+
966
+ def test_last
967
+ authors = Author.all
968
+ assert_equal authors(:bob), authors.last
969
+ end
970
+
971
+ def test_select_with_aggregates
972
+ posts = Post.select(:title, :body)
973
+
974
+ assert_equal 11, posts.count(:all)
975
+ assert_equal 11, posts.size
976
+ assert_predicate posts, :any?
977
+ assert_predicate posts, :many?
978
+ assert_not_empty posts
979
+ end
980
+
981
+ def test_select_takes_a_variable_list_of_args
982
+ david = developers(:david)
983
+
984
+ developer = Developer.where(id: david.id).select(:name, :salary).first
985
+ assert_equal david.name, developer.name
986
+ assert_equal david.salary, developer.salary
987
+ end
988
+
989
+ def test_select_takes_an_aliased_attribute
990
+ first = topics(:first)
991
+
992
+ topic = Topic.where(id: first.id).select(:heading).first
993
+ assert_equal first.heading, topic.heading
994
+ end
995
+
996
+ def test_select_argument_error
997
+ assert_raises(ArgumentError) { Developer.select }
998
+ end
999
+
1000
+ def test_select_argument_error_with_block
1001
+ assert_raises(ArgumentError) { Developer.select(:id) { |d| d.id % 2 == 0 } }
1002
+ end
1003
+
1004
+ def test_count
1005
+ posts = Post.all
1006
+
1007
+ assert_equal 11, posts.count
1008
+ assert_equal 11, posts.count(:all)
1009
+ assert_equal 11, posts.count(:id)
1010
+
1011
+ assert_equal 3, posts.where("legacy_comments_count > 1").count
1012
+ assert_equal 6, posts.where(comments_count: 0).count
1013
+ end
1014
+
1015
+ def test_count_with_block
1016
+ posts = Post.all
1017
+ assert_equal 8, posts.count { |p| p.comments_count.even? }
1018
+ end
1019
+
1020
+ def test_count_on_association_relation
1021
+ author = Author.last
1022
+ another_author = Author.first
1023
+ posts = Post.where(author_id: author.id)
1024
+
1025
+ assert_equal author.posts.where(author_id: author.id).size, posts.count
1026
+
1027
+ assert_equal 0, author.posts.where(author_id: another_author.id).size
1028
+ assert_empty author.posts.where(author_id: another_author.id)
1029
+ end
1030
+
1031
+ def test_count_with_distinct
1032
+ posts = Post.all
1033
+
1034
+ assert_equal 4, posts.distinct(true).count(:comments_count)
1035
+ assert_equal 11, posts.distinct(false).count(:comments_count)
1036
+
1037
+ assert_equal 4, posts.distinct(true).select(:comments_count).count
1038
+ assert_equal 11, posts.distinct(false).select(:comments_count).count
1039
+ end
1040
+
1041
+ def test_size_with_distinct
1042
+ posts = Post.distinct.select(:author_id, :comments_count)
1043
+ assert_queries(1) { assert_equal 8, posts.size }
1044
+ assert_queries(1) { assert_equal 8, posts.load.size }
1045
+ end
1046
+
1047
+ def test_size_with_eager_loading_and_custom_order
1048
+ posts = Post.includes(:comments).order("comments.id")
1049
+ assert_queries(1) { assert_equal 11, posts.size }
1050
+ assert_queries(1) { assert_equal 11, posts.load.size }
1051
+ end
1052
+
1053
+ def test_size_with_eager_loading_and_custom_select_and_order
1054
+ posts = Post.includes(:comments).order("comments.id").select(:type)
1055
+ assert_queries(1) { assert_equal 11, posts.size }
1056
+ assert_queries(1) { assert_equal 11, posts.load.size }
1057
+ end
1058
+
1059
+ def test_size_with_eager_loading_and_custom_order_and_distinct
1060
+ posts = Post.includes(:comments).order("comments.id").distinct
1061
+ assert_queries(1) { assert_equal 11, posts.size }
1062
+ assert_queries(1) { assert_equal 11, posts.load.size }
1063
+ end
1064
+
1065
+ def test_size_with_eager_loading_and_manual_distinct_select_and_custom_order
1066
+ accounts = Account.select("DISTINCT accounts.firm_id").order("accounts.firm_id")
1067
+
1068
+ assert_queries(1) { assert_equal 5, accounts.size }
1069
+ assert_queries(1) { assert_equal 5, accounts.load.size }
1070
+ end
1071
+
1072
+ def test_count_explicit_columns
1073
+ Post.update_all(comments_count: nil)
1074
+ posts = Post.all
1075
+
1076
+ assert_equal [0], posts.select("comments_count").where("id is not null").group("id").order("id").count.values.uniq
1077
+ assert_equal 0, posts.where("id is not null").select("comments_count").count
1078
+
1079
+ assert_equal 11, posts.select("comments_count").count("id")
1080
+ assert_equal 0, posts.select("comments_count").count
1081
+ assert_equal 0, posts.count(:comments_count)
1082
+ assert_equal 0, posts.count("comments_count")
1083
+ end
1084
+
1085
+ def test_multiple_selects
1086
+ post = Post.all.select("comments_count").select("title").order("id ASC").first
1087
+ assert_equal "Welcome to the weblog", post.title
1088
+ assert_equal 2, post.comments_count
1089
+ end
1090
+
1091
+ def test_size
1092
+ posts = Post.all
1093
+
1094
+ assert_queries(1) { assert_equal 11, posts.size }
1095
+ assert_not_predicate posts, :loaded?
1096
+
1097
+ best_posts = posts.where(comments_count: 0)
1098
+ best_posts.load # force load
1099
+ assert_no_queries { assert_equal 6, best_posts.size }
1100
+ end
1101
+
1102
+ def test_size_with_limit
1103
+ posts = Post.limit(10)
1104
+
1105
+ assert_queries(1) { assert_equal 10, posts.size }
1106
+ assert_not_predicate posts, :loaded?
1107
+
1108
+ best_posts = posts.where(comments_count: 0)
1109
+ best_posts.load # force load
1110
+ assert_no_queries { assert_equal 6, best_posts.size }
1111
+ end
1112
+
1113
+ def test_size_with_zero_limit
1114
+ posts = Post.limit(0)
1115
+
1116
+ assert_no_queries { assert_equal 0, posts.size }
1117
+ assert_not_predicate posts, :loaded?
1118
+
1119
+ posts.load # force load
1120
+ assert_no_queries { assert_equal 0, posts.size }
1121
+ end
1122
+
1123
+ def test_empty_with_zero_limit
1124
+ posts = Post.limit(0)
1125
+
1126
+ assert_no_queries { assert_equal true, posts.empty? }
1127
+ assert_not_predicate posts, :loaded?
1128
+ end
1129
+
1130
+ def test_count_complex_chained_relations
1131
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("legacy_comments_count > 0")
1132
+
1133
+ expected = { 1 => 4, 2 => 1 }
1134
+ assert_equal expected, posts.count
1135
+ end
1136
+
1137
+ def test_empty
1138
+ posts = Post.all
1139
+
1140
+ assert_queries(1) { assert_equal false, posts.empty? }
1141
+ assert_not_predicate posts, :loaded?
1142
+
1143
+ no_posts = posts.where(title: "")
1144
+ assert_queries(1) { assert_equal true, no_posts.empty? }
1145
+ assert_not_predicate no_posts, :loaded?
1146
+
1147
+ best_posts = posts.where(comments_count: 0)
1148
+ best_posts.load # force load
1149
+ assert_no_queries { assert_equal false, best_posts.empty? }
1150
+ end
1151
+
1152
+ def test_empty_complex_chained_relations
1153
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("legacy_comments_count > 0")
1154
+
1155
+ assert_queries(1) { assert_equal false, posts.empty? }
1156
+ assert_not_predicate posts, :loaded?
1157
+
1158
+ no_posts = posts.where(title: "")
1159
+ assert_queries(1) { assert_equal true, no_posts.empty? }
1160
+ assert_not_predicate no_posts, :loaded?
1161
+ end
1162
+
1163
+ def test_any
1164
+ posts = Post.all
1165
+
1166
+ assert_queries(3) do
1167
+ assert posts.any? # Uses COUNT()
1168
+ assert_not_predicate posts.where(id: nil), :any?
1169
+
1170
+ assert posts.any? { |p| p.id > 0 }
1171
+ assert_not posts.any? { |p| p.id <= 0 }
1172
+ end
1173
+
1174
+ assert_predicate posts, :loaded?
1175
+ end
1176
+
1177
+ def test_many
1178
+ posts = Post.all
1179
+
1180
+ assert_queries(2) do
1181
+ assert posts.many? # Uses COUNT()
1182
+ assert posts.many? { |p| p.id > 0 }
1183
+ assert_not posts.many? { |p| p.id < 2 }
1184
+ end
1185
+
1186
+ assert_predicate posts, :loaded?
1187
+ end
1188
+
1189
+ def test_many_with_limits
1190
+ posts = Post.all
1191
+
1192
+ assert_predicate posts, :many?
1193
+ assert_not_predicate posts.limit(1), :many?
1194
+ end
1195
+
1196
+ def test_none?
1197
+ posts = Post.all
1198
+ assert_queries(1) do
1199
+ assert_not posts.none? # Uses COUNT()
1200
+ end
1201
+
1202
+ assert_not_predicate posts, :loaded?
1203
+
1204
+ assert_queries(1) do
1205
+ assert posts.none? { |p| p.id < 0 }
1206
+ assert_not posts.none? { |p| p.id == 1 }
1207
+ end
1208
+
1209
+ assert_predicate posts, :loaded?
1210
+ end
1211
+
1212
+ def test_one
1213
+ posts = Post.all
1214
+ assert_queries(1) do
1215
+ assert_not posts.one? # Uses COUNT()
1216
+ end
1217
+
1218
+ assert_not_predicate posts, :loaded?
1219
+
1220
+ assert_queries(1) do
1221
+ assert_not posts.one? { |p| p.id < 3 }
1222
+ assert posts.one? { |p| p.id == 1 }
1223
+ end
1224
+
1225
+ assert_predicate posts, :loaded?
1226
+ end
1227
+
1228
+ def test_to_a_should_dup_target
1229
+ posts = Post.all
1230
+
1231
+ original_size = posts.size
1232
+ removed = posts.to_a.pop
1233
+
1234
+ assert_equal original_size, posts.size
1235
+ assert_includes posts.to_a, removed
1236
+ end
1237
+
1238
+ def test_build
1239
+ posts = Post.all
1240
+
1241
+ post = posts.new
1242
+ assert_kind_of Post, post
1243
+ end
1244
+
1245
+ def test_scoped_build
1246
+ posts = Post.where(title: "You told a lie")
1247
+
1248
+ post = posts.new
1249
+ assert_kind_of Post, post
1250
+ assert_equal "You told a lie", post.title
1251
+ end
1252
+
1253
+ def test_create
1254
+ birds = Bird.all
1255
+
1256
+ sparrow = birds.create
1257
+ assert_kind_of Bird, sparrow
1258
+ assert_not_predicate sparrow, :persisted?
1259
+
1260
+ hen = birds.where(name: "hen").create
1261
+ assert_predicate hen, :persisted?
1262
+ assert_equal "hen", hen.name
1263
+ end
1264
+
1265
+ def test_create_bang
1266
+ birds = Bird.all
1267
+
1268
+ assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
1269
+
1270
+ hen = birds.where(name: "hen").create!
1271
+ assert_kind_of Bird, hen
1272
+ assert_predicate hen, :persisted?
1273
+ assert_equal "hen", hen.name
1274
+ end
1275
+
1276
+ def test_create_with_polymorphic_association
1277
+ author = authors(:david)
1278
+ post = posts(:welcome)
1279
+ comment = Comment.where(post: post, author: author).create!(body: "hello")
1280
+
1281
+ assert_equal author, comment.author
1282
+ assert_equal post, comment.post
1283
+ end
1284
+
1285
+ def test_first_or_create
1286
+ parrot = Bird.where(color: "green").first_or_create(name: "parrot")
1287
+ assert_kind_of Bird, parrot
1288
+ assert_predicate parrot, :persisted?
1289
+ assert_equal "parrot", parrot.name
1290
+ assert_equal "green", parrot.color
1291
+
1292
+ same_parrot = Bird.where(color: "green").first_or_create(name: "parakeet")
1293
+ assert_kind_of Bird, same_parrot
1294
+ assert_predicate same_parrot, :persisted?
1295
+ assert_equal parrot, same_parrot
1296
+
1297
+ canary = Bird.where(Bird.arel_table[:color].is_distinct_from("green")).first_or_create(name: "canary")
1298
+ assert_equal "canary", canary.name
1299
+ assert_nil canary.color
1300
+ end
1301
+
1302
+ def test_first_or_create_with_no_parameters
1303
+ parrot = Bird.where(color: "green").first_or_create
1304
+ assert_kind_of Bird, parrot
1305
+ assert_not_predicate parrot, :persisted?
1306
+ assert_equal "green", parrot.color
1307
+ end
1308
+
1309
+ def test_first_or_create_with_block
1310
+ canary = Bird.create!(color: "yellow", name: "canary")
1311
+ parrot = Bird.where(color: "green").first_or_create do |bird|
1312
+ bird.name = "parrot"
1313
+ bird.enable_count = true
1314
+ assert_equal canary, Bird.find_by!(name: "canary")
1315
+ end
1316
+ assert_equal 1, parrot.total_count
1317
+ assert_kind_of Bird, parrot
1318
+ assert_predicate parrot, :persisted?
1319
+ assert_equal "green", parrot.color
1320
+ assert_equal "parrot", parrot.name
1321
+
1322
+ same_parrot = Bird.where(color: "green").first_or_create { |bird| bird.name = "parakeet" }
1323
+ assert_equal parrot, same_parrot
1324
+ end
1325
+
1326
+ def test_first_or_create_with_array
1327
+ several_green_birds = Bird.where(color: "green").first_or_create([{ name: "parrot" }, { name: "parakeet" }])
1328
+ assert_kind_of Array, several_green_birds
1329
+ several_green_birds.each { |bird| assert bird.persisted? }
1330
+
1331
+ same_parrot = Bird.where(color: "green").first_or_create([{ name: "hummingbird" }, { name: "macaw" }])
1332
+ assert_kind_of Bird, same_parrot
1333
+ assert_equal several_green_birds.first, same_parrot
1334
+ end
1335
+
1336
+ def test_first_or_create_bang_with_valid_options
1337
+ parrot = Bird.where(color: "green").first_or_create!(name: "parrot")
1338
+ assert_kind_of Bird, parrot
1339
+ assert_predicate parrot, :persisted?
1340
+ assert_equal "parrot", parrot.name
1341
+ assert_equal "green", parrot.color
1342
+
1343
+ same_parrot = Bird.where(color: "green").first_or_create!(name: "parakeet")
1344
+ assert_kind_of Bird, same_parrot
1345
+ assert_predicate same_parrot, :persisted?
1346
+ assert_equal parrot, same_parrot
1347
+ end
1348
+
1349
+ def test_first_or_create_bang_with_invalid_options
1350
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!(pirate_id: 1) }
1351
+ end
1352
+
1353
+ def test_first_or_create_bang_with_no_parameters
1354
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create! }
1355
+ end
1356
+
1357
+ def test_first_or_create_bang_with_valid_block
1358
+ canary = Bird.create!(color: "yellow", name: "canary")
1359
+ parrot = Bird.where(color: "green").first_or_create! do |bird|
1360
+ bird.name = "parrot"
1361
+ bird.enable_count = true
1362
+ assert_equal canary, Bird.find_by!(name: "canary")
1363
+ end
1364
+ assert_equal 1, parrot.total_count
1365
+ assert_kind_of Bird, parrot
1366
+ assert_predicate parrot, :persisted?
1367
+ assert_equal "green", parrot.color
1368
+ assert_equal "parrot", parrot.name
1369
+
1370
+ same_parrot = Bird.where(color: "green").first_or_create! { |bird| bird.name = "parakeet" }
1371
+ assert_equal parrot, same_parrot
1372
+ end
1373
+
1374
+ def test_first_or_create_bang_with_invalid_block
1375
+ assert_raise(ActiveRecord::RecordInvalid) do
1376
+ Bird.where(color: "green").first_or_create! { |bird| bird.pirate_id = 1 }
1377
+ end
1378
+ end
1379
+
1380
+ def test_first_or_create_bang_with_valid_array
1381
+ several_green_birds = Bird.where(color: "green").first_or_create!([{ name: "parrot" }, { name: "parakeet" }])
1382
+ assert_kind_of Array, several_green_birds
1383
+ several_green_birds.each { |bird| assert bird.persisted? }
1384
+
1385
+ same_parrot = Bird.where(color: "green").first_or_create!([{ name: "hummingbird" }, { name: "macaw" }])
1386
+ assert_kind_of Bird, same_parrot
1387
+ assert_equal several_green_birds.first, same_parrot
1388
+ end
1389
+
1390
+ def test_first_or_create_bang_with_invalid_array
1391
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!([ { name: "parrot" }, { pirate_id: 1 } ]) }
1392
+ end
1393
+
1394
+ def test_first_or_initialize
1395
+ parrot = Bird.where(color: "green").first_or_initialize(name: "parrot")
1396
+ assert_kind_of Bird, parrot
1397
+ assert_not_predicate parrot, :persisted?
1398
+ assert_predicate parrot, :valid?
1399
+ assert_predicate parrot, :new_record?
1400
+ assert_equal "parrot", parrot.name
1401
+ assert_equal "green", parrot.color
1402
+
1403
+ canary = Bird.where(Bird.arel_table[:color].is_distinct_from("green")).first_or_initialize(name: "canary")
1404
+ assert_equal "canary", canary.name
1405
+ assert_nil canary.color
1406
+ end
1407
+
1408
+ def test_first_or_initialize_with_no_parameters
1409
+ parrot = Bird.where(color: "green").first_or_initialize
1410
+ assert_kind_of Bird, parrot
1411
+ assert_not_predicate parrot, :persisted?
1412
+ assert_not_predicate parrot, :valid?
1413
+ assert_predicate parrot, :new_record?
1414
+ assert_equal "green", parrot.color
1415
+ end
1416
+
1417
+ def test_first_or_initialize_with_block
1418
+ canary = Bird.create!(color: "yellow", name: "canary")
1419
+ parrot = Bird.where(color: "green").first_or_initialize do |bird|
1420
+ bird.name = "parrot"
1421
+ bird.enable_count = true
1422
+ assert_equal canary, Bird.find_by!(name: "canary")
1423
+ end
1424
+ assert_equal 1, parrot.total_count
1425
+ assert_kind_of Bird, parrot
1426
+ assert_not_predicate parrot, :persisted?
1427
+ assert_predicate parrot, :valid?
1428
+ assert_predicate parrot, :new_record?
1429
+ assert_equal "green", parrot.color
1430
+ assert_equal "parrot", parrot.name
1431
+ end
1432
+
1433
+ def test_find_or_create_by
1434
+ assert_nil Bird.find_by(name: "bob")
1435
+
1436
+ bird = Bird.find_or_create_by(name: "bob")
1437
+ assert_predicate bird, :persisted?
1438
+
1439
+ assert_equal bird, Bird.find_or_create_by(name: "bob")
1440
+ end
1441
+
1442
+ def test_find_or_create_by_with_create_with
1443
+ assert_nil Bird.find_by(name: "bob")
1444
+
1445
+ bird = Bird.create_with(color: "green").find_or_create_by(name: "bob")
1446
+ assert_predicate bird, :persisted?
1447
+ assert_equal "green", bird.color
1448
+
1449
+ assert_equal bird, Bird.create_with(color: "blue").find_or_create_by(name: "bob")
1450
+ end
1451
+
1452
+ def test_find_or_create_by!
1453
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: "green") }
1454
+ end
1455
+
1456
+ def test_create_or_find_by
1457
+ assert_nil Subscriber.find_by(nick: "bob")
1458
+
1459
+ subscriber = Subscriber.create!(nick: "bob")
1460
+
1461
+ assert_equal subscriber, Subscriber.create_or_find_by(nick: "bob")
1462
+ assert_not_equal subscriber, Subscriber.create_or_find_by(nick: "cat")
1463
+ end
1464
+
1465
+ def test_create_or_find_by_should_not_raise_due_to_validation_errors
1466
+ assert_nothing_raised do
1467
+ bird = Bird.create_or_find_by(color: "green")
1468
+ assert_predicate bird, :invalid?
1469
+ end
1470
+ end
1471
+
1472
+ def test_create_or_find_by_with_non_unique_attributes
1473
+ Subscriber.create!(nick: "bob", name: "the builder")
1474
+
1475
+ assert_raises(ActiveRecord::RecordNotFound) do
1476
+ Subscriber.create_or_find_by(nick: "bob", name: "the cat")
1477
+ end
1478
+ end
1479
+
1480
+ def test_create_or_find_by_within_transaction
1481
+ assert_nil Subscriber.find_by(nick: "bob")
1482
+
1483
+ subscriber = Subscriber.create!(nick: "bob")
1484
+
1485
+ Subscriber.transaction do
1486
+ assert_equal subscriber, Subscriber.create_or_find_by(nick: "bob")
1487
+ assert_not_equal subscriber, Subscriber.create_or_find_by(nick: "cat")
1488
+ end
1489
+ end
1490
+
1491
+ def test_create_or_find_by_with_bang
1492
+ assert_nil Subscriber.find_by(nick: "bob")
1493
+
1494
+ subscriber = Subscriber.create!(nick: "bob")
1495
+
1496
+ assert_equal subscriber, Subscriber.create_or_find_by!(nick: "bob")
1497
+ assert_not_equal subscriber, Subscriber.create_or_find_by!(nick: "cat")
1498
+ end
1499
+
1500
+ def test_create_or_find_by_with_bang_should_raise_due_to_validation_errors
1501
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.create_or_find_by!(color: "green") }
1502
+ end
1503
+
1504
+ def test_create_or_find_by_with_bang_with_non_unique_attributes
1505
+ Subscriber.create!(nick: "bob", name: "the builder")
1506
+
1507
+ assert_raises(ActiveRecord::RecordNotFound) do
1508
+ Subscriber.create_or_find_by!(nick: "bob", name: "the cat")
1509
+ end
1510
+ end
1511
+
1512
+ def test_create_or_find_by_with_bang_within_transaction
1513
+ assert_nil Subscriber.find_by(nick: "bob")
1514
+
1515
+ subscriber = Subscriber.create!(nick: "bob")
1516
+
1517
+ Subscriber.transaction do
1518
+ assert_equal subscriber, Subscriber.create_or_find_by!(nick: "bob")
1519
+ assert_not_equal subscriber, Subscriber.create_or_find_by!(nick: "cat")
1520
+ end
1521
+ end
1522
+
1523
+ def test_find_or_initialize_by
1524
+ assert_nil Bird.find_by(name: "bob")
1525
+
1526
+ bird = Bird.find_or_initialize_by(name: "bob")
1527
+ assert_predicate bird, :new_record?
1528
+ bird.save!
1529
+
1530
+ assert_equal bird, Bird.find_or_initialize_by(name: "bob")
1531
+ end
1532
+
1533
+ def test_explicit_create_with
1534
+ hens = Bird.where(name: "hen")
1535
+ assert_equal "hen", hens.new.name
1536
+
1537
+ hens = hens.create_with(name: "cock")
1538
+ assert_equal "cock", hens.new.name
1539
+ end
1540
+
1541
+ def test_create_with_nested_attributes
1542
+ assert_difference("Project.count", 1) do
1543
+ developers = Developer.where(name: "Aaron")
1544
+ developers = developers.create_with(
1545
+ projects_attributes: [{ name: "p1" }]
1546
+ )
1547
+ developers.create!
1548
+ end
1549
+ end
1550
+
1551
+ def test_except
1552
+ relation = Post.where(author_id: 1).order("id ASC").limit(1)
1553
+ assert_equal [posts(:welcome)], relation.to_a
1554
+
1555
+ author_posts = relation.except(:order, :limit)
1556
+ assert_equal Post.where(author_id: 1).sort_by(&:id), author_posts.sort_by(&:id)
1557
+ assert_equal author_posts.sort_by(&:id), relation.scoping { Post.except(:order, :limit).sort_by(&:id) }
1558
+
1559
+ all_posts = relation.except(:where, :order, :limit)
1560
+ assert_equal Post.all.sort_by(&:id), all_posts.sort_by(&:id)
1561
+ assert_equal all_posts.sort_by(&:id), relation.scoping { Post.except(:where, :order, :limit).sort_by(&:id) }
1562
+ end
1563
+
1564
+ def test_only
1565
+ relation = Post.where(author_id: 1).order("id ASC").limit(1)
1566
+ assert_equal [posts(:welcome)], relation.to_a
1567
+
1568
+ author_posts = relation.only(:where)
1569
+ assert_equal Post.where(author_id: 1).sort_by(&:id), author_posts.sort_by(&:id)
1570
+ assert_equal author_posts.sort_by(&:id), relation.scoping { Post.only(:where).sort_by(&:id) }
1571
+
1572
+ all_posts = relation.only(:order)
1573
+ assert_equal Post.order("id ASC").to_a, all_posts.to_a
1574
+ assert_equal all_posts.to_a, relation.scoping { Post.only(:order).to_a }
1575
+ end
1576
+
1577
+ def test_anonymous_extension
1578
+ relation = Post.where(author_id: 1).order("id ASC").extending do
1579
+ def author
1580
+ "lifo"
1581
+ end
1582
+ end
1583
+
1584
+ assert_equal "lifo", relation.author
1585
+ assert_equal "lifo", relation.limit(1).author
1586
+ end
1587
+
1588
+ def test_named_extension
1589
+ relation = Post.where(author_id: 1).order("id ASC").extending(Post::NamedExtension)
1590
+ assert_equal "lifo", relation.author
1591
+ assert_equal "lifo", relation.limit(1).author
1592
+ end
1593
+
1594
+ def test_order_by_relation_attribute
1595
+ assert_equal Post.order(Post.arel_table[:title]).to_a, Post.order("title").to_a
1596
+ end
1597
+
1598
+ def test_default_scope_order_with_scope_order
1599
+ assert_equal "zyke", CoolCar.order_using_new_style.limit(1).first.name
1600
+ assert_equal "zyke", FastCar.order_using_new_style.limit(1).first.name
1601
+ end
1602
+
1603
+ def test_order_using_scoping
1604
+ car1 = CoolCar.order("id DESC").scoping do
1605
+ CoolCar.all.merge!(order: "id asc").first
1606
+ end
1607
+ assert_equal "zyke", car1.name
1608
+
1609
+ car2 = FastCar.order("id DESC").scoping do
1610
+ FastCar.all.merge!(order: "id asc").first
1611
+ end
1612
+ assert_equal "zyke", car2.name
1613
+ end
1614
+
1615
+ def test_unscoped_block_style
1616
+ assert_equal "honda", CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name }
1617
+ assert_equal "honda", FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name }
1618
+ end
1619
+
1620
+ def test_intersection_with_array
1621
+ relation = Author.where(name: "David")
1622
+ rails_author = relation.first
1623
+
1624
+ assert_equal [rails_author], [rails_author] & relation
1625
+ assert_equal [rails_author], relation & [rails_author]
1626
+ end
1627
+
1628
+ def test_primary_key
1629
+ assert_equal "id", Post.all.primary_key
1630
+ end
1631
+
1632
+ def test_ordering_with_extra_spaces
1633
+ assert_equal authors(:david), Author.order("id DESC , name DESC").last
1634
+ end
1635
+
1636
+ def test_distinct
1637
+ tag1 = Tag.create(name: "Foo")
1638
+ tag2 = Tag.create(name: "Foo")
1639
+
1640
+ query = Tag.select(:name).where(id: [tag1.id, tag2.id])
1641
+
1642
+ assert_equal ["Foo", "Foo"], query.map(&:name)
1643
+ assert_sql(/DISTINCT/) do
1644
+ assert_equal ["Foo"], query.distinct.map(&:name)
1645
+ end
1646
+ assert_sql(/DISTINCT/) do
1647
+ assert_equal ["Foo"], query.distinct(true).map(&:name)
1648
+ end
1649
+ assert_equal ["Foo", "Foo"], query.distinct(true).distinct(false).map(&:name)
1650
+ end
1651
+
1652
+ def test_doesnt_add_having_values_if_options_are_blank
1653
+ scope = Post.having("")
1654
+ assert_empty scope.having_clause
1655
+
1656
+ scope = Post.having([])
1657
+ assert_empty scope.having_clause
1658
+ end
1659
+
1660
+ def test_having_with_binds_for_both_where_and_having
1661
+ post = Post.first
1662
+ having_then_where = Post.having(id: post.id).where(title: post.title).group(:id, :author_id, :title, :body, :type, :legacy_comments_count, :taggings_with_delete_all_count, :taggings_with_destroy_count, :tags_count, :indestructible_tags_count, :tags_with_destroy_count, :tags_with_nullify_count)
1663
+ where_then_having = Post.where(title: post.title).having(id: post.id).group(:id, :author_id, :title, :body, :type, :legacy_comments_count, :taggings_with_delete_all_count, :taggings_with_destroy_count, :tags_count, :indestructible_tags_count, :tags_with_destroy_count, :tags_with_nullify_count)
1664
+
1665
+ assert_equal [post], having_then_where
1666
+ assert_equal [post], where_then_having
1667
+ end
1668
+
1669
+ def test_multiple_where_and_having_clauses
1670
+ puts "test_multiple_where_and_having_clauses"
1671
+ post = Post.first
1672
+ having_then_where = Post.having(id: post.id).where(title: post.title)
1673
+ .having(id: post.id).where(title: post.title).group(:id, :author_id, :title, :body, :type, :legacy_comments_count, :taggings_with_delete_all_count, :taggings_with_destroy_count, :tags_count, :indestructible_tags_count, :tags_with_destroy_count, :tags_with_nullify_count)
1674
+
1675
+ assert_equal [post], having_then_where
1676
+ end
1677
+
1678
+ def test_grouping_by_column_with_reserved_name
1679
+ assert_equal [], Possession.select(:where).group(:where).to_a
1680
+ end
1681
+
1682
+ def test_references_triggers_eager_loading
1683
+ scope = Post.includes(:comments)
1684
+ assert_not_predicate scope, :eager_loading?
1685
+ assert_predicate scope.references(:comments), :eager_loading?
1686
+ end
1687
+
1688
+ def test_references_doesnt_trigger_eager_loading_if_reference_not_included
1689
+ scope = Post.references(:comments)
1690
+ assert_not_predicate scope, :eager_loading?
1691
+ end
1692
+
1693
+ def test_automatically_added_where_references
1694
+ scope = Post.where(comments: { body: "Bla" })
1695
+ assert_equal ["comments"], scope.references_values
1696
+
1697
+ scope = Post.where("comments.body" => "Bla")
1698
+ assert_equal ["comments"], scope.references_values
1699
+ end
1700
+
1701
+ def test_automatically_added_where_not_references
1702
+ scope = Post.where.not(comments: { body: "Bla" })
1703
+ assert_equal ["comments"], scope.references_values
1704
+
1705
+ scope = Post.where.not("comments.body" => "Bla")
1706
+ assert_equal ["comments"], scope.references_values
1707
+ end
1708
+
1709
+ def test_automatically_added_having_references
1710
+ scope = Post.having(comments: { body: "Bla" })
1711
+ assert_equal ["comments"], scope.references_values
1712
+
1713
+ scope = Post.having("comments.body" => "Bla")
1714
+ assert_equal ["comments"], scope.references_values
1715
+ end
1716
+
1717
+ def test_automatically_added_order_references
1718
+ scope = Post.order("comments.body")
1719
+ assert_equal ["comments"], scope.references_values
1720
+
1721
+ scope = Post.order("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}")
1722
+ if current_adapter?(:OracleAdapter)
1723
+ assert_equal ["COMMENTS"], scope.references_values
1724
+ else
1725
+ assert_equal ["comments"], scope.references_values
1726
+ end
1727
+
1728
+ scope = Post.order("comments.body", "yaks.body")
1729
+ assert_equal ["comments", "yaks"], scope.references_values
1730
+
1731
+ # Don't infer yaks, let's not go down that road again...
1732
+ scope = Post.order("comments.body, yaks.body")
1733
+ assert_equal ["comments"], scope.references_values
1734
+
1735
+ scope = Post.order("comments.body asc")
1736
+ assert_equal ["comments"], scope.references_values
1737
+
1738
+ scope = Post.order("foo(comments.body)")
1739
+ assert_equal [], scope.references_values
1740
+ end
1741
+
1742
+ def test_automatically_added_reorder_references
1743
+ scope = Post.reorder("comments.body")
1744
+ assert_equal %w(comments), scope.references_values
1745
+
1746
+ scope = Post.reorder("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}")
1747
+ if current_adapter?(:OracleAdapter)
1748
+ assert_equal ["COMMENTS"], scope.references_values
1749
+ else
1750
+ assert_equal ["comments"], scope.references_values
1751
+ end
1752
+
1753
+ scope = Post.reorder("comments.body", "yaks.body")
1754
+ assert_equal %w(comments yaks), scope.references_values
1755
+
1756
+ # Don't infer yaks, let's not go down that road again...
1757
+ scope = Post.reorder("comments.body, yaks.body")
1758
+ assert_equal %w(comments), scope.references_values
1759
+
1760
+ scope = Post.reorder("comments.body asc")
1761
+ assert_equal %w(comments), scope.references_values
1762
+
1763
+ scope = Post.reorder("foo(comments.body)")
1764
+ assert_equal [], scope.references_values
1765
+ end
1766
+
1767
+ def test_order_with_reorder_nil_removes_the_order
1768
+ relation = Post.order(:title).reorder(nil)
1769
+
1770
+ assert_nil relation.order_values.first
1771
+ end
1772
+
1773
+ def test_reverse_order_with_reorder_nil_removes_the_order
1774
+ relation = Post.order(:title).reverse_order.reorder(nil)
1775
+
1776
+ assert_nil relation.order_values.first
1777
+ end
1778
+
1779
+ def test_reorder_with_first
1780
+ sql_log = capture_sql do
1781
+ message = <<~MSG.squish
1782
+ `.reorder(nil)` with `.first` / `.first!` no longer
1783
+ takes non-deterministic result in Rails 7.0.
1784
+ To continue taking non-deterministic result, use `.take` / `.take!` instead.
1785
+ MSG
1786
+ assert_deprecated(message) do
1787
+ assert Post.order(:title).reorder(nil).first
1788
+ end
1789
+ end
1790
+ assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
1791
+ end
1792
+
1793
+ def test_reorder_with_take
1794
+ sql_log = capture_sql do
1795
+ assert Post.order(:title).reorder(nil).take
1796
+ end
1797
+ assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
1798
+ end
1799
+
1800
+ def test_presence
1801
+ topics = Topic.all
1802
+
1803
+ # the first query is triggered because there are no topics yet.
1804
+ assert_queries(1) { assert topics.present? }
1805
+
1806
+ # checking if there are topics is used before you actually display them,
1807
+ # thus it shouldn't invoke an extra count query.
1808
+ assert_no_queries { assert topics.present? }
1809
+ assert_no_queries { assert_not topics.blank? }
1810
+
1811
+ # shows count of topics and loops after loading the query should not trigger extra queries either.
1812
+ assert_no_queries { topics.size }
1813
+ assert_no_queries { topics.length }
1814
+ assert_no_queries { topics.each }
1815
+
1816
+ # count always trigger the COUNT query.
1817
+ assert_queries(1) { topics.count }
1818
+
1819
+ assert_predicate topics, :loaded?
1820
+ end
1821
+
1822
+ def test_delete_by
1823
+ david = authors(:david)
1824
+
1825
+ assert_difference("Post.count", -3) { david.posts.delete_by(body: "hello") }
1826
+
1827
+ deleted = Author.delete_by(id: david.id)
1828
+ assert_equal 1, deleted
1829
+ end
1830
+
1831
+ def test_destroy_by
1832
+ david = authors(:david)
1833
+
1834
+ assert_difference("Post.count", -3) { david.posts.destroy_by(body: "hello") }
1835
+
1836
+ destroyed = Author.destroy_by(id: david.id)
1837
+ assert_equal [david], destroyed
1838
+ end
1839
+
1840
+ test "find_by with hash conditions returns the first matching record" do
1841
+ assert_equal posts(:eager_other), Post.order(:id).find_by(author_id: 2)
1842
+ end
1843
+
1844
+ test "find_by with non-hash conditions returns the first matching record" do
1845
+ assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = 2")
1846
+ end
1847
+
1848
+ test "find_by with multi-arg conditions returns the first matching record" do
1849
+ assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = ?", 2)
1850
+ end
1851
+
1852
+ test "find_by returns nil if the record is missing" do
1853
+ assert_nil Post.all.find_by("1 = 0")
1854
+ end
1855
+
1856
+ test "find_by doesn't have implicit ordering" do
1857
+ assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
1858
+ end
1859
+
1860
+ test "find_by requires at least one argument" do
1861
+ assert_raises(ArgumentError) { Post.all.find_by }
1862
+ end
1863
+
1864
+ test "find_by! with hash conditions returns the first matching record" do
1865
+ assert_equal posts(:eager_other), Post.order(:id).find_by!(author_id: 2)
1866
+ end
1867
+
1868
+ test "find_by! with non-hash conditions returns the first matching record" do
1869
+ assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = 2")
1870
+ end
1871
+
1872
+ test "find_by! with multi-arg conditions returns the first matching record" do
1873
+ assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = ?", 2)
1874
+ end
1875
+
1876
+ test "find_by! doesn't have implicit ordering" do
1877
+ assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
1878
+ end
1879
+
1880
+ test "find_by! raises RecordNotFound if the record is missing" do
1881
+ assert_raises(ActiveRecord::RecordNotFound) do
1882
+ Post.all.find_by!("1 = 0")
1883
+ end
1884
+ end
1885
+
1886
+ test "find_by! requires at least one argument" do
1887
+ assert_raises(ArgumentError) { Post.all.find_by! }
1888
+ end
1889
+
1890
+ test "loaded relations cannot be mutated by multi value methods" do
1891
+ relation = Post.all
1892
+ relation.to_a
1893
+
1894
+ assert_raises(ActiveRecord::ImmutableRelation) do
1895
+ relation.where! "foo"
1896
+ end
1897
+ end
1898
+
1899
+ test "loaded relations cannot be mutated by single value methods" do
1900
+ relation = Post.all
1901
+ relation.to_a
1902
+
1903
+ assert_raises(ActiveRecord::ImmutableRelation) do
1904
+ relation.limit! 5
1905
+ end
1906
+ end
1907
+
1908
+ test "loaded relations cannot be mutated by merge!" do
1909
+ relation = Post.all
1910
+ relation.to_a
1911
+
1912
+ assert_raises(ActiveRecord::ImmutableRelation) do
1913
+ relation.merge! where: "foo"
1914
+ end
1915
+ end
1916
+
1917
+ test "loaded relations cannot be mutated by extending!" do
1918
+ relation = Post.all
1919
+ relation.to_a
1920
+
1921
+ assert_raises(ActiveRecord::ImmutableRelation) do
1922
+ relation.extending! Module.new
1923
+ end
1924
+ end
1925
+
1926
+ test "relations with cached arel can't be mutated [internal API]" do
1927
+ relation = Post.all
1928
+ relation.arel
1929
+
1930
+ assert_raises(ActiveRecord::ImmutableRelation) { relation.limit!(5) }
1931
+ assert_raises(ActiveRecord::ImmutableRelation) { relation.where!("1 = 2") }
1932
+ end
1933
+
1934
+ test "relations show the records in #inspect" do
1935
+ relation = Post.limit(2)
1936
+ assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
1937
+ end
1938
+
1939
+ test "relations limit the records in #inspect at 10" do
1940
+ relation = Post.limit(11)
1941
+ assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
1942
+ end
1943
+
1944
+ test "relations don't load all records in #inspect" do
1945
+ assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
1946
+ Post.all.inspect
1947
+ end
1948
+ end
1949
+
1950
+ test "loading query is annotated in #inspect" do
1951
+ assert_sql(%r(/\* loading for inspect \*/)) do
1952
+ Post.all.inspect
1953
+ end
1954
+ end
1955
+
1956
+ test "already-loaded relations don't perform a new query in #inspect" do
1957
+ relation = Post.limit(2)
1958
+ relation.to_a
1959
+
1960
+ expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>"
1961
+
1962
+ assert_no_queries do
1963
+ assert_equal expected, relation.inspect
1964
+ end
1965
+ end
1966
+
1967
+ test "using a custom table affects the wheres" do
1968
+ post = posts(:welcome)
1969
+
1970
+ assert_equal post, custom_post_relation.where!(title: post.title).take
1971
+ end
1972
+
1973
+ test "using a custom table with joins affects the joins" do
1974
+ post = posts(:welcome)
1975
+
1976
+ assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).take
1977
+ end
1978
+
1979
+ test "arel_table respects a custom table" do
1980
+ assert_equal [posts(:sti_comments)], custom_post_relation.ranked_by_comments.limit_by(1).to_a
1981
+ end
1982
+
1983
+ test "alias_tracker respects a custom table" do
1984
+ assert_equal posts(:welcome), custom_post_relation("categories_posts").joins(:categories).first
1985
+ end
1986
+
1987
+ test "#load" do
1988
+ relation = Post.all
1989
+ assert_queries(1) do
1990
+ assert_equal relation, relation.load
1991
+ end
1992
+ assert_no_queries { relation.to_a }
1993
+ end
1994
+
1995
+ test "group with select and includes" do
1996
+ authors_count = Post.select("author_id, COUNT(author_id) AS num_posts").
1997
+ group("author_id").order("author_id").includes(:author).to_a
1998
+
1999
+ assert_no_queries do
2000
+ result = authors_count.map do |post|
2001
+ [post.num_posts, post.author&.name]
2002
+ end
2003
+
2004
+ expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
2005
+ assert_equal expected, result
2006
+ end
2007
+ end
2008
+
2009
+ test "joins with select" do
2010
+ posts = Post.joins(:author).select("id", "authors.author_address_id").order("posts.id").limit(3)
2011
+ assert_equal [1, 2, 4], posts.map(&:id)
2012
+ assert_equal [1, 1, 1], posts.map(&:author_address_id)
2013
+ end
2014
+
2015
+ test "joins with select custom attribute" do
2016
+ contract = Company.create!(name: "test").contracts.create!
2017
+ company = Company.joins(:contracts).select(:id, :metadata).find(contract.company_id)
2018
+ assert_equal contract.metadata, company.metadata
2019
+ end
2020
+
2021
+ test "joins with order by custom attribute" do
2022
+ companies = Company.create!([{ name: "test1" }, { name: "test2" }])
2023
+ companies.each { |company| company.contracts.create! }
2024
+ assert_equal companies, Company.joins(:contracts).order(:metadata, :count)
2025
+ assert_equal companies.reverse, Company.joins(:contracts).order(metadata: :desc, count: :desc)
2026
+ end
2027
+
2028
+ test "delegations do not leak to other classes" do
2029
+ Topic.all.by_lifo
2030
+ assert Topic.all.class.method_defined?(:by_lifo)
2031
+ assert_not_respond_to Post.all, :by_lifo
2032
+ end
2033
+
2034
+ def test_unscope_with_subquery
2035
+ p1 = Post.where(id: 1)
2036
+ p2 = Post.where(id: 2)
2037
+
2038
+ assert_not_equal p1, p2
2039
+
2040
+ comments = Comment.where(post: p1).unscope(where: :post_id).where(post: p2)
2041
+
2042
+ assert_not_equal p1.first.comments, comments
2043
+ assert_equal p2.first.comments, comments
2044
+ end
2045
+
2046
+ def test_unscope_with_merge
2047
+ p0 = Post.where(author_id: 0)
2048
+ p1 = Post.where(author_id: 1, comments_count: 1)
2049
+
2050
+ assert_equal [posts(:authorless)], p0
2051
+ assert_equal [posts(:thinking)], p1
2052
+
2053
+ comments = Comment.merge(p0).unscope(where: :author_id).where(post: p1)
2054
+
2055
+ assert_not_equal p0.first.comments, comments
2056
+ assert_equal p1.first.comments, comments
2057
+ end
2058
+
2059
+ def test_unscope_with_unknown_column
2060
+ comment = comments(:greetings)
2061
+ comment.update!(comments: 1)
2062
+
2063
+ comments = Comment.where(comments: 1).unscope(where: :unknown_column)
2064
+ assert_equal [comment], comments
2065
+
2066
+ comments = Comment.where(comments: 1).unscope(where: { comments: :unknown_column })
2067
+ assert_equal [comment], comments
2068
+ end
2069
+
2070
+ def test_unscope_specific_where_value
2071
+ posts = Post.where(title: "Welcome to the weblog", body: "Such a lovely day")
2072
+
2073
+ assert_equal 1, posts.count
2074
+ assert_equal 1, posts.unscope(where: :title).count
2075
+ assert_equal 1, posts.unscope(where: :body).count
2076
+ end
2077
+
2078
+ def test_unscope_with_aliased_column
2079
+ posts = Post.where(author: authors(:mary), text: "hullo").order(:id)
2080
+ assert_equal [posts(:misc_by_mary)], posts
2081
+
2082
+ posts = posts.unscope(where: :"posts.text")
2083
+ assert_equal posts(:eager_other, :misc_by_mary, :other_by_mary), posts
2084
+ end
2085
+
2086
+ def test_unscope_with_table_name_qualified_column
2087
+ comments = Comment.joins(:post).where("posts.id": posts(:thinking))
2088
+ assert_equal [comments(:does_it_hurt)], comments
2089
+
2090
+ comments = comments.where(id: comments(:greetings))
2091
+ assert_empty comments
2092
+
2093
+ comments = comments.unscope(where: :"posts.id")
2094
+ assert_equal [comments(:greetings)], comments
2095
+ end
2096
+
2097
+ def test_unscope_with_table_name_qualified_hash
2098
+ comments = Comment.joins(:post).where("posts.id": posts(:thinking))
2099
+ assert_equal [comments(:does_it_hurt)], comments
2100
+
2101
+ comments = comments.where(id: comments(:greetings))
2102
+ assert_empty comments
2103
+
2104
+ comments = comments.unscope(where: { posts: :id })
2105
+ assert_equal [comments(:greetings)], comments
2106
+ end
2107
+
2108
+ def test_unscope_with_arel_sql
2109
+ posts = Post.where(Arel.sql("'Welcome to the weblog'").eq(Post.arel_table[:title]))
2110
+
2111
+ assert_equal 1, posts.count
2112
+ assert_equal Post.count, posts.unscope(where: :title).count
2113
+
2114
+ posts = Post.where(Arel.sql("posts.title").eq("Welcome to the weblog"))
2115
+
2116
+ assert_equal 1, posts.count
2117
+ assert_equal 1, posts.unscope(where: :title).count
2118
+ end
2119
+
2120
+ def test_unscope_grouped_where
2121
+ posts = Post.where(
2122
+ title: ["Welcome to the weblog", "So I was thinking", nil]
2123
+ )
2124
+
2125
+ assert_equal 2, posts.count
2126
+ assert_equal Post.count, posts.unscope(where: :title).count
2127
+ end
2128
+
2129
+ def test_locked_should_not_build_arel
2130
+ posts = Post.locked
2131
+ assert_predicate posts, :locked?
2132
+ assert_nothing_raised { posts.lock!(false) }
2133
+ end
2134
+
2135
+ def test_relation_join_method
2136
+ assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.order(:id).join(",")
2137
+ end
2138
+
2139
+ def test_relation_with_private_kernel_method
2140
+ accounts = Account.all
2141
+ assert_equal [accounts(:signals37)], accounts.open
2142
+ assert_equal [accounts(:signals37)], accounts.available
2143
+
2144
+ sub_accounts = SubAccount.all
2145
+ assert_equal [accounts(:signals37)], sub_accounts.open
2146
+ assert_equal [accounts(:signals37)], sub_accounts.available
2147
+
2148
+ assert_equal [topics(:second)], topics(:first).open_replies
2149
+ end
2150
+
2151
+ def test_where_with_take_memoization
2152
+ 5.times do |idx|
2153
+ Post.create!(title: idx.to_s, body: idx.to_s)
2154
+ end
2155
+
2156
+ posts = Post.all
2157
+ first_post = posts.take
2158
+ third_post = posts.where(title: "3").take
2159
+
2160
+ assert_equal "3", third_post.title
2161
+ assert_not_same first_post, third_post
2162
+ end
2163
+
2164
+ def test_find_by_with_take_memoization
2165
+ 5.times do |idx|
2166
+ Post.create!(title: idx.to_s, body: idx.to_s)
2167
+ end
2168
+
2169
+ posts = Post.all
2170
+ first_post = posts.take
2171
+ third_post = posts.find_by(title: "3")
2172
+
2173
+ assert_equal "3", third_post.title
2174
+ assert_not_same first_post, third_post
2175
+ end
2176
+
2177
+ test "#skip_query_cache!" do
2178
+ Post.cache do
2179
+ assert_queries(1) do
2180
+ Post.all.load
2181
+ Post.all.load
2182
+ end
2183
+
2184
+ assert_queries(2) do
2185
+ Post.all.skip_query_cache!.load
2186
+ Post.all.skip_query_cache!.load
2187
+ end
2188
+ end
2189
+ end
2190
+
2191
+ test "#skip_query_cache! with an eager load" do
2192
+ Post.cache do
2193
+ assert_queries(1) do
2194
+ Post.eager_load(:comments).load
2195
+ Post.eager_load(:comments).load
2196
+ end
2197
+
2198
+ assert_queries(2) do
2199
+ Post.eager_load(:comments).skip_query_cache!.load
2200
+ Post.eager_load(:comments).skip_query_cache!.load
2201
+ end
2202
+ end
2203
+ end
2204
+
2205
+ test "#skip_query_cache! with a preload" do
2206
+ Post.cache do
2207
+ assert_queries(2) do
2208
+ Post.preload(:comments).load
2209
+ Post.preload(:comments).load
2210
+ end
2211
+
2212
+ assert_queries(4) do
2213
+ Post.preload(:comments).skip_query_cache!.load
2214
+ Post.preload(:comments).skip_query_cache!.load
2215
+ end
2216
+ end
2217
+ end
2218
+
2219
+ test "#where with set" do
2220
+ david = authors(:david)
2221
+ mary = authors(:mary)
2222
+
2223
+ authors = Author.where(name: ["David", "Mary"].to_set)
2224
+ assert_equal [david, mary], authors.order(:id)
2225
+ end
2226
+
2227
+ test "#where with empty set" do
2228
+ authors = Author.where(name: Set.new)
2229
+ assert_empty authors
2230
+ end
2231
+
2232
+ (ActiveRecord::Relation::MULTI_VALUE_METHODS - [:extending]).each do |method|
2233
+ test "#{method} with blank value" do
2234
+ authors = Author.public_send(method, [""])
2235
+ assert_empty authors.public_send(:"#{method}_values")
2236
+ end
2237
+ end
2238
+
2239
+ private
2240
+ def custom_post_relation(alias_name = "omg_posts")
2241
+ table_alias = Post.arel_table.alias(alias_name)
2242
+ table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias)
2243
+ predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata)
2244
+
2245
+ ActiveRecord::Relation.create(
2246
+ Post,
2247
+ table: table_alias,
2248
+ predicate_builder: predicate_builder
2249
+ )
2250
+ end
2251
+ end