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,1676 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper"
4
+ require "models/post"
5
+ require "models/author"
6
+ require "models/account"
7
+ require "models/categorization"
8
+ require "models/comment"
9
+ require "models/company"
10
+ require "models/tagging"
11
+ require "models/topic"
12
+ require "models/reply"
13
+ require "models/rating"
14
+ require "models/entrant"
15
+ require "models/project"
16
+ require "models/developer"
17
+ require "models/computer"
18
+ require "models/customer"
19
+ require "models/toy"
20
+ require "models/matey"
21
+ require "models/dog"
22
+ require "models/car"
23
+ require "models/tyre"
24
+ require "models/subscriber"
25
+ require "models/non_primary_key"
26
+ require "support/stubs/strong_parameters"
27
+
28
+ class FinderTest < ActiveRecord::TestCase
29
+ fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :author_addresses, :customers, :categories, :categorizations, :cars
30
+
31
+ def test_find_by_id_with_hash
32
+ assert_nothing_raised do
33
+ Post.find_by_id(limit: 1)
34
+ end
35
+ end
36
+
37
+ def test_find_by_title_and_id_with_hash
38
+ assert_nothing_raised do
39
+ Post.find_by_title_and_id("foo", limit: 1)
40
+ end
41
+ end
42
+
43
+ def test_find
44
+ assert_equal(topics(:first).title, Topic.find(1).title)
45
+ end
46
+
47
+ def test_find_with_hash_parameter
48
+ assert_raises(ActiveRecord::RecordNotFound) { Post.find(foo: "bar") }
49
+ assert_raises(ActiveRecord::RecordNotFound) { Post.find(foo: "bar", bar: "baz") }
50
+ end
51
+
52
+ def test_find_with_proc_parameter_and_block
53
+ exception = assert_raises(RuntimeError) do
54
+ Topic.all.find(-> { raise "should happen" }) { |e| e.title == "non-existing-title" }
55
+ end
56
+ assert_equal "should happen", exception.message
57
+
58
+ assert_nothing_raised do
59
+ Topic.all.find(-> { raise "should not happen" }) { |e| e.title == topics(:first).title }
60
+ end
61
+ end
62
+
63
+ def test_find_with_ids_returning_ordered
64
+ records = Topic.find([4, 2, 5])
65
+ assert_equal "The Fourth Topic of the day", records[0].title
66
+ assert_equal "The Second Topic of the day", records[1].title
67
+ assert_equal "The Fifth Topic of the day", records[2].title
68
+
69
+ records = Topic.find(4, 2, 5)
70
+ assert_equal "The Fourth Topic of the day", records[0].title
71
+ assert_equal "The Second Topic of the day", records[1].title
72
+ assert_equal "The Fifth Topic of the day", records[2].title
73
+
74
+ records = Topic.find(["4", "2", "5"])
75
+ assert_equal "The Fourth Topic of the day", records[0].title
76
+ assert_equal "The Second Topic of the day", records[1].title
77
+ assert_equal "The Fifth Topic of the day", records[2].title
78
+
79
+ records = Topic.find("4", "2", "5")
80
+ assert_equal "The Fourth Topic of the day", records[0].title
81
+ assert_equal "The Second Topic of the day", records[1].title
82
+ assert_equal "The Fifth Topic of the day", records[2].title
83
+ end
84
+
85
+ def test_find_with_ids_and_order_clause
86
+ # The order clause takes precedence over the informed ids
87
+ records = Topic.order(:author_name).find([5, 3, 1])
88
+ assert_equal "The Third Topic of the day", records[0].title
89
+ assert_equal "The First Topic", records[1].title
90
+ assert_equal "The Fifth Topic of the day", records[2].title
91
+
92
+ records = Topic.order(:id).find([5, 3, 1])
93
+ assert_equal "The First Topic", records[0].title
94
+ assert_equal "The Third Topic of the day", records[1].title
95
+ assert_equal "The Fifth Topic of the day", records[2].title
96
+ end
97
+
98
+ def test_find_with_ids_with_limit_and_order_clause
99
+ # The order clause takes precedence over the informed ids
100
+ records = Topic.limit(2).order(:id).find([5, 3, 1])
101
+ assert_equal 2, records.size
102
+ assert_equal "The First Topic", records[0].title
103
+ assert_equal "The Third Topic of the day", records[1].title
104
+ end
105
+
106
+ def test_find_with_ids_and_limit
107
+ records = Topic.limit(3).find([3, 2, 5, 1, 4])
108
+ assert_equal 3, records.size
109
+ assert_equal "The Third Topic of the day", records[0].title
110
+ assert_equal "The Second Topic of the day", records[1].title
111
+ assert_equal "The Fifth Topic of the day", records[2].title
112
+ end
113
+
114
+ def test_find_with_ids_where_and_limit
115
+ # Please note that Topic 1 is the only not approved so
116
+ # if it were among the first 3 it would raise an ActiveRecord::RecordNotFound
117
+ records = Topic.where(approved: true).limit(3).find([3, 2, 5, 1, 4])
118
+ assert_equal 3, records.size
119
+ assert_equal "The Third Topic of the day", records[0].title
120
+ assert_equal "The Second Topic of the day", records[1].title
121
+ assert_equal "The Fifth Topic of the day", records[2].title
122
+ end
123
+
124
+ def test_find_with_ids_and_offset
125
+ records = Topic.offset(2).find([3, 2, 5, 1, 4])
126
+ assert_equal 3, records.size
127
+ assert_equal "The Fifth Topic of the day", records[0].title
128
+ assert_equal "The First Topic", records[1].title
129
+ assert_equal "The Fourth Topic of the day", records[2].title
130
+ end
131
+
132
+ def test_find_with_ids_with_no_id_passed
133
+ exception = assert_raises(ActiveRecord::RecordNotFound) { Topic.find }
134
+ assert_equal exception.model, "Topic"
135
+ assert_equal exception.primary_key, "id"
136
+ end
137
+
138
+ def test_find_with_ids_with_id_out_of_range
139
+ exception = assert_raises(ActiveRecord::RecordNotFound) do
140
+ Topic.find("9999999999999999999999999999999")
141
+ end
142
+
143
+ assert_equal exception.model, "Topic"
144
+ assert_equal exception.primary_key, "id"
145
+ end
146
+
147
+ def test_find_passing_active_record_object_is_not_permitted
148
+ assert_raises(ArgumentError) do
149
+ Topic.find(Topic.last)
150
+ end
151
+ end
152
+
153
+ def test_symbols_table_ref
154
+ gc_disabled = GC.disable
155
+ Post.where("author_id" => nil) # warm up
156
+ x = Symbol.all_symbols.count
157
+ Post.where("title" => { "xxxqqqq" => "bar" })
158
+ assert_equal x, Symbol.all_symbols.count
159
+ ensure
160
+ GC.enable if gc_disabled == false
161
+ end
162
+
163
+ # find should handle strings that come from URLs
164
+ # (example: Category.find(params[:id]))
165
+ def test_find_with_string
166
+ assert_equal(Topic.find(1).title, Topic.find("1").title)
167
+ end
168
+
169
+ def test_exists
170
+ assert_equal true, Topic.exists?(1)
171
+ assert_equal true, Topic.exists?("1")
172
+ assert_equal true, Topic.exists?(title: "The First Topic")
173
+ assert_equal true, Topic.exists?(heading: "The First Topic")
174
+ assert_equal true, Topic.exists?(author_name: "Mary", approved: true)
175
+ assert_equal true, Topic.exists?(["parent_id = ?", 1])
176
+ assert_equal true, Topic.exists?(id: [1, 9999])
177
+
178
+ assert_equal false, Topic.exists?(45)
179
+ assert_equal false, Topic.exists?(9999999999999999999999999999999)
180
+ assert_equal false, Topic.exists?(Topic.new.id)
181
+
182
+ assert_raise(NoMethodError) { Topic.exists?([1, 2]) }
183
+ end
184
+
185
+ def test_exists_with_scope
186
+ davids = Author.where(name: "David")
187
+ assert_equal true, davids.exists?
188
+ assert_equal true, davids.exists?(authors(:david).id)
189
+ assert_equal false, davids.exists?(authors(:mary).id)
190
+ assert_equal false, davids.exists?("42")
191
+ assert_equal false, davids.exists?(42)
192
+ assert_equal false, davids.exists?(davids.new.id)
193
+
194
+ fake = Author.where(name: "fake author")
195
+ assert_equal false, fake.exists?
196
+ assert_equal false, fake.exists?(authors(:david).id)
197
+ end
198
+
199
+ def test_exists_uses_existing_scope
200
+ post = authors(:david).posts.first
201
+ authors = Author.includes(:posts).where(name: "David", posts: { id: post.id })
202
+ assert_equal true, authors.exists?(authors(:david).id)
203
+ end
204
+
205
+ def test_any_with_scope_on_hash_includes
206
+ post = authors(:david).posts.first
207
+ categories = Categorization.includes(author: :posts).where(posts: { id: post.id })
208
+ assert_equal true, categories.exists?
209
+ end
210
+
211
+ def test_exists_with_polymorphic_relation
212
+ post = Post.create!(title: "Post", body: "default", taggings: [Tagging.new(comment: "tagging comment")])
213
+ relation = Post.tagged_with_comment("tagging comment")
214
+
215
+ assert_equal true, relation.exists?(title: ["Post"])
216
+ assert_equal true, relation.exists?(["title LIKE ?", "Post%"])
217
+ assert_equal true, relation.exists?
218
+ assert_equal true, relation.exists?(post.id)
219
+ assert_equal true, relation.exists?(post.id.to_s)
220
+
221
+ assert_equal false, relation.exists?(false)
222
+ end
223
+
224
+ def test_exists_with_string
225
+ assert_equal false, Subscriber.exists?("foo")
226
+ assert_equal false, Subscriber.exists?(" ")
227
+
228
+ Subscriber.create!(id: "foo")
229
+ Subscriber.create!(id: " ")
230
+
231
+ assert_equal true, Subscriber.exists?("foo")
232
+ assert_equal true, Subscriber.exists?(" ")
233
+ end
234
+
235
+ def test_exists_with_strong_parameters
236
+ assert_equal false, Subscriber.exists?(ProtectedParams.new(nick: "foo").permit!)
237
+
238
+ Subscriber.create!(nick: "foo")
239
+
240
+ assert_equal true, Subscriber.exists?(ProtectedParams.new(nick: "foo").permit!)
241
+
242
+ assert_raises(ActiveModel::ForbiddenAttributesError) do
243
+ Subscriber.exists?(ProtectedParams.new(nick: "foo"))
244
+ end
245
+ end
246
+
247
+ def test_exists_passing_active_record_object_is_not_permitted
248
+ assert_raises(ArgumentError) do
249
+ Topic.exists?(Topic.new)
250
+ end
251
+ end
252
+
253
+ def test_exists_does_not_select_columns_without_alias
254
+ c = Topic.connection
255
+ assert_sql(/SELECT 1 AS one FROM #{Regexp.escape(c.quote_table_name("topics"))}/i) do
256
+ Topic.exists?
257
+ end
258
+ end
259
+
260
+ def test_exists_returns_true_with_one_record_and_no_args
261
+ assert_equal true, Topic.exists?
262
+ end
263
+
264
+ def test_exists_returns_false_with_false_arg
265
+ assert_equal false, Topic.exists?(false)
266
+ end
267
+
268
+ # exists? should handle nil for id's that come from URLs and always return false
269
+ # (example: Topic.exists?(params[:id])) where params[:id] is nil
270
+ def test_exists_with_nil_arg
271
+ assert_equal false, Topic.exists?(nil)
272
+ assert_equal true, Topic.exists?
273
+
274
+ assert_equal false, Topic.first.replies.exists?(nil)
275
+ assert_equal true, Topic.first.replies.exists?
276
+ end
277
+
278
+ def test_exists_with_empty_hash_arg
279
+ assert_equal true, Topic.exists?({})
280
+ end
281
+
282
+ def test_exists_with_distinct_and_offset_and_joins
283
+ assert Post.left_joins(:comments).distinct.offset(10).exists?
284
+ assert_not Post.left_joins(:comments).distinct.offset(11).exists?
285
+ end
286
+
287
+ def test_exists_with_distinct_and_offset_and_select
288
+ assert Post.select(:body).distinct.offset(4).exists?
289
+ assert_not Post.select(:body).distinct.offset(5).exists?
290
+ end
291
+
292
+ def test_exists_with_distinct_and_offset_and_eagerload_and_order
293
+ assert Post.eager_load(:comments).distinct.offset(10).merge(Comment.order(post_id: :asc)).exists?
294
+ assert_not Post.eager_load(:comments).distinct.offset(11).merge(Comment.order(post_id: :asc)).exists?
295
+ end
296
+
297
+ # Ensure +exists?+ runs without an error by excluding distinct value.
298
+ # See https://github.com/rails/rails/pull/26981.
299
+ def test_exists_with_order_and_distinct
300
+ assert_equal true, Topic.order(:id).distinct.exists?
301
+ end
302
+
303
+ # Ensure +exists?+ runs without an error by excluding order value.
304
+ def test_exists_with_order
305
+ assert_equal true, Topic.order(Arel.sql("invalid sql here")).exists?
306
+ end
307
+
308
+ def test_exists_with_large_number
309
+ assert_equal true, Topic.where(id: [1, 9223372036854775808]).exists?
310
+ assert_equal true, Topic.where(id: 1..9223372036854775808).exists?
311
+ assert_equal true, Topic.where(id: -9223372036854775809..9223372036854775808).exists?
312
+ assert_equal false, Topic.where(id: 9223372036854775808..9223372036854775809).exists?
313
+ assert_equal false, Topic.where(id: -9223372036854775810..-9223372036854775809).exists?
314
+ assert_equal false, Topic.where(id: 9223372036854775808..1).exists?
315
+ assert_equal true, Topic.where(id: 1).or(Topic.where(id: 9223372036854775808)).exists?
316
+ assert_equal true, Topic.where.not(id: 9223372036854775808).exists?
317
+ end
318
+
319
+ def test_exists_with_joins
320
+ assert_equal true, Topic.joins(:replies).where(replies_topics: { approved: true }).order("replies_topics.created_at DESC").exists?
321
+ end
322
+
323
+ def test_exists_with_left_joins
324
+ assert_equal true, Topic.left_joins(:replies).where(replies_topics: { approved: true }).order("replies_topics.created_at DESC").exists?
325
+ end
326
+
327
+ def test_exists_with_eager_load
328
+ assert_equal true, Topic.eager_load(:replies).where(replies_topics: { approved: true }).order("replies_topics.created_at DESC").exists?
329
+ end
330
+
331
+ def test_exists_with_includes_limit_and_empty_result
332
+ assert_no_queries { assert_equal false, Topic.includes(:replies).limit(0).exists? }
333
+ assert_queries(1) { assert_equal false, Topic.includes(:replies).limit(1).where("0 = 1").exists? }
334
+ end
335
+
336
+ def test_exists_with_distinct_association_includes_and_limit
337
+ author = Author.first
338
+ unique_categorized_posts = author.unique_categorized_posts.includes(:special_comments)
339
+ assert_no_queries { assert_equal false, unique_categorized_posts.limit(0).exists? }
340
+ assert_queries(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
341
+ end
342
+
343
+ def test_exists_with_distinct_association_includes_limit_and_order
344
+ author = Author.first
345
+ unique_categorized_posts = author.unique_categorized_posts.includes(:special_comments).order("comments.tags_count DESC")
346
+ assert_no_queries { assert_equal false, unique_categorized_posts.limit(0).exists? }
347
+ assert_queries(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
348
+ end
349
+
350
+ def test_exists_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
351
+ ratings = developers(:david).ratings.includes(comment: :post).where(posts: { id: 1 })
352
+ assert_queries(1) { assert_not_predicate ratings.limit(1), :exists? }
353
+ end
354
+
355
+ def test_exists_with_empty_table_and_no_args_given
356
+ Topic.delete_all
357
+ assert_equal false, Topic.exists?
358
+ end
359
+
360
+ def test_exists_with_aggregate_having_three_mappings
361
+ existing_address = customers(:david).address
362
+ assert_equal true, Customer.exists?(address: existing_address)
363
+ end
364
+
365
+ def test_exists_with_aggregate_having_three_mappings_with_one_difference
366
+ existing_address = customers(:david).address
367
+ assert_equal false, Customer.exists?(address: Address.new(existing_address.street, existing_address.city, existing_address.country + "1"))
368
+ assert_equal false, Customer.exists?(address: Address.new(existing_address.street, existing_address.city + "1", existing_address.country))
369
+ assert_equal false, Customer.exists?(address: Address.new(existing_address.street + "1", existing_address.city, existing_address.country))
370
+ end
371
+
372
+ def test_exists_does_not_instantiate_records
373
+ assert_not_called(Developer, :instantiate) do
374
+ Developer.exists?
375
+ end
376
+ end
377
+
378
+ def test_include_on_unloaded_relation_with_match
379
+ assert_sql(/1 AS one.*LIMIT/) do
380
+ assert_equal true, Customer.where(name: "David").include?(customers(:david))
381
+ end
382
+ end
383
+
384
+ def test_include_on_unloaded_relation_without_match
385
+ assert_sql(/1 AS one.*LIMIT/) do
386
+ assert_equal false, Customer.where(name: "David").include?(customers(:mary))
387
+ end
388
+ end
389
+
390
+ def test_include_on_unloaded_relation_with_mismatched_class
391
+ topic = topics(:first)
392
+ assert Customer.exists?(topic.id)
393
+
394
+ assert_no_queries do
395
+ assert_equal false, Customer.where(name: "David").include?(topic)
396
+ end
397
+ end
398
+
399
+ def test_include_on_unloaded_relation_with_offset
400
+ assert_sql(/ORDER BY name ASC/) do
401
+ assert_equal true, Customer.offset(1).order("name ASC").include?(customers(:mary))
402
+ end
403
+ end
404
+
405
+ def test_include_on_unloaded_relation_with_limit
406
+ mary = customers(:mary)
407
+ barney = customers(:barney)
408
+ david = customers(:david)
409
+
410
+ assert_equal false, Customer.order(id: :desc).limit(2).include?(david)
411
+ assert_equal true, Customer.order(id: :desc).limit(2).include?(barney)
412
+ assert_equal true, Customer.order(id: :desc).limit(2).include?(mary)
413
+ end
414
+
415
+ def test_include_on_unloaded_relation_with_having_referencing_aliased_select
416
+ skip if current_adapter?(:PostgreSQLAdapter)
417
+ bob = authors(:bob)
418
+ mary = authors(:mary)
419
+
420
+ assert_equal false, Author.select("COUNT(*) as total_posts", "authors.*").joins(:posts).group(:id).having("total_posts > 2").include?(bob)
421
+ assert_equal true, Author.select("COUNT(*) as total_posts", "authors.*").joins(:posts).group(:id).having("total_posts > 2").include?(mary)
422
+ end
423
+
424
+ def test_include_on_loaded_relation_with_match
425
+ customers = Customer.where(name: "David").load
426
+ david = customers(:david)
427
+
428
+ assert_no_queries do
429
+ assert_equal true, customers.include?(david)
430
+ end
431
+ end
432
+
433
+ def test_include_on_loaded_relation_without_match
434
+ customers = Customer.where(name: "David").load
435
+ mary = customers(:mary)
436
+
437
+ assert_no_queries do
438
+ assert_equal false, customers.include?(mary)
439
+ end
440
+ end
441
+
442
+ def test_member_on_unloaded_relation_with_match
443
+ assert_sql(/1 AS one.*LIMIT/) do
444
+ assert_equal true, Customer.where(name: "David").member?(customers(:david))
445
+ end
446
+ end
447
+
448
+ def test_member_on_unloaded_relation_without_match
449
+ assert_sql(/1 AS one.*LIMIT/) do
450
+ assert_equal false, Customer.where(name: "David").member?(customers(:mary))
451
+ end
452
+ end
453
+
454
+ def test_member_on_unloaded_relation_with_mismatched_class
455
+ topic = topics(:first)
456
+ assert Customer.exists?(topic.id)
457
+
458
+ assert_no_queries do
459
+ assert_equal false, Customer.where(name: "David").member?(topic)
460
+ end
461
+ end
462
+
463
+ def test_member_on_unloaded_relation_with_offset
464
+ assert_sql(/ORDER BY name ASC/) do
465
+ assert_equal true, Customer.offset(1).order("name ASC").member?(customers(:mary))
466
+ end
467
+ end
468
+
469
+ def test_member_on_unloaded_relation_with_limit
470
+ mary = customers(:mary)
471
+ barney = customers(:barney)
472
+ david = customers(:david)
473
+
474
+ assert_equal false, Customer.order(id: :desc).limit(2).member?(david)
475
+ assert_equal true, Customer.order(id: :desc).limit(2).member?(barney)
476
+ assert_equal true, Customer.order(id: :desc).limit(2).member?(mary)
477
+ end
478
+
479
+ def test_member_on_loaded_relation_with_match
480
+ customers = Customer.where(name: "David").load
481
+ david = customers(:david)
482
+
483
+ assert_no_queries do
484
+ assert_equal true, customers.member?(david)
485
+ end
486
+ end
487
+
488
+ def test_member_on_loaded_relation_without_match
489
+ customers = Customer.where(name: "David").load
490
+ mary = customers(:mary)
491
+
492
+ assert_no_queries do
493
+ assert_equal false, customers.member?(mary)
494
+ end
495
+ end
496
+
497
+ def test_find_by_array_of_one_id
498
+ assert_kind_of(Array, Topic.find([ 1 ]))
499
+ assert_equal(1, Topic.find([ 1 ]).length)
500
+ end
501
+
502
+ def test_find_by_ids
503
+ assert_equal 2, Topic.find(1, 2).size
504
+ assert_equal topics(:second).title, Topic.find([2]).first.title
505
+ end
506
+
507
+ def test_find_by_ids_with_limit_and_offset
508
+ assert_equal 2, Entrant.limit(2).find([1, 3, 2]).size
509
+ entrants = Entrant.limit(3).offset(2).find([1, 3, 2])
510
+ assert_equal 1, entrants.size
511
+ assert_equal "Ruby Guru", entrants.first.name
512
+
513
+ # Also test an edge case: If you have 11 results, and you set a
514
+ # limit of 3 and offset of 9, then you should find that there
515
+ # will be only 2 results, regardless of the limit.
516
+ devs = Developer.all
517
+ last_devs = Developer.limit(3).offset(9).find(devs.map(&:id).sort)
518
+ assert_equal 2, last_devs.size
519
+ assert_equal "fixture_10", last_devs[0].name
520
+ assert_equal "Jamis", last_devs[1].name
521
+ end
522
+
523
+ def test_find_with_large_number
524
+ assert_queries(0) do
525
+ assert_raises(ActiveRecord::RecordNotFound) { Topic.find("9999999999999999999999999999999") }
526
+ end
527
+ end
528
+
529
+ def test_find_by_with_large_number
530
+ assert_queries(0) do
531
+ assert_nil Topic.find_by(id: "9999999999999999999999999999999")
532
+ end
533
+ end
534
+
535
+ def test_find_by_id_with_large_number
536
+ assert_queries(0) do
537
+ assert_nil Topic.find_by_id("9999999999999999999999999999999")
538
+ end
539
+ end
540
+
541
+ def test_find_on_relation_with_large_number
542
+ assert_raises(ActiveRecord::RecordNotFound) do
543
+ Topic.where("1=1").find(9999999999999999999999999999999)
544
+ end
545
+ assert_equal topics(:first), Topic.where(id: [1, 9999999999999999999999999999999]).find(1)
546
+ end
547
+
548
+ def test_find_by_on_relation_with_large_number
549
+ assert_nil Topic.where("1=1").find_by(id: 9999999999999999999999999999999)
550
+ assert_equal topics(:first), Topic.where(id: [1, 9999999999999999999999999999999]).find_by(id: 1)
551
+ end
552
+
553
+ def test_find_by_bang_on_relation_with_large_number
554
+ assert_raises(ActiveRecord::RecordNotFound) do
555
+ Topic.where("1=1").find_by!(id: 9999999999999999999999999999999)
556
+ end
557
+ assert_equal topics(:first), Topic.where(id: [1, 9999999999999999999999999999999]).find_by!(id: 1)
558
+ end
559
+
560
+ def test_find_an_empty_array
561
+ empty_array = []
562
+ result = Topic.find(empty_array)
563
+ assert_equal [], result
564
+ assert_not_same empty_array, result
565
+ end
566
+
567
+ def test_find_doesnt_have_implicit_ordering
568
+ assert_sql(/^((?!ORDER).)*$/) { Topic.find(1) }
569
+ end
570
+
571
+ def test_find_by_ids_missing_one
572
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1, 2, 45) }
573
+ end
574
+
575
+ def test_find_with_group_and_sanitized_having_method
576
+ developers = Developer.group(:salary).having("sum(salary) > ?", 10000).select("salary").to_a
577
+ assert_equal 3, developers.size
578
+ assert_equal 3, developers.map(&:salary).uniq.size
579
+ assert developers.all? { |developer| developer.salary > 10000 }
580
+ end
581
+
582
+ def test_find_with_entire_select_statement
583
+ topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
584
+
585
+ assert_equal(1, topics.size)
586
+ assert_equal(topics(:second).title, topics.first.title)
587
+ end
588
+
589
+ def test_find_with_prepared_select_statement
590
+ topics = Topic.find_by_sql ["SELECT * FROM topics WHERE author_name = ?", "Mary"]
591
+
592
+ assert_equal(1, topics.size)
593
+ assert_equal(topics(:second).title, topics.first.title)
594
+ end
595
+
596
+ def test_find_by_sql_with_sti_on_joined_table
597
+ accounts = Account.find_by_sql("SELECT * FROM accounts INNER JOIN companies ON companies.id = accounts.firm_id")
598
+ assert_equal [Account], accounts.collect(&:class).uniq
599
+ end
600
+
601
+ def test_find_by_association_subquery
602
+ firm = companies(:first_firm)
603
+ assert_equal firm.account, Account.find_by(firm: Firm.where(id: firm))
604
+ assert_equal firm.account, Account.find_by(firm_id: Firm.where(id: firm))
605
+ end
606
+
607
+ def test_find_by_and_where_consistency_with_active_record_instance
608
+ firm = companies(:first_firm)
609
+ assert_equal Account.where(firm_id: firm).take, Account.find_by(firm_id: firm)
610
+ end
611
+
612
+ def test_find_by_with_alias
613
+ account = accounts(:last_account)
614
+ assert_equal account, Account.find_by(available_credit: account.available_credit)
615
+ end
616
+
617
+ def test_take
618
+ assert_equal topics(:first), Topic.where("title = 'The First Topic'").take
619
+ end
620
+
621
+ def test_take_failing
622
+ assert_nil Topic.where("title = 'This title does not exist'").take
623
+ end
624
+
625
+ def test_take_bang_present
626
+ assert_nothing_raised do
627
+ assert_equal topics(:second), Topic.where("title = 'The Second Topic of the day'").take!
628
+ end
629
+ end
630
+
631
+ def test_take_bang_missing
632
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
633
+ Topic.where("title = 'This title does not exist'").take!
634
+ end
635
+ end
636
+
637
+ def test_first
638
+ assert_equal topics(:second).title, Topic.where("title = 'The Second Topic of the day'").first.title
639
+ end
640
+
641
+ def test_first_failing
642
+ assert_nil Topic.where("title = 'The Second Topic of the day!'").first
643
+ end
644
+
645
+ def test_first_bang_present
646
+ assert_nothing_raised do
647
+ assert_equal topics(:second), Topic.where("title = 'The Second Topic of the day'").first!
648
+ end
649
+ end
650
+
651
+ def test_first_bang_missing
652
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
653
+ Topic.where("title = 'This title does not exist'").first!
654
+ end
655
+ end
656
+
657
+ def test_first_have_primary_key_order_by_default
658
+ expected = topics(:first)
659
+ expected.touch # PostgreSQL changes the default order if no order clause is used
660
+ assert_equal expected, Topic.first
661
+ assert_equal expected, Topic.limit(5).first
662
+ assert_equal expected, Topic.order(nil).first
663
+ end
664
+
665
+ def test_model_class_responds_to_first_bang
666
+ assert Topic.first!
667
+ Topic.delete_all
668
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
669
+ Topic.first!
670
+ end
671
+ end
672
+
673
+ def test_second
674
+ assert_equal topics(:second).title, Topic.second.title
675
+ end
676
+
677
+ def test_second_with_offset
678
+ assert_equal topics(:fifth), Topic.offset(3).second
679
+ end
680
+
681
+ def test_second_have_primary_key_order_by_default
682
+ expected = topics(:second)
683
+ expected.touch # PostgreSQL changes the default order if no order clause is used
684
+ assert_equal expected, Topic.second
685
+ assert_equal expected, Topic.limit(5).second
686
+ assert_equal expected, Topic.order(nil).second
687
+ end
688
+
689
+ def test_model_class_responds_to_second_bang
690
+ assert Topic.second!
691
+ Topic.delete_all
692
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
693
+ Topic.second!
694
+ end
695
+ end
696
+
697
+ def test_third
698
+ assert_equal topics(:third).title, Topic.third.title
699
+ end
700
+
701
+ def test_third_with_offset
702
+ assert_equal topics(:fifth), Topic.offset(2).third
703
+ end
704
+
705
+ def test_third_have_primary_key_order_by_default
706
+ expected = topics(:third)
707
+ expected.touch # PostgreSQL changes the default order if no order clause is used
708
+ assert_equal expected, Topic.third
709
+ assert_equal expected, Topic.limit(5).third
710
+ assert_equal expected, Topic.order(nil).third
711
+ end
712
+
713
+ def test_model_class_responds_to_third_bang
714
+ assert Topic.third!
715
+ Topic.delete_all
716
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
717
+ Topic.third!
718
+ end
719
+ end
720
+
721
+ def test_fourth
722
+ assert_equal topics(:fourth).title, Topic.fourth.title
723
+ end
724
+
725
+ def test_fourth_with_offset
726
+ assert_equal topics(:fifth), Topic.offset(1).fourth
727
+ end
728
+
729
+ def test_fourth_have_primary_key_order_by_default
730
+ expected = topics(:fourth)
731
+ expected.touch # PostgreSQL changes the default order if no order clause is used
732
+ assert_equal expected, Topic.fourth
733
+ assert_equal expected, Topic.limit(5).fourth
734
+ assert_equal expected, Topic.order(nil).fourth
735
+ end
736
+
737
+ def test_model_class_responds_to_fourth_bang
738
+ assert Topic.fourth!
739
+ Topic.delete_all
740
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
741
+ Topic.fourth!
742
+ end
743
+ end
744
+
745
+ def test_fifth
746
+ assert_equal topics(:fifth).title, Topic.fifth.title
747
+ end
748
+
749
+ def test_fifth_with_offset
750
+ assert_equal topics(:fifth), Topic.offset(0).fifth
751
+ end
752
+
753
+ def test_fifth_have_primary_key_order_by_default
754
+ expected = topics(:fifth)
755
+ expected.touch # PostgreSQL changes the default order if no order clause is used
756
+ assert_equal expected, Topic.fifth
757
+ assert_equal expected, Topic.limit(5).fifth
758
+ assert_equal expected, Topic.order(nil).fifth
759
+ end
760
+
761
+ def test_model_class_responds_to_fifth_bang
762
+ assert Topic.fifth!
763
+ Topic.delete_all
764
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
765
+ Topic.fifth!
766
+ end
767
+ end
768
+
769
+ def test_second_to_last
770
+ assert_equal topics(:fourth).title, Topic.second_to_last.title
771
+
772
+ # test with offset
773
+ assert_equal topics(:fourth), Topic.offset(1).second_to_last
774
+ assert_equal topics(:fourth), Topic.offset(2).second_to_last
775
+ assert_equal topics(:fourth), Topic.offset(3).second_to_last
776
+ assert_nil Topic.offset(4).second_to_last
777
+ assert_nil Topic.offset(5).second_to_last
778
+
779
+ # test with limit
780
+ assert_nil Topic.limit(1).second
781
+ assert_nil Topic.limit(1).second_to_last
782
+ end
783
+
784
+ def test_second_to_last_have_primary_key_order_by_default
785
+ expected = topics(:fourth)
786
+ expected.touch # PostgreSQL changes the default order if no order clause is used
787
+ assert_equal expected, Topic.second_to_last
788
+ end
789
+
790
+ def test_model_class_responds_to_second_to_last_bang
791
+ assert Topic.second_to_last!
792
+ Topic.delete_all
793
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
794
+ Topic.second_to_last!
795
+ end
796
+ end
797
+
798
+ def test_third_to_last
799
+ assert_equal topics(:third).title, Topic.third_to_last.title
800
+
801
+ # test with offset
802
+ assert_equal topics(:third), Topic.offset(1).third_to_last
803
+ assert_equal topics(:third), Topic.offset(2).third_to_last
804
+ assert_nil Topic.offset(3).third_to_last
805
+ assert_nil Topic.offset(4).third_to_last
806
+ assert_nil Topic.offset(5).third_to_last
807
+
808
+ # test with limit
809
+ assert_nil Topic.limit(1).third
810
+ assert_nil Topic.limit(1).third_to_last
811
+ assert_nil Topic.limit(2).third
812
+ assert_nil Topic.limit(2).third_to_last
813
+ end
814
+
815
+ def test_third_to_last_have_primary_key_order_by_default
816
+ expected = topics(:third)
817
+ expected.touch # PostgreSQL changes the default order if no order clause is used
818
+ assert_equal expected, Topic.third_to_last
819
+ end
820
+
821
+ def test_model_class_responds_to_third_to_last_bang
822
+ assert Topic.third_to_last!
823
+ Topic.delete_all
824
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
825
+ Topic.third_to_last!
826
+ end
827
+ end
828
+
829
+ def test_last_bang_present
830
+ assert_nothing_raised do
831
+ assert_equal topics(:second), Topic.where("title = 'The Second Topic of the day'").last!
832
+ end
833
+ end
834
+
835
+ def test_last_bang_missing
836
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
837
+ Topic.where("title = 'This title does not exist'").last!
838
+ end
839
+ end
840
+
841
+ def test_model_class_responds_to_last_bang
842
+ assert_equal topics(:fifth), Topic.last!
843
+ assert_raises_with_message ActiveRecord::RecordNotFound, "Couldn't find Topic" do
844
+ Topic.delete_all
845
+ Topic.last!
846
+ end
847
+ end
848
+
849
+ def test_take_and_first_and_last_with_integer_should_use_sql_limit
850
+ assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.take(3).entries }
851
+ assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.first(2).entries }
852
+ assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.last(5).entries }
853
+ end
854
+
855
+ def test_last_with_integer_and_order_should_keep_the_order
856
+ assert_equal Topic.order("title").to_a.last(2), Topic.order("title").last(2)
857
+ end
858
+
859
+ def test_last_with_integer_and_order_should_use_sql_limit
860
+ relation = Topic.order("title")
861
+ assert_queries(1) { relation.last(5) }
862
+ assert_not_predicate relation, :loaded?
863
+ end
864
+
865
+ def test_last_with_integer_and_reorder_should_use_sql_limit
866
+ relation = Topic.reorder("title")
867
+ assert_queries(1) { relation.last(5) }
868
+ assert_not_predicate relation, :loaded?
869
+ end
870
+
871
+ def test_last_on_loaded_relation_should_not_use_sql
872
+ relation = Topic.limit(10).load
873
+ assert_no_queries do
874
+ relation.last
875
+ relation.last(2)
876
+ end
877
+ end
878
+
879
+ def test_last_with_irreversible_order
880
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
881
+ Topic.order(Arel.sql("coalesce(author_name, title)")).last
882
+ end
883
+ end
884
+
885
+ def test_last_on_relation_with_limit_and_offset
886
+ post = posts("sti_comments")
887
+
888
+ comments = post.comments.order(id: :asc)
889
+ assert_equal comments.limit(2).to_a.last, comments.limit(2).last
890
+ assert_equal comments.limit(2).to_a.last(2), comments.limit(2).last(2)
891
+ assert_equal comments.limit(2).to_a.last(3), comments.limit(2).last(3)
892
+
893
+ assert_equal comments.offset(2).to_a.last, comments.offset(2).last
894
+ assert_equal comments.offset(2).to_a.last(2), comments.offset(2).last(2)
895
+ assert_equal comments.offset(2).to_a.last(3), comments.offset(2).last(3)
896
+
897
+ comments = comments.offset(1)
898
+ assert_equal comments.limit(2).to_a.last, comments.limit(2).last
899
+ assert_equal comments.limit(2).to_a.last(2), comments.limit(2).last(2)
900
+ assert_equal comments.limit(2).to_a.last(3), comments.limit(2).last(3)
901
+ end
902
+
903
+ def test_first_on_relation_with_limit_and_offset
904
+ post = posts("sti_comments")
905
+
906
+ comments = post.comments.order(id: :asc)
907
+ assert_equal comments.limit(2).to_a.first, comments.limit(2).first
908
+ assert_equal comments.limit(2).to_a.first(2), comments.limit(2).first(2)
909
+ assert_equal comments.limit(2).to_a.first(3), comments.limit(2).first(3)
910
+
911
+ assert_equal comments.offset(2).to_a.first, comments.offset(2).first
912
+ assert_equal comments.offset(2).to_a.first(2), comments.offset(2).first(2)
913
+ assert_equal comments.offset(2).to_a.first(3), comments.offset(2).first(3)
914
+
915
+ comments = comments.offset(1)
916
+ assert_equal comments.limit(2).to_a.first, comments.limit(2).first
917
+ assert_equal comments.limit(2).to_a.first(2), comments.limit(2).first(2)
918
+ assert_equal comments.limit(2).to_a.first(3), comments.limit(2).first(3)
919
+ end
920
+
921
+ def test_first_have_determined_order_by_default
922
+ expected = [companies(:second_client), companies(:another_client)]
923
+ clients = Client.where(name: expected.map(&:name))
924
+
925
+ assert_equal expected, clients.first(2)
926
+ assert_equal expected, clients.limit(5).first(2)
927
+ assert_equal expected, clients.order(nil).first(2)
928
+ end
929
+
930
+ def test_implicit_order_column_is_configurable
931
+ old_implicit_order_column = Topic.implicit_order_column
932
+ Topic.implicit_order_column = "title"
933
+
934
+ assert_equal topics(:fifth), Topic.first
935
+ assert_equal topics(:third), Topic.last
936
+
937
+ c = Topic.connection
938
+ assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
939
+ Topic.last
940
+ }
941
+ ensure
942
+ Topic.implicit_order_column = old_implicit_order_column
943
+ end
944
+
945
+ def test_implicit_order_set_to_primary_key
946
+ old_implicit_order_column = Topic.implicit_order_column
947
+ Topic.implicit_order_column = "id"
948
+
949
+ c = Topic.connection
950
+ assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
951
+ Topic.last
952
+ }
953
+ ensure
954
+ Topic.implicit_order_column = old_implicit_order_column
955
+ end
956
+
957
+ def test_implicit_order_for_model_without_primary_key
958
+ old_implicit_order_column = NonPrimaryKey.implicit_order_column
959
+ NonPrimaryKey.implicit_order_column = "created_at"
960
+
961
+ c = NonPrimaryKey.connection
962
+ assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC LIMIT/i) {
963
+ NonPrimaryKey.last
964
+ }
965
+ ensure
966
+ NonPrimaryKey.implicit_order_column = old_implicit_order_column
967
+ end
968
+
969
+ def test_take_and_first_and_last_with_integer_should_return_an_array
970
+ assert_kind_of Array, Topic.take(5)
971
+ assert_kind_of Array, Topic.first(5)
972
+ assert_kind_of Array, Topic.last(5)
973
+ end
974
+
975
+ def test_unexisting_record_exception_handling
976
+ assert_raise(ActiveRecord::RecordNotFound) {
977
+ Topic.find(1).parent
978
+ }
979
+
980
+ Topic.find(2).topic
981
+ end
982
+
983
+ def test_find_only_some_columns
984
+ topic = Topic.select("author_name").find(1)
985
+ assert_raise(ActiveModel::MissingAttributeError) { topic.title }
986
+ assert_raise(ActiveModel::MissingAttributeError) { topic.title? }
987
+ assert_nil topic.read_attribute("title")
988
+ assert_equal "David", topic.author_name
989
+ assert_not topic.attribute_present?("title")
990
+ assert_not topic.attribute_present?(:title)
991
+ assert topic.attribute_present?("author_name")
992
+ assert_respond_to topic, "author_name"
993
+ end
994
+
995
+ def test_find_on_array_conditions
996
+ assert Topic.where(["approved = ?", false]).find(1)
997
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(["approved = ?", true]).find(1) }
998
+ end
999
+
1000
+ def test_find_on_hash_conditions
1001
+ assert Topic.where(approved: false).find(1)
1002
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(approved: true).find(1) }
1003
+ end
1004
+
1005
+ def test_find_on_hash_conditions_with_qualified_attribute_dot_notation_string
1006
+ assert Topic.where("topics.approved" => false).find(1)
1007
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where("topics.approved" => true).find(1) }
1008
+ end
1009
+
1010
+ def test_find_on_hash_conditions_with_qualified_attribute_dot_notation_symbol
1011
+ assert Topic.where('topics.approved': false).find(1)
1012
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where('topics.approved': true).find(1) }
1013
+ end
1014
+
1015
+ def test_find_on_hash_conditions_with_hashed_table_name
1016
+ assert Topic.where(topics: { approved: false }).find(1)
1017
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(topics: { approved: true }).find(1) }
1018
+ end
1019
+
1020
+ def test_find_on_combined_explicit_and_hashed_table_names
1021
+ assert Topic.where("topics.approved" => false, topics: { author_name: "David" }).find(1)
1022
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where("topics.approved" => true, topics: { author_name: "David" }).find(1) }
1023
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where("topics.approved" => false, topics: { author_name: "Melanie" }).find(1) }
1024
+ end
1025
+
1026
+ def test_find_with_hash_conditions_on_joined_table
1027
+ firms = Firm.joins(:account).where(accounts: { credit_limit: 50 })
1028
+ assert_equal 1, firms.size
1029
+ assert_equal companies(:first_firm), firms.first
1030
+ end
1031
+
1032
+ def test_find_with_hash_conditions_on_joined_table_and_with_range
1033
+ firms = DependentFirm.joins(:account).where(name: "RailsCore", accounts: { credit_limit: 55..60 })
1034
+ assert_equal 1, firms.size
1035
+ assert_equal companies(:rails_core), firms.first
1036
+ end
1037
+
1038
+ def test_find_on_hash_conditions_with_explicit_table_name_and_aggregate
1039
+ david = customers(:david)
1040
+ assert Customer.where("customers.name" => david.name, :address => david.address).find(david.id)
1041
+ assert_raise(ActiveRecord::RecordNotFound) {
1042
+ Customer.where("customers.name" => david.name + "1", :address => david.address).find(david.id)
1043
+ }
1044
+ end
1045
+
1046
+ def test_find_on_association_proxy_conditions
1047
+ assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13], Comment.where(post_id: authors(:david).posts).map(&:id).sort
1048
+ end
1049
+
1050
+ def test_find_on_hash_conditions_with_range
1051
+ assert_equal [1, 2], Topic.where(id: 1..2).to_a.map(&:id).sort
1052
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(id: 2..3).find(1) }
1053
+ end
1054
+
1055
+ def test_find_on_hash_conditions_with_end_exclusive_range
1056
+ assert_equal [1, 2, 3], Topic.where(id: 1..3).to_a.map(&:id).sort
1057
+ assert_equal [1, 2], Topic.where(id: 1...3).to_a.map(&:id).sort
1058
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(id: 2...3).find(3) }
1059
+ end
1060
+
1061
+ def test_find_on_hash_conditions_with_multiple_ranges
1062
+ assert_equal [1, 2, 3], Comment.where(id: 1..3, post_id: 1..2).to_a.map(&:id).sort
1063
+ assert_equal [1], Comment.where(id: 1..1, post_id: 1..10).to_a.map(&:id).sort
1064
+ end
1065
+
1066
+ def test_find_on_hash_conditions_with_array_of_integers_and_ranges
1067
+ assert_equal [1, 2, 3, 5, 6, 7, 8, 9], Comment.where(id: [1..2, 3, 5, 6..8, 9]).to_a.map(&:id).sort
1068
+ end
1069
+
1070
+ def test_find_on_hash_conditions_with_array_of_ranges
1071
+ assert_equal [1, 2, 6, 7, 8], Comment.where(id: [1..2, 6..8]).to_a.map(&:id).sort
1072
+ end
1073
+
1074
+ def test_find_on_hash_conditions_with_open_ended_range
1075
+ assert_equal [1, 2, 3], Comment.where(id: Float::INFINITY..3).to_a.map(&:id).sort
1076
+ end
1077
+
1078
+ def test_find_on_hash_conditions_with_numeric_range_for_string
1079
+ topic = Topic.create!(title: "12 Factor App")
1080
+ assert_equal [topic], Topic.where(title: 10..2).to_a
1081
+ end
1082
+
1083
+ def test_find_on_multiple_hash_conditions
1084
+ assert Topic.where(author_name: "David", title: "The First Topic", replies_count: 1, approved: false).find(1)
1085
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(author_name: "David", title: "The First Topic", replies_count: 1, approved: true).find(1) }
1086
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.where(author_name: "David", title: "HHC", replies_count: 1, approved: false).find(1) }
1087
+ end
1088
+
1089
+ def test_condition_interpolation
1090
+ assert_kind_of Firm, Company.where("name = '%s'", "37signals").first
1091
+ assert_nil Company.where(["name = '%s'", "37signals!"]).first
1092
+ assert_nil Company.where(["name = '%s'", "37signals!' OR 1=1"]).first
1093
+ assert_kind_of Time, Topic.where(["id = %d", 1]).first.written_on
1094
+ end
1095
+
1096
+ def test_condition_array_interpolation
1097
+ assert_kind_of Firm, Company.where(["name = '%s'", "37signals"]).first
1098
+ assert_nil Company.where(["name = '%s'", "37signals!"]).first
1099
+ assert_nil Company.where(["name = '%s'", "37signals!' OR 1=1"]).first
1100
+ assert_kind_of Time, Topic.where(["id = %d", 1]).first.written_on
1101
+ end
1102
+
1103
+ def test_condition_hash_interpolation
1104
+ assert_kind_of Firm, Company.where(name: "37signals").first
1105
+ assert_nil Company.where(name: "37signals!").first
1106
+ assert_kind_of Time, Topic.where(id: 1).first.written_on
1107
+ end
1108
+
1109
+ def test_hash_condition_find_malformed
1110
+ assert_raise(ActiveRecord::StatementInvalid) {
1111
+ Company.where(id: 2, dhh: true).first
1112
+ }
1113
+ end
1114
+
1115
+ def test_hash_condition_find_with_escaped_characters
1116
+ Company.create("name" => "Ain't noth'n like' \#stuff")
1117
+ assert Company.where(name: "Ain't noth'n like' \#stuff").first
1118
+ end
1119
+
1120
+ def test_hash_condition_find_with_array
1121
+ p1, p2 = Post.limit(2).order("id asc").to_a
1122
+ assert_equal [p1, p2], Post.where(id: [p1, p2]).order("id asc").to_a
1123
+ assert_equal [p1, p2], Post.where(id: [p1, p2.id]).order("id asc").to_a
1124
+ end
1125
+
1126
+ def test_hash_condition_find_with_nil
1127
+ topic = Topic.where(last_read: nil).first
1128
+ assert_not_nil topic
1129
+ assert_nil topic.last_read
1130
+ end
1131
+
1132
+ def test_hash_condition_find_with_aggregate_having_one_mapping
1133
+ balance = customers(:david).balance
1134
+ assert_kind_of Money, balance
1135
+ found_customer = Customer.where(balance: balance).first
1136
+ assert_equal customers(:david), found_customer
1137
+ end
1138
+
1139
+ def test_hash_condition_find_with_aggregate_having_three_mappings_array
1140
+ david_address = customers(:david).address
1141
+ zaphod_address = customers(:zaphod).address
1142
+ barney_address = customers(:barney).address
1143
+ assert_kind_of Address, david_address
1144
+ assert_kind_of Address, zaphod_address
1145
+ found_customers = Customer.where(address: [david_address, zaphod_address, barney_address])
1146
+ assert_equal [customers(:david), customers(:zaphod), customers(:barney)], found_customers.sort_by(&:id)
1147
+ end
1148
+
1149
+ def test_hash_condition_find_with_aggregate_having_one_mapping_array
1150
+ david_balance = customers(:david).balance
1151
+ zaphod_balance = customers(:zaphod).balance
1152
+ assert_kind_of Money, david_balance
1153
+ assert_kind_of Money, zaphod_balance
1154
+ found_customers = Customer.where(balance: [david_balance, zaphod_balance])
1155
+ assert_equal [customers(:david), customers(:zaphod)], found_customers.sort_by(&:id)
1156
+ assert_equal Customer.where(balance: [david_balance.amount, zaphod_balance.amount]).to_sql, found_customers.to_sql
1157
+ end
1158
+
1159
+ def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_aggregate
1160
+ gps_location = customers(:david).gps_location
1161
+ assert_kind_of GpsLocation, gps_location
1162
+ found_customer = Customer.where(gps_location: gps_location).first
1163
+ assert_equal customers(:david), found_customer
1164
+ end
1165
+
1166
+ def test_hash_condition_find_with_aggregate_having_one_mapping_and_key_value_being_attribute_value
1167
+ balance = customers(:david).balance
1168
+ assert_kind_of Money, balance
1169
+ found_customer = Customer.where(balance: balance.amount).first
1170
+ assert_equal customers(:david), found_customer
1171
+ end
1172
+
1173
+ def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_attribute_value
1174
+ gps_location = customers(:david).gps_location
1175
+ assert_kind_of GpsLocation, gps_location
1176
+ found_customer = Customer.where(gps_location: gps_location.gps_location).first
1177
+ assert_equal customers(:david), found_customer
1178
+ end
1179
+
1180
+ def test_hash_condition_find_with_aggregate_having_three_mappings
1181
+ address = customers(:david).address
1182
+ assert_kind_of Address, address
1183
+ customers = Customer.where(address: address).order(:id)
1184
+ assert_equal [customers(:david)], customers
1185
+ assert_equal customers(:david, :mary), customers.unscope(where: [:address_city, :address_country])
1186
+ end
1187
+
1188
+ def test_hash_condition_find_with_one_condition_being_aggregate_and_another_not
1189
+ address = customers(:david).address
1190
+ assert_kind_of Address, address
1191
+ found_customer = Customer.where(address: address, name: customers(:david).name).first
1192
+ assert_equal customers(:david), found_customer
1193
+ end
1194
+
1195
+ def test_hash_condition_find_nil_with_aggregate_having_one_mapping
1196
+ assert_nil customers(:zaphod).gps_location
1197
+ found_customer = Customer.where(gps_location: nil, name: customers(:zaphod).name).first
1198
+ assert_equal customers(:zaphod), found_customer
1199
+ end
1200
+
1201
+ def test_hash_condition_find_nil_with_aggregate_having_multiple_mappings
1202
+ customers(:david).update(address: nil)
1203
+ assert_nil customers(:david).address_street
1204
+ assert_nil customers(:david).address_city
1205
+ found_customer = Customer.where(address: nil, name: customers(:david).name).first
1206
+ assert_equal customers(:david), found_customer
1207
+ end
1208
+
1209
+ def test_hash_condition_find_empty_array_with_aggregate_having_multiple_mappings
1210
+ assert_nil Customer.where(address: []).first
1211
+ end
1212
+
1213
+ def test_condition_utc_time_interpolation_with_default_timezone_local
1214
+ with_env_tz "America/New_York" do
1215
+ with_timezone_config default: :local do
1216
+ topic = Topic.first
1217
+ assert_equal topic, Topic.where(["written_on = ?", topic.written_on.getutc]).first
1218
+ end
1219
+ end
1220
+ end
1221
+
1222
+ def test_hash_condition_utc_time_interpolation_with_default_timezone_local
1223
+ with_env_tz "America/New_York" do
1224
+ with_timezone_config default: :local do
1225
+ topic = Topic.first
1226
+ assert_equal topic, Topic.where(written_on: topic.written_on.getutc).first
1227
+ end
1228
+ end
1229
+ end
1230
+
1231
+ def test_condition_local_time_interpolation_with_default_timezone_utc
1232
+ with_env_tz "America/New_York" do
1233
+ with_timezone_config default: :utc do
1234
+ topic = Topic.first
1235
+ assert_equal topic, Topic.where(["written_on = ?", topic.written_on.getlocal]).first
1236
+ end
1237
+ end
1238
+ end
1239
+
1240
+ def test_hash_condition_local_time_interpolation_with_default_timezone_utc
1241
+ with_env_tz "America/New_York" do
1242
+ with_timezone_config default: :utc do
1243
+ topic = Topic.first
1244
+ assert_equal topic, Topic.where(written_on: topic.written_on.getlocal).first
1245
+ end
1246
+ end
1247
+ end
1248
+
1249
+ def test_bind_variables
1250
+ assert_kind_of Firm, Company.where(["name = ?", "37signals"]).first
1251
+ assert_nil Company.where(["name = ?", "37signals!"]).first
1252
+ assert_nil Company.where(["name = ?", "37signals!' OR 1=1"]).first
1253
+ assert_kind_of Time, Topic.where(["id = ?", 1]).first.written_on
1254
+ assert_raise(ActiveRecord::PreparedStatementInvalid) {
1255
+ Company.where(["id=? AND name = ?", 2]).first
1256
+ }
1257
+ assert_raise(ActiveRecord::PreparedStatementInvalid) {
1258
+ Company.where(["id=?", 2, 3, 4]).first
1259
+ }
1260
+ end
1261
+
1262
+ def test_bind_variables_with_quotes
1263
+ Company.create("name" => "37signals' go'es against")
1264
+ assert Company.where(["name = ?", "37signals' go'es against"]).first
1265
+ end
1266
+
1267
+ def test_named_bind_variables_with_quotes
1268
+ Company.create("name" => "37signals' go'es against")
1269
+ assert Company.where(["name = :name", { name: "37signals' go'es against" }]).first
1270
+ end
1271
+
1272
+ def test_named_bind_variables
1273
+ assert_kind_of Firm, Company.where(["name = :name", { name: "37signals" }]).first
1274
+ assert_nil Company.where(["name = :name", { name: "37signals!" }]).first
1275
+ assert_nil Company.where(["name = :name", { name: "37signals!' OR 1=1" }]).first
1276
+ assert_kind_of Time, Topic.where(["id = :id", { id: 1 }]).first.written_on
1277
+ end
1278
+
1279
+ def test_count_by_sql
1280
+ assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3"))
1281
+ assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2]))
1282
+ assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
1283
+ end
1284
+
1285
+ def test_find_by_one_attribute
1286
+ assert_equal topics(:first), Topic.find_by_title("The First Topic")
1287
+ assert_nil Topic.find_by_title("The First Topic!")
1288
+ end
1289
+
1290
+ def test_find_by_one_attribute_bang
1291
+ assert_equal topics(:first), Topic.find_by_title!("The First Topic")
1292
+ assert_raises_with_message(ActiveRecord::RecordNotFound, "Couldn't find Topic") do
1293
+ Topic.find_by_title!("The First Topic!")
1294
+ end
1295
+ end
1296
+
1297
+ def test_find_by_on_attribute_that_is_a_reserved_word
1298
+ dog_alias = "Dog"
1299
+ dog = Dog.create(alias: dog_alias)
1300
+
1301
+ assert_equal dog, Dog.find_by_alias(dog_alias)
1302
+ end
1303
+
1304
+ def test_find_by_one_attribute_that_is_an_alias
1305
+ assert_equal topics(:first), Topic.find_by_heading("The First Topic")
1306
+ assert_nil Topic.find_by_heading("The First Topic!")
1307
+ end
1308
+
1309
+ def test_find_by_one_attribute_bang_with_blank_defined
1310
+ blank_topic = BlankTopic.create(title: "The Blank One")
1311
+ assert_equal blank_topic, BlankTopic.find_by_title!("The Blank One")
1312
+ end
1313
+
1314
+ def test_find_by_one_attribute_with_conditions
1315
+ assert_equal accounts(:rails_core_account), Account.where("firm_id = ?", 6).find_by_credit_limit(50)
1316
+ end
1317
+
1318
+ def test_find_by_one_attribute_that_is_an_aggregate
1319
+ address = customers(:david).address
1320
+ assert_kind_of Address, address
1321
+ found_customer = Customer.find_by_address(address)
1322
+ assert_equal customers(:david), found_customer
1323
+ end
1324
+
1325
+ def test_find_by_one_attribute_that_is_an_aggregate_with_one_attribute_difference
1326
+ address = customers(:david).address
1327
+ assert_kind_of Address, address
1328
+ missing_address = Address.new(address.street, address.city, address.country + "1")
1329
+ assert_nil Customer.find_by_address(missing_address)
1330
+ missing_address = Address.new(address.street, address.city + "1", address.country)
1331
+ assert_nil Customer.find_by_address(missing_address)
1332
+ missing_address = Address.new(address.street + "1", address.city, address.country)
1333
+ assert_nil Customer.find_by_address(missing_address)
1334
+ end
1335
+
1336
+ def test_find_by_two_attributes_that_are_both_aggregates
1337
+ balance = customers(:david).balance
1338
+ address = customers(:david).address
1339
+ assert_kind_of Money, balance
1340
+ assert_kind_of Address, address
1341
+ found_customer = Customer.find_by_balance_and_address(balance, address)
1342
+ assert_equal customers(:david), found_customer
1343
+ end
1344
+
1345
+ def test_find_by_two_attributes_with_one_being_an_aggregate
1346
+ balance = customers(:david).balance
1347
+ assert_kind_of Money, balance
1348
+ found_customer = Customer.find_by_balance_and_name(balance, customers(:david).name)
1349
+ assert_equal customers(:david), found_customer
1350
+ end
1351
+
1352
+ def test_dynamic_finder_on_one_attribute_with_conditions_returns_same_results_after_caching
1353
+ # ensure this test can run independently of order
1354
+ Account.singleton_class.remove_method :find_by_credit_limit if Account.public_methods.include?(:find_by_credit_limit)
1355
+ a = Account.where("firm_id = ?", 6).find_by_credit_limit(50)
1356
+ assert_equal a, Account.where("firm_id = ?", 6).find_by_credit_limit(50) # find_by_credit_limit has been cached
1357
+ end
1358
+
1359
+ def test_find_by_one_attribute_with_several_options
1360
+ assert_equal accounts(:unknown), Account.order("id DESC").where("id != ?", 3).find_by_credit_limit(50)
1361
+ end
1362
+
1363
+ def test_find_by_one_missing_attribute
1364
+ assert_raise(NoMethodError) { Topic.find_by_undertitle("The First Topic!") }
1365
+ end
1366
+
1367
+ def test_find_by_invalid_method_syntax
1368
+ assert_raise(NoMethodError) { Topic.fail_to_find_by_title("The First Topic") }
1369
+ assert_raise(NoMethodError) { Topic.find_by_title?("The First Topic") }
1370
+ assert_raise(NoMethodError) { Topic.fail_to_find_or_create_by_title("Nonexistent Title") }
1371
+ assert_raise(NoMethodError) { Topic.find_or_create_by_title?("Nonexistent Title") }
1372
+ end
1373
+
1374
+ def test_find_by_two_attributes
1375
+ assert_equal topics(:first), Topic.find_by_title_and_author_name("The First Topic", "David")
1376
+ assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary")
1377
+ end
1378
+
1379
+ def test_find_by_two_attributes_but_passing_only_one
1380
+ assert_raise(ArgumentError) { Topic.find_by_title_and_author_name("The First Topic") }
1381
+ end
1382
+
1383
+ def test_find_by_nil_attribute
1384
+ topic = Topic.find_by_last_read nil
1385
+ assert_not_nil topic
1386
+ assert_nil topic.last_read
1387
+ end
1388
+
1389
+ def test_find_by_nil_and_not_nil_attributes
1390
+ topic = Topic.find_by_last_read_and_author_name nil, "Mary"
1391
+ assert_equal "Mary", topic.author_name
1392
+ end
1393
+
1394
+ def test_find_with_bad_sql
1395
+ assert_raise(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
1396
+ end
1397
+
1398
+ def test_joins_dont_clobber_id
1399
+ first = Firm.
1400
+ joins("INNER JOIN companies clients ON clients.firm_id = companies.id").
1401
+ where("companies.id = 1").first
1402
+ assert_equal 1, first.id
1403
+ end
1404
+
1405
+ def test_joins_with_string_array
1406
+ person_with_reader_and_post = Post.
1407
+ joins(["INNER JOIN categorizations ON categorizations.post_id = posts.id",
1408
+ "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
1409
+ ])
1410
+ assert_equal 1, person_with_reader_and_post.size
1411
+ end
1412
+
1413
+ def test_find_by_id_with_conditions_with_or
1414
+ assert_nothing_raised do
1415
+ Post.where("posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'").find([1, 2, 3])
1416
+ end
1417
+ end
1418
+
1419
+ def test_find_ignores_previously_inserted_record
1420
+ Post.create!(title: "test", body: "it out")
1421
+ assert_equal [], Post.where(id: nil)
1422
+ end
1423
+
1424
+ def test_find_by_empty_ids
1425
+ assert_equal [], Post.find([])
1426
+ end
1427
+
1428
+ def test_find_by_empty_in_condition
1429
+ assert_equal [], Post.where("id in (?)", [])
1430
+ end
1431
+
1432
+ def test_find_by_records
1433
+ p1, p2 = Post.limit(2).order("id asc").to_a
1434
+ assert_equal [p1, p2], Post.where(["id in (?)", [p1, p2]]).order("id asc")
1435
+ assert_equal [p1, p2], Post.where(["id in (?)", [p1, p2.id]]).order("id asc")
1436
+ end
1437
+
1438
+ def test_select_value
1439
+ assert_equal "37signals", Company.connection.select_value("SELECT name FROM companies WHERE id = 1")
1440
+ assert_nil Company.connection.select_value("SELECT name FROM companies WHERE id = -1")
1441
+ # make sure we didn't break count...
1442
+ assert_equal 0, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = 'Halliburton'")
1443
+ assert_equal 1, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = '37signals'")
1444
+ end
1445
+
1446
+ def test_select_values
1447
+ assert_equal ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "15"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map!(&:to_s)
1448
+ assert_equal ["37signals", "Summit", "Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux", "Apex", "RVshare"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
1449
+ end
1450
+
1451
+ def test_select_rows
1452
+ assert_equal(
1453
+ [["1", "1", nil, "37signals"],
1454
+ ["2", "1", "2", "Summit"],
1455
+ ["3", "1", "1", "Microsoft"]],
1456
+ Company.connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! { |i| i.map! { |j| j.to_s unless j.nil? } })
1457
+ assert_equal [["1", "37signals"], ["2", "Summit"], ["3", "Microsoft"]],
1458
+ Company.connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! { |i| i.map! { |j| j.to_s unless j.nil? } }
1459
+ end
1460
+
1461
+ def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
1462
+ assert_equal 2, Post.includes(authors: :author_address).
1463
+ where.not(author_addresses: { id: nil }).
1464
+ order("author_addresses.id DESC").limit(2).to_a.size
1465
+
1466
+ assert_equal 3, Post.includes(author: :author_address, authors: :author_address).
1467
+ where.not(author_addresses_authors: { id: nil }).
1468
+ order("author_addresses_authors.id DESC").limit(3).to_a.size
1469
+ end
1470
+
1471
+ def test_find_with_eager_loading_collection_and_ordering_by_collection_primary_key
1472
+ assert_equal Post.first, Post.eager_load(comments: :ratings).
1473
+ order("posts.id, ratings.id, comments.id").first
1474
+ end
1475
+
1476
+ def test_find_with_nil_inside_set_passed_for_one_attribute
1477
+ client_of = Company.
1478
+ where(client_of: [2, 1, nil],
1479
+ name: ["37signals", "Summit", "Microsoft"]).
1480
+ order("client_of DESC").
1481
+ map(&:client_of)
1482
+
1483
+ assert_includes client_of, nil
1484
+ assert_equal [2, 1].sort, client_of.compact.sort
1485
+ end
1486
+
1487
+ def test_find_with_nil_inside_set_passed_for_attribute
1488
+ client_of = Company.
1489
+ where(client_of: [nil]).
1490
+ order("client_of DESC").
1491
+ map(&:client_of)
1492
+
1493
+ assert_equal [], client_of.compact
1494
+ end
1495
+
1496
+ def test_with_limiting_with_custom_select
1497
+ posts = Post.references(:authors).merge(
1498
+ includes: :author, select: 'posts.*, authors.id as "author_id"',
1499
+ limit: 3, order: "posts.id"
1500
+ ).to_a
1501
+ assert_equal 3, posts.size
1502
+ assert_equal [1, 1, nil], posts.map(&:author_id)
1503
+ end
1504
+
1505
+ def test_custom_select_takes_precedence_over_original_value
1506
+ posts = Post.select("UPPER(title) AS title")
1507
+ assert_equal "WELCOME TO THE WEBLOG", posts.first.title
1508
+ assert_equal "WELCOME TO THE WEBLOG", posts.preload(:comments).first.title
1509
+ assert_equal "WELCOME TO THE WEBLOG", posts.eager_load(:comments).first.title
1510
+ end
1511
+
1512
+ def test_eager_load_for_no_has_many_with_limit_and_joins_for_has_many
1513
+ relation = Post.eager_load(:author).joins(comments: :post)
1514
+ assert_equal 5, relation.to_a.size
1515
+ assert_equal 5, relation.limit(5).to_a.size
1516
+ end
1517
+
1518
+ def test_eager_load_for_no_has_many_with_limit_and_left_joins_for_has_many
1519
+ relation = Post.eager_load(:author).left_joins(comments: :post)
1520
+ assert_equal 11, relation.to_a.size
1521
+ assert_equal 11, relation.limit(11).to_a.size
1522
+ end
1523
+
1524
+ def test_find_one_message_on_primary_key
1525
+ e = assert_raises(ActiveRecord::RecordNotFound) do
1526
+ Car.find(0)
1527
+ end
1528
+ assert_equal 0, e.id
1529
+ assert_equal "id", e.primary_key
1530
+ assert_equal "Car", e.model
1531
+ assert_equal "Couldn't find Car with 'id'=0", e.message
1532
+ end
1533
+
1534
+ def test_find_one_message_with_custom_primary_key
1535
+ table_with_custom_primary_key do |model|
1536
+ model.primary_key = :name
1537
+ e = assert_raises(ActiveRecord::RecordNotFound) do
1538
+ model.find "Hello World!"
1539
+ end
1540
+ assert_equal "Couldn't find MercedesCar with 'name'=Hello World!", e.message
1541
+ end
1542
+ end
1543
+
1544
+ def test_find_some_message_with_custom_primary_key
1545
+ table_with_custom_primary_key do |model|
1546
+ model.primary_key = :name
1547
+ e = assert_raises(ActiveRecord::RecordNotFound) do
1548
+ model.find "Hello", "World!"
1549
+ end
1550
+ assert_equal "Couldn't find all MercedesCars with 'name': (Hello, World!) (found 0 results, but was looking for 2).", e.message
1551
+ end
1552
+ end
1553
+
1554
+ def test_find_without_primary_key
1555
+ assert_raises(ActiveRecord::UnknownPrimaryKey) do
1556
+ Matey.find(1)
1557
+ end
1558
+ end
1559
+
1560
+ def test_finder_with_offset_string
1561
+ assert_nothing_raised { Topic.offset("3").to_a }
1562
+ end
1563
+
1564
+ test "find_by with hash conditions returns the first matching record" do
1565
+ assert_equal posts(:eager_other), Post.find_by(id: posts(:eager_other).id)
1566
+ end
1567
+
1568
+ test "find_by with non-hash conditions returns the first matching record" do
1569
+ assert_equal posts(:eager_other), Post.find_by("id = #{posts(:eager_other).id}")
1570
+ end
1571
+
1572
+ test "find_by with multi-arg conditions returns the first matching record" do
1573
+ assert_equal posts(:eager_other), Post.find_by("id = ?", posts(:eager_other).id)
1574
+ end
1575
+
1576
+ test "find_by with range conditions returns the first matching record" do
1577
+ assert_equal posts(:eager_other), Post.find_by(id: posts(:eager_other).id...posts(:misc_by_bob).id)
1578
+ end
1579
+
1580
+ test "find_by returns nil if the record is missing" do
1581
+ assert_nil Post.find_by("1 = 0")
1582
+ end
1583
+
1584
+ test "find_by with associations" do
1585
+ assert_equal authors(:david), Post.find_by(author: authors(:david)).author
1586
+ assert_equal authors(:mary), Post.find_by(author: authors(:mary)).author
1587
+ end
1588
+
1589
+ test "find_by doesn't have implicit ordering" do
1590
+ assert_sql(/^((?!ORDER).)*$/) { Post.find_by(id: posts(:eager_other).id) }
1591
+ end
1592
+
1593
+ test "find_by! with hash conditions returns the first matching record" do
1594
+ assert_equal posts(:eager_other), Post.find_by!(id: posts(:eager_other).id)
1595
+ end
1596
+
1597
+ test "find_by! with non-hash conditions returns the first matching record" do
1598
+ assert_equal posts(:eager_other), Post.find_by!("id = #{posts(:eager_other).id}")
1599
+ end
1600
+
1601
+ test "find_by! with multi-arg conditions returns the first matching record" do
1602
+ assert_equal posts(:eager_other), Post.find_by!("id = ?", posts(:eager_other).id)
1603
+ end
1604
+
1605
+ test "find_by! doesn't have implicit ordering" do
1606
+ assert_sql(/^((?!ORDER).)*$/) { Post.find_by!(id: posts(:eager_other).id) }
1607
+ end
1608
+
1609
+ test "find_by! raises RecordNotFound if the record is missing" do
1610
+ assert_raises(ActiveRecord::RecordNotFound) do
1611
+ Post.find_by!("1 = 0")
1612
+ end
1613
+ end
1614
+
1615
+ test "find on a scope does not perform statement caching" do
1616
+ honda = cars(:honda)
1617
+ zyke = cars(:zyke)
1618
+ tyre = honda.tyres.create!
1619
+ tyre2 = zyke.tyres.create!
1620
+
1621
+ assert_equal tyre, honda.tyres.custom_find(tyre.id)
1622
+ assert_equal tyre2, zyke.tyres.custom_find(tyre2.id)
1623
+ end
1624
+
1625
+ test "find_by on a scope does not perform statement caching" do
1626
+ honda = cars(:honda)
1627
+ zyke = cars(:zyke)
1628
+ tyre = honda.tyres.create!
1629
+ tyre2 = zyke.tyres.create!
1630
+
1631
+ assert_equal tyre, honda.tyres.custom_find_by(id: tyre.id)
1632
+ assert_equal tyre2, zyke.tyres.custom_find_by(id: tyre2.id)
1633
+ end
1634
+
1635
+ test "#skip_query_cache! for #exists?" do
1636
+ Topic.cache do
1637
+ assert_queries(1) do
1638
+ Topic.exists?
1639
+ Topic.exists?
1640
+ end
1641
+
1642
+ assert_queries(2) do
1643
+ Topic.all.skip_query_cache!.exists?
1644
+ Topic.all.skip_query_cache!.exists?
1645
+ end
1646
+ end
1647
+ end
1648
+
1649
+ test "#skip_query_cache! for #exists? with a limited eager load" do
1650
+ Topic.cache do
1651
+ assert_queries(1) do
1652
+ Topic.eager_load(:replies).limit(1).exists?
1653
+ Topic.eager_load(:replies).limit(1).exists?
1654
+ end
1655
+
1656
+ assert_queries(2) do
1657
+ Topic.eager_load(:replies).limit(1).skip_query_cache!.exists?
1658
+ Topic.eager_load(:replies).limit(1).skip_query_cache!.exists?
1659
+ end
1660
+ end
1661
+ end
1662
+
1663
+ private
1664
+ def table_with_custom_primary_key
1665
+ yield(Class.new(Toy) do
1666
+ def self.name
1667
+ "MercedesCar"
1668
+ end
1669
+ end)
1670
+ end
1671
+
1672
+ def assert_raises_with_message(exception_class, message, &block)
1673
+ err = assert_raises(exception_class) { block.call }
1674
+ assert_match message, err.message
1675
+ end
1676
+ end