ibm_db 5.1.0-x86-mingw32 → 5.3.2-x86-mingw32

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 (624) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/ext/Makefile +14 -14
  5. data/ext/extconf.rb +4 -4
  6. data/ext/ibm_db.c +62 -57
  7. data/ext/ibm_db.o +0 -0
  8. data/ext/ibm_db.so +0 -0
  9. data/ext/mkmf.log +11 -11
  10. data/ext/ruby_ibm_db_cli.c +1 -0
  11. data/ext/ruby_ibm_db_cli.o +0 -0
  12. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
  13. data/lib/ibm_db.so +1 -0
  14. data/lib/mswin32/ibm_db.rb +7 -3
  15. data/lib/mswin32/rb2x/i386/ruby25/ibm_db.so +0 -0
  16. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  17. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  18. data/test/activejob/destroy_association_async_test.rb +305 -0
  19. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  20. data/test/activejob/helper.rb +15 -0
  21. data/test/assets/schema_dump_5_1.yml +345 -0
  22. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  23. data/test/cases/adapter_test.rb +432 -218
  24. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  25. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  27. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  30. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  31. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  32. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  33. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  34. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  35. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  36. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  37. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  38. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  39. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  40. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  41. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  42. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  43. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  44. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  45. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  46. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  47. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  48. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  49. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  50. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  51. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  52. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  53. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  54. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  55. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  56. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  57. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  58. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  59. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  60. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  61. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  62. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  63. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  64. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  65. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  66. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  67. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  68. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  69. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  70. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  71. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  72. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  73. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  74. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  75. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  76. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  77. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  78. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  79. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  80. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  81. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  82. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  83. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  84. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  85. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  86. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  87. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  88. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  89. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  90. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  91. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  92. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  93. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  94. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  95. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  96. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  97. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  98. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  99. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  100. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  101. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  102. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  103. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  104. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  105. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  106. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  107. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  108. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  109. data/test/cases/aggregations_test.rb +14 -12
  110. data/test/cases/annotate_test.rb +46 -0
  111. data/test/cases/ar_schema_test.rb +153 -86
  112. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  113. data/test/cases/arel/attributes/math_test.rb +83 -0
  114. data/test/cases/arel/attributes_test.rb +27 -0
  115. data/test/cases/arel/collectors/bind_test.rb +40 -0
  116. data/test/cases/arel/collectors/composite_test.rb +47 -0
  117. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  118. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  119. data/test/cases/arel/crud_test.rb +65 -0
  120. data/test/cases/arel/delete_manager_test.rb +53 -0
  121. data/test/cases/arel/factory_methods_test.rb +46 -0
  122. data/test/cases/arel/helper.rb +45 -0
  123. data/test/cases/arel/insert_manager_test.rb +241 -0
  124. data/test/cases/arel/nodes/and_test.rb +30 -0
  125. data/test/cases/arel/nodes/as_test.rb +36 -0
  126. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  127. data/test/cases/arel/nodes/bin_test.rb +35 -0
  128. data/test/cases/arel/nodes/binary_test.rb +29 -0
  129. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  130. data/test/cases/arel/nodes/case_test.rb +96 -0
  131. data/test/cases/arel/nodes/casted_test.rb +18 -0
  132. data/test/cases/arel/nodes/comment_test.rb +22 -0
  133. data/test/cases/arel/nodes/count_test.rb +35 -0
  134. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  135. data/test/cases/arel/nodes/descending_test.rb +46 -0
  136. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  137. data/test/cases/arel/nodes/equality_test.rb +62 -0
  138. data/test/cases/arel/nodes/extract_test.rb +43 -0
  139. data/test/cases/arel/nodes/false_test.rb +21 -0
  140. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  141. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  142. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  143. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  144. data/test/cases/arel/nodes/node_test.rb +22 -0
  145. data/test/cases/arel/nodes/not_test.rb +31 -0
  146. data/test/cases/arel/nodes/or_test.rb +36 -0
  147. data/test/cases/arel/nodes/over_test.rb +69 -0
  148. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  149. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  150. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  151. data/test/cases/arel/nodes/sum_test.rb +35 -0
  152. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  153. data/test/cases/arel/nodes/true_test.rb +21 -0
  154. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  155. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  156. data/test/cases/arel/nodes/window_test.rb +81 -0
  157. data/test/cases/arel/nodes_test.rb +34 -0
  158. data/test/cases/arel/select_manager_test.rb +1238 -0
  159. data/test/cases/arel/support/fake_record.rb +135 -0
  160. data/test/cases/arel/table_test.rb +216 -0
  161. data/test/cases/arel/update_manager_test.rb +126 -0
  162. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  163. data/test/cases/arel/visitors/dot_test.rb +90 -0
  164. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  165. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  166. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  167. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  168. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  169. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  170. data/test/cases/associations/callbacks_test.rb +56 -38
  171. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  172. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  173. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  174. data/test/cases/associations/eager_singularization_test.rb +21 -21
  175. data/test/cases/associations/eager_test.rb +559 -415
  176. data/test/cases/associations/extension_test.rb +18 -12
  177. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  178. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  179. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  180. data/test/cases/associations/has_one_associations_test.rb +294 -129
  181. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  182. data/test/cases/associations/inner_join_association_test.rb +114 -38
  183. data/test/cases/associations/inverse_associations_test.rb +606 -398
  184. data/test/cases/associations/join_model_test.rb +158 -148
  185. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  186. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  187. data/test/cases/associations/required_test.rb +35 -10
  188. data/test/cases/associations_test.rb +241 -110
  189. data/test/cases/attribute_methods/read_test.rb +11 -11
  190. data/test/cases/attribute_methods_test.rb +413 -298
  191. data/test/cases/attributes_test.rb +145 -27
  192. data/test/cases/autosave_association_test.rb +681 -436
  193. data/test/cases/base_prevent_writes_test.rb +229 -0
  194. data/test/cases/base_test.rb +599 -542
  195. data/test/cases/batches_test.rb +288 -82
  196. data/test/cases/binary_test.rb +26 -31
  197. data/test/cases/bind_parameter_test.rb +194 -21
  198. data/test/cases/boolean_test.rb +52 -0
  199. data/test/cases/cache_key_test.rb +110 -5
  200. data/test/cases/calculations_test.rb +740 -177
  201. data/test/cases/callbacks_test.rb +74 -207
  202. data/test/cases/clone_test.rb +15 -10
  203. data/test/cases/coders/json_test.rb +2 -0
  204. data/test/cases/coders/yaml_column_test.rb +16 -13
  205. data/test/cases/collection_cache_key_test.rb +177 -20
  206. data/test/cases/column_alias_test.rb +9 -7
  207. data/test/cases/column_definition_test.rb +10 -68
  208. data/test/cases/comment_test.rb +166 -107
  209. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  210. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  211. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  212. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  213. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  214. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  215. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  216. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  217. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  218. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  219. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  220. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  221. data/test/cases/connection_management_test.rb +13 -11
  222. data/test/cases/connection_pool_test.rb +316 -83
  223. data/test/cases/core_test.rb +82 -58
  224. data/test/cases/counter_cache_test.rb +204 -50
  225. data/test/cases/custom_locking_test.rb +5 -3
  226. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  227. data/test/cases/database_configurations/resolver_test.rb +150 -0
  228. data/test/cases/database_configurations_test.rb +145 -0
  229. data/test/cases/database_selector_test.rb +296 -0
  230. data/test/cases/database_statements_test.rb +18 -16
  231. data/test/cases/date_test.rb +8 -16
  232. data/test/cases/date_time_precision_test.rb +100 -78
  233. data/test/cases/date_time_test.rb +23 -8
  234. data/test/cases/defaults_test.rb +106 -71
  235. data/test/cases/delegated_type_test.rb +57 -0
  236. data/test/cases/dirty_test.rb +419 -223
  237. data/test/cases/disconnected_test.rb +6 -6
  238. data/test/cases/dup_test.rb +54 -27
  239. data/test/cases/enum_test.rb +461 -82
  240. data/test/cases/errors_test.rb +7 -7
  241. data/test/cases/explain_subscriber_test.rb +17 -15
  242. data/test/cases/explain_test.rb +11 -19
  243. data/test/cases/filter_attributes_test.rb +153 -0
  244. data/test/cases/finder_respond_to_test.rb +14 -14
  245. data/test/cases/finder_test.rb +669 -287
  246. data/test/cases/fixture_set/file_test.rb +34 -38
  247. data/test/cases/fixtures_test.rb +833 -176
  248. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  249. data/test/cases/habtm_destroy_order_test.rb +25 -25
  250. data/test/cases/helper.rb +78 -49
  251. data/test/cases/hot_compatibility_test.rb +33 -32
  252. data/test/cases/i18n_test.rb +18 -17
  253. data/test/cases/inheritance_test.rb +180 -115
  254. data/test/cases/insert_all_test.rb +489 -0
  255. data/test/cases/instrumentation_test.rb +101 -0
  256. data/test/cases/integration_test.rb +119 -31
  257. data/test/cases/invalid_connection_test.rb +18 -16
  258. data/test/cases/invertible_migration_test.rb +183 -43
  259. data/test/cases/json_attribute_test.rb +35 -0
  260. data/test/cases/json_serialization_test.rb +57 -58
  261. data/test/cases/json_shared_test_cases.rb +290 -0
  262. data/test/cases/locking_test.rb +413 -119
  263. data/test/cases/log_subscriber_test.rb +68 -26
  264. data/test/cases/marshal_serialization_test.rb +39 -0
  265. data/test/cases/migration/change_schema_test.rb +118 -72
  266. data/test/cases/migration/change_table_test.rb +138 -30
  267. data/test/cases/migration/check_constraint_test.rb +162 -0
  268. data/test/cases/migration/column_attributes_test.rb +45 -35
  269. data/test/cases/migration/column_positioning_test.rb +18 -6
  270. data/test/cases/migration/columns_test.rb +93 -77
  271. data/test/cases/migration/command_recorder_test.rb +121 -34
  272. data/test/cases/migration/compatibility_test.rb +578 -23
  273. data/test/cases/migration/create_join_table_test.rb +35 -25
  274. data/test/cases/migration/foreign_key_test.rb +503 -284
  275. data/test/cases/migration/helper.rb +4 -3
  276. data/test/cases/migration/index_test.rb +119 -70
  277. data/test/cases/migration/logger_test.rb +9 -6
  278. data/test/cases/migration/pending_migrations_test.rb +88 -34
  279. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  280. data/test/cases/migration/references_index_test.rb +38 -19
  281. data/test/cases/migration/references_statements_test.rb +15 -14
  282. data/test/cases/migration/rename_table_test.rb +53 -30
  283. data/test/cases/migration_test.rb +637 -269
  284. data/test/cases/migrator_test.rb +191 -135
  285. data/test/cases/mixin_test.rb +7 -11
  286. data/test/cases/modules_test.rb +36 -34
  287. data/test/cases/multi_db_migrator_test.rb +223 -0
  288. data/test/cases/multiparameter_attributes_test.rb +60 -33
  289. data/test/cases/multiple_db_test.rb +16 -22
  290. data/test/cases/nested_attributes_test.rb +341 -320
  291. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  292. data/test/cases/null_relation_test.rb +84 -0
  293. data/test/cases/numeric_data_test.rb +93 -0
  294. data/test/cases/persistence_test.rb +361 -269
  295. data/test/cases/pooled_connections_test.rb +18 -26
  296. data/test/cases/prepared_statement_status_test.rb +48 -0
  297. data/test/cases/primary_keys_test.rb +210 -104
  298. data/test/cases/query_cache_test.rb +610 -141
  299. data/test/cases/quoting_test.rb +132 -31
  300. data/test/cases/readonly_test.rb +49 -48
  301. data/test/cases/reaper_test.rb +146 -32
  302. data/test/cases/reflection_test.rb +167 -156
  303. data/test/cases/relation/delegation_test.rb +49 -36
  304. data/test/cases/relation/delete_all_test.rb +117 -0
  305. data/test/cases/relation/merging_test.rb +319 -42
  306. data/test/cases/relation/mutation_test.rb +55 -93
  307. data/test/cases/relation/or_test.rb +129 -29
  308. data/test/cases/relation/predicate_builder_test.rb +21 -6
  309. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  310. data/test/cases/relation/select_test.rb +67 -0
  311. data/test/cases/relation/update_all_test.rb +317 -0
  312. data/test/cases/relation/where_chain_test.rb +68 -32
  313. data/test/cases/relation/where_clause_test.rb +136 -61
  314. data/test/cases/relation/where_test.rb +155 -48
  315. data/test/cases/relation_test.rb +266 -112
  316. data/test/cases/relations_test.rb +969 -744
  317. data/test/cases/reload_models_test.rb +13 -9
  318. data/test/cases/reserved_word_test.rb +141 -0
  319. data/test/cases/result_test.rb +68 -17
  320. data/test/cases/sanitize_test.rb +87 -71
  321. data/test/cases/schema_dumper_test.rb +221 -128
  322. data/test/cases/schema_loading_test.rb +3 -2
  323. data/test/cases/scoping/default_scoping_test.rb +185 -144
  324. data/test/cases/scoping/named_scoping_test.rb +177 -89
  325. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  326. data/test/cases/secure_token_test.rb +18 -3
  327. data/test/cases/serialization_test.rb +30 -28
  328. data/test/cases/serialized_attribute_test.rb +133 -42
  329. data/test/cases/signed_id_test.rb +168 -0
  330. data/test/cases/statement_cache_test.rb +41 -24
  331. data/test/cases/statement_invalid_test.rb +42 -0
  332. data/test/cases/store_test.rb +180 -55
  333. data/test/cases/strict_loading_test.rb +473 -0
  334. data/test/cases/suppressor_test.rb +26 -12
  335. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  336. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  337. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  338. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  339. data/test/cases/test_case.rb +51 -40
  340. data/test/cases/test_databases_test.rb +79 -0
  341. data/test/cases/test_fixtures_test.rb +79 -19
  342. data/test/cases/time_precision_test.rb +98 -76
  343. data/test/cases/timestamp_test.rb +102 -99
  344. data/test/cases/touch_later_test.rb +12 -10
  345. data/test/cases/transaction_callbacks_test.rb +344 -90
  346. data/test/cases/transaction_isolation_test.rb +12 -12
  347. data/test/cases/transactions_test.rb +612 -162
  348. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  349. data/test/cases/type/date_time_test.rb +4 -2
  350. data/test/cases/type/integer_test.rb +4 -2
  351. data/test/cases/type/string_test.rb +10 -8
  352. data/test/cases/type/time_test.rb +28 -0
  353. data/test/cases/type/type_map_test.rb +29 -28
  354. data/test/cases/type/unsigned_integer_test.rb +19 -0
  355. data/test/cases/type_test.rb +2 -0
  356. data/test/cases/types_test.rb +3 -1
  357. data/test/cases/unconnected_test.rb +14 -1
  358. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  359. data/test/cases/validations/absence_validation_test.rb +19 -17
  360. data/test/cases/validations/association_validation_test.rb +30 -28
  361. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  362. data/test/cases/validations/i18n_validation_test.rb +22 -21
  363. data/test/cases/validations/length_validation_test.rb +34 -33
  364. data/test/cases/validations/numericality_validation_test.rb +181 -0
  365. data/test/cases/validations/presence_validation_test.rb +21 -19
  366. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  367. data/test/cases/validations_repair_helper.rb +2 -0
  368. data/test/cases/validations_test.rb +61 -26
  369. data/test/cases/view_test.rb +122 -116
  370. data/test/cases/yaml_serialization_test.rb +79 -34
  371. data/test/config.example.yml +19 -19
  372. data/test/config.rb +3 -1
  373. data/test/config.yml +16 -6
  374. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  375. data/test/fixtures/author_addresses.yml +1 -8
  376. data/test/fixtures/authors.yml +1 -7
  377. data/test/fixtures/binaries.yml +4 -0
  378. data/test/fixtures/books.yml +9 -2
  379. data/test/fixtures/categories_posts.yml +3 -0
  380. data/test/fixtures/citations.yml +5 -0
  381. data/test/fixtures/comments.yml +7 -0
  382. data/test/fixtures/companies.yml +5 -0
  383. data/test/fixtures/computers.yml +2 -0
  384. data/test/fixtures/customers.yml +10 -1
  385. data/test/fixtures/developers.yml +1 -1
  386. data/test/fixtures/essays.yml +10 -0
  387. data/test/fixtures/faces.yml +3 -3
  388. data/test/fixtures/humans.yml +5 -0
  389. data/test/fixtures/interests.yml +7 -7
  390. data/test/fixtures/memberships.yml +7 -0
  391. data/test/fixtures/minimalistics.yml +3 -0
  392. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  393. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  394. data/test/fixtures/naked/yml/parrots.yml +1 -0
  395. data/test/fixtures/other_books.yml +26 -0
  396. data/test/fixtures/other_posts.yml +1 -0
  397. data/test/fixtures/parrots.yml +7 -1
  398. data/test/fixtures/pirates.yml +3 -0
  399. data/test/fixtures/posts.yml +11 -3
  400. data/test/fixtures/readers.yml +6 -0
  401. data/test/fixtures/reserved_words/values.yml +2 -2
  402. data/test/fixtures/sponsors.yml +3 -0
  403. data/test/fixtures/strict_zines.yml +2 -0
  404. data/test/fixtures/subscribers.yml +1 -1
  405. data/test/fixtures/tasks.yml +1 -1
  406. data/test/fixtures/warehouse-things.yml +3 -0
  407. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  408. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  409. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  410. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  411. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  412. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  413. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  414. data/test/migrations/rename/1_we_need_things.rb +2 -0
  415. data/test/migrations/rename/2_rename_things.rb +2 -0
  416. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  417. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  418. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  419. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  420. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  421. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  422. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  423. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  424. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  425. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  426. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  427. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  428. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  429. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  430. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  431. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  432. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  433. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  434. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  435. data/test/models/account.rb +46 -0
  436. data/test/models/admin/account.rb +3 -1
  437. data/test/models/admin/randomly_named_c1.rb +2 -0
  438. data/test/models/admin/user.rb +16 -8
  439. data/test/models/admin.rb +4 -2
  440. data/test/models/aircraft.rb +3 -1
  441. data/test/models/arunit2_model.rb +2 -0
  442. data/test/models/author.rb +153 -102
  443. data/test/models/auto_id.rb +2 -0
  444. data/test/models/autoloadable/extra_firm.rb +2 -0
  445. data/test/models/binary.rb +3 -1
  446. data/test/models/binary_field.rb +6 -0
  447. data/test/models/bird.rb +13 -1
  448. data/test/models/book.rb +14 -4
  449. data/test/models/book_destroy_async.rb +24 -0
  450. data/test/models/boolean.rb +5 -0
  451. data/test/models/bulb.rb +13 -4
  452. data/test/models/cake_designer.rb +2 -0
  453. data/test/models/car.rb +17 -10
  454. data/test/models/carrier.rb +2 -0
  455. data/test/models/cart.rb +5 -0
  456. data/test/models/cat.rb +2 -0
  457. data/test/models/categorization.rb +8 -6
  458. data/test/models/category.rb +28 -16
  459. data/test/models/chef.rb +2 -0
  460. data/test/models/citation.rb +5 -1
  461. data/test/models/club.rb +13 -10
  462. data/test/models/college.rb +4 -2
  463. data/test/models/column.rb +2 -0
  464. data/test/models/column_name.rb +2 -0
  465. data/test/models/comment.rb +32 -10
  466. data/test/models/company.rb +102 -106
  467. data/test/models/company_in_module.rb +27 -26
  468. data/test/models/computer.rb +3 -1
  469. data/test/models/contact.rb +15 -13
  470. data/test/models/content.rb +5 -3
  471. data/test/models/contract.rb +21 -3
  472. data/test/models/country.rb +2 -4
  473. data/test/models/course.rb +3 -1
  474. data/test/models/customer.rb +10 -8
  475. data/test/models/customer_carrier.rb +2 -0
  476. data/test/models/dashboard.rb +2 -0
  477. data/test/models/default.rb +2 -0
  478. data/test/models/department.rb +2 -0
  479. data/test/models/destroy_async_parent.rb +15 -0
  480. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  481. data/test/models/developer.rb +152 -85
  482. data/test/models/dl_keyed_belongs_to.rb +13 -0
  483. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  484. data/test/models/dl_keyed_has_many.rb +5 -0
  485. data/test/models/dl_keyed_has_many_through.rb +5 -0
  486. data/test/models/dl_keyed_has_one.rb +5 -0
  487. data/test/models/dl_keyed_join.rb +10 -0
  488. data/test/models/dog.rb +2 -0
  489. data/test/models/dog_lover.rb +2 -0
  490. data/test/models/doubloon.rb +3 -1
  491. data/test/models/drink_designer.rb +17 -0
  492. data/test/models/edge.rb +4 -2
  493. data/test/models/electron.rb +2 -0
  494. data/test/models/engine.rb +3 -2
  495. data/test/models/entrant.rb +2 -0
  496. data/test/models/entry.rb +5 -0
  497. data/test/models/essay.rb +6 -3
  498. data/test/models/essay_destroy_async.rb +12 -0
  499. data/test/models/event.rb +3 -1
  500. data/test/models/eye.rb +5 -3
  501. data/test/models/face.rb +14 -6
  502. data/test/models/family.rb +6 -0
  503. data/test/models/family_tree.rb +6 -0
  504. data/test/models/friendship.rb +5 -3
  505. data/test/models/frog.rb +8 -0
  506. data/test/models/guid.rb +3 -1
  507. data/test/models/guitar.rb +2 -0
  508. data/test/models/hotel.rb +5 -3
  509. data/test/models/human.rb +39 -0
  510. data/test/models/image.rb +3 -1
  511. data/test/models/interest.rb +14 -3
  512. data/test/models/invoice.rb +4 -2
  513. data/test/models/item.rb +3 -1
  514. data/test/models/job.rb +5 -3
  515. data/test/models/joke.rb +4 -2
  516. data/test/models/keyboard.rb +3 -1
  517. data/test/models/legacy_thing.rb +2 -0
  518. data/test/models/lesson.rb +2 -0
  519. data/test/models/line_item.rb +3 -1
  520. data/test/models/liquid.rb +2 -0
  521. data/test/models/matey.rb +3 -1
  522. data/test/models/measurement.rb +4 -0
  523. data/test/models/member.rb +23 -20
  524. data/test/models/member_detail.rb +3 -0
  525. data/test/models/member_type.rb +2 -0
  526. data/test/models/membership.rb +4 -1
  527. data/test/models/mentor.rb +3 -1
  528. data/test/models/message.rb +5 -0
  529. data/test/models/minimalistic.rb +2 -0
  530. data/test/models/minivan.rb +3 -2
  531. data/test/models/mixed_case_monkey.rb +3 -1
  532. data/test/models/molecule.rb +2 -0
  533. data/test/models/mouse.rb +6 -0
  534. data/test/models/movie.rb +2 -0
  535. data/test/models/node.rb +4 -2
  536. data/test/models/non_primary_key.rb +2 -0
  537. data/test/models/notification.rb +2 -0
  538. data/test/models/numeric_data.rb +12 -0
  539. data/test/models/order.rb +4 -2
  540. data/test/models/organization.rb +9 -7
  541. data/test/models/other_dog.rb +3 -1
  542. data/test/models/owner.rb +6 -4
  543. data/test/models/parrot.rb +12 -4
  544. data/test/models/person.rb +59 -54
  545. data/test/models/personal_legacy_thing.rb +3 -1
  546. data/test/models/pet.rb +4 -2
  547. data/test/models/pet_treasure.rb +2 -0
  548. data/test/models/pirate.rb +67 -43
  549. data/test/models/possession.rb +3 -1
  550. data/test/models/post.rb +184 -86
  551. data/test/models/price_estimate.rb +11 -1
  552. data/test/models/professor.rb +3 -1
  553. data/test/models/project.rb +14 -12
  554. data/test/models/publisher/article.rb +2 -0
  555. data/test/models/publisher/magazine.rb +2 -0
  556. data/test/models/publisher.rb +2 -0
  557. data/test/models/randomly_named_c1.rb +2 -0
  558. data/test/models/rating.rb +5 -1
  559. data/test/models/reader.rb +7 -5
  560. data/test/models/recipe.rb +2 -0
  561. data/test/models/record.rb +2 -0
  562. data/test/models/reference.rb +6 -3
  563. data/test/models/reply.rb +39 -21
  564. data/test/models/room.rb +6 -0
  565. data/test/models/section.rb +6 -0
  566. data/test/models/seminar.rb +6 -0
  567. data/test/models/session.rb +6 -0
  568. data/test/models/ship.rb +12 -9
  569. data/test/models/ship_part.rb +5 -3
  570. data/test/models/shop.rb +4 -2
  571. data/test/models/shop_account.rb +2 -0
  572. data/test/models/speedometer.rb +2 -0
  573. data/test/models/sponsor.rb +8 -5
  574. data/test/models/squeak.rb +6 -0
  575. data/test/models/strict_zine.rb +7 -0
  576. data/test/models/string_key_object.rb +2 -0
  577. data/test/models/student.rb +2 -0
  578. data/test/models/subscriber.rb +4 -2
  579. data/test/models/subscription.rb +5 -1
  580. data/test/models/tag.rb +6 -3
  581. data/test/models/tagging.rb +13 -6
  582. data/test/models/task.rb +2 -0
  583. data/test/models/topic.rb +54 -19
  584. data/test/models/toy.rb +4 -0
  585. data/test/models/traffic_light.rb +2 -0
  586. data/test/models/treasure.rb +5 -3
  587. data/test/models/treaty.rb +2 -4
  588. data/test/models/tree.rb +2 -0
  589. data/test/models/tuning_peg.rb +2 -0
  590. data/test/models/tyre.rb +2 -0
  591. data/test/models/user.rb +12 -4
  592. data/test/models/uuid_child.rb +2 -0
  593. data/test/models/uuid_item.rb +2 -0
  594. data/test/models/uuid_parent.rb +2 -0
  595. data/test/models/vegetables.rb +12 -3
  596. data/test/models/vertex.rb +6 -4
  597. data/test/models/warehouse_thing.rb +2 -0
  598. data/test/models/wheel.rb +3 -1
  599. data/test/models/without_table.rb +3 -1
  600. data/test/models/zine.rb +3 -1
  601. data/test/schema/mysql2_specific_schema.rb +49 -35
  602. data/test/schema/oracle_specific_schema.rb +13 -15
  603. data/test/schema/postgresql_specific_schema.rb +51 -40
  604. data/test/schema/schema.rb +334 -154
  605. data/test/schema/sqlite_specific_schema.rb +9 -16
  606. data/test/support/config.rb +26 -26
  607. data/test/support/connection.rb +14 -8
  608. data/test/support/connection_helper.rb +3 -1
  609. data/test/support/ddl_helper.rb +2 -0
  610. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  611. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  618. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  619. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  620. data/test/support/schema_dumping_helper.rb +2 -0
  621. data/test/support/stubs/strong_parameters.rb +40 -0
  622. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  623. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  624. metadata +196 -11
@@ -1,45 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cases/helper"
2
- require 'models/tag'
3
- require 'models/tagging'
4
- require 'models/post'
5
- require 'models/topic'
6
- require 'models/comment'
7
- require 'models/author'
8
- require 'models/entrant'
9
- require 'models/developer'
10
- require 'models/computer'
11
- require 'models/reply'
12
- require 'models/company'
13
- require 'models/bird'
14
- require 'models/car'
15
- require 'models/engine'
16
- require 'models/tyre'
17
- require 'models/minivan'
18
- require 'models/aircraft'
4
+ require "models/tag"
5
+ require "models/tagging"
6
+ require "models/post"
7
+ require "models/topic"
8
+ require "models/comment"
9
+ require "models/author"
10
+ require "models/entrant"
11
+ require "models/developer"
12
+ require "models/project"
13
+ require "models/person"
14
+ require "models/computer"
15
+ require "models/reply"
16
+ require "models/company"
17
+ require "models/contract"
18
+ require "models/bird"
19
+ require "models/car"
20
+ require "models/engine"
21
+ require "models/tyre"
22
+ require "models/minivan"
19
23
  require "models/possession"
20
24
  require "models/reader"
25
+ require "models/category"
21
26
  require "models/categorization"
22
27
  require "models/edge"
28
+ require "models/subscriber"
23
29
 
24
30
  class RelationTest < ActiveRecord::TestCase
25
- fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
26
- :tags, :taggings, :cars, :minivans
27
-
28
- class TopicWithCallbacks < ActiveRecord::Base
29
- self.table_name = :topics
30
- before_update { |topic| topic.author_name = 'David' if topic.author_name.blank? }
31
- end
31
+ fixtures :authors, :author_addresses, :topics, :entrants, :developers, :people, :companies, :developers_projects, :accounts, :categories, :categorizations, :categories_posts, :posts, :comments, :tags, :taggings, :cars, :minivans
32
32
 
33
33
  def test_do_not_double_quote_string_id
34
34
  van = Minivan.last
35
35
  assert van
36
- assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id
36
+ assert_equal van.id, Minivan.where(minivan_id: van).to_a.first.minivan_id
37
37
  end
38
38
 
39
39
  def test_do_not_double_quote_string_id_with_array
40
40
  van = Minivan.last
41
41
  assert van
42
- assert_equal van, Minivan.where(:minivan_id => [van]).to_a.first
42
+ assert_equal van, Minivan.where(minivan_id: [van]).to_a.first
43
43
  end
44
44
 
45
45
  def test_two_scopes_with_includes_should_not_drop_any_include
@@ -54,12 +54,12 @@ class RelationTest < ActiveRecord::TestCase
54
54
  end
55
55
 
56
56
  def test_dynamic_finder
57
- x = Post.where('author_id = ?', 1)
58
- assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders'
57
+ x = Post.where("author_id = ?", 1)
58
+ assert_respond_to x.klass, :find_by_id
59
59
  end
60
60
 
61
61
  def test_multivalue_where
62
- posts = Post.where('author_id = ? AND id = ?', 1, 1)
62
+ posts = Post.where("author_id = ? AND id = ?", 1, 1)
63
63
  assert_equal 1, posts.to_a.size
64
64
  end
65
65
 
@@ -93,50 +93,54 @@ class RelationTest < ActiveRecord::TestCase
93
93
  def test_loaded_all
94
94
  topics = Topic.all
95
95
 
96
+ assert_not_predicate topics, :loaded?
97
+ assert_not_predicate topics, :loaded
98
+
96
99
  assert_queries(1) do
97
100
  2.times { assert_equal 5, topics.to_a.size }
98
101
  end
99
102
 
100
- assert topics.loaded?
103
+ assert_predicate topics, :loaded?
104
+ assert_predicate topics, :loaded
101
105
  end
102
106
 
103
107
  def test_scoped_first
104
- topics = Topic.all.order('id ASC')
108
+ topics = Topic.all.order("id ASC")
105
109
 
106
110
  assert_queries(1) do
107
111
  2.times { assert_equal "The First Topic", topics.first.title }
108
112
  end
109
113
 
110
- assert ! topics.loaded?
114
+ assert_not_predicate topics, :loaded?
111
115
  end
112
116
 
113
117
  def test_loaded_first
114
- topics = Topic.all.order('id ASC')
115
- topics.to_a # force load
118
+ topics = Topic.all.order("id ASC")
119
+ topics.load # force load
116
120
 
117
121
  assert_no_queries do
118
122
  assert_equal "The First Topic", topics.first.title
119
123
  end
120
124
 
121
- assert topics.loaded?
125
+ assert_predicate topics, :loaded?
122
126
  end
123
127
 
124
128
  def test_loaded_first_with_limit
125
- topics = Topic.all.order('id ASC')
126
- topics.to_a # force load
129
+ topics = Topic.all.order("id ASC")
130
+ topics.load # force load
127
131
 
128
132
  assert_no_queries do
129
133
  assert_equal ["The First Topic",
130
134
  "The Second Topic of the day"], topics.first(2).map(&:title)
131
135
  end
132
136
 
133
- assert topics.loaded?
137
+ assert_predicate topics, :loaded?
134
138
  end
135
139
 
136
140
  def test_first_get_more_than_available
137
- topics = Topic.all.order('id ASC')
141
+ topics = Topic.all.order("id ASC")
138
142
  unloaded_first = topics.first(10)
139
- topics.to_a # force load
143
+ topics.load # force load
140
144
 
141
145
  assert_no_queries do
142
146
  loaded_first = topics.first(10)
@@ -151,28 +155,28 @@ class RelationTest < ActiveRecord::TestCase
151
155
  2.times { topics.to_a }
152
156
  end
153
157
 
154
- assert topics.loaded?
158
+ assert_predicate topics, :loaded?
155
159
 
156
160
  original_size = topics.to_a.size
157
- Topic.create! :title => 'fake'
161
+ Topic.create! title: "fake"
158
162
 
159
163
  assert_queries(1) { topics.reload }
160
164
  assert_equal original_size + 1, topics.size
161
- assert topics.loaded?
165
+ assert_predicate topics, :loaded?
162
166
  end
163
167
 
164
168
  def test_finding_with_subquery
165
- relation = Topic.where(:approved => true)
166
- assert_equal relation.to_a, Topic.select('*').from(relation).to_a
167
- assert_equal relation.to_a, Topic.select('subquery.*').from(relation).to_a
168
- assert_equal relation.to_a, Topic.select('a.*').from(relation, :a).to_a
169
+ relation = Topic.where(approved: true)
170
+ assert_equal relation.to_a, Topic.select("*").from(relation).to_a
171
+ assert_equal relation.to_a, Topic.select("subquery.*").from(relation).to_a
172
+ assert_equal relation.to_a, Topic.select("a.*").from(relation, :a).to_a
169
173
  end
170
174
 
171
175
  def test_finding_with_subquery_with_binds
172
176
  relation = Post.first.comments
173
- assert_equal relation.to_a, Comment.select('*').from(relation).to_a
174
- assert_equal relation.to_a, Comment.select('subquery.*').from(relation).to_a
175
- assert_equal relation.to_a, Comment.select('a.*').from(relation, :a).to_a
177
+ assert_equal relation.to_a, Comment.select("*").from(relation).to_a
178
+ assert_equal relation.to_a, Comment.select("subquery.*").from(relation).to_a
179
+ assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).to_a
176
180
  end
177
181
 
178
182
  def test_finding_with_subquery_without_select_does_not_change_the_select
@@ -182,26 +186,91 @@ class RelationTest < ActiveRecord::TestCase
182
186
  end
183
187
  end
184
188
 
189
+ def test_select_with_from_includes_original_table_name
190
+ relation = Comment.joins(:post).select(:id).order(:id)
191
+ subquery = Comment.from("#{Comment.table_name} /*! USE INDEX (PRIMARY) */").joins(:post).select(:id).order(:id)
192
+ assert_equal relation.map(&:id), subquery.map(&:id)
193
+ end
194
+
195
+ def test_pluck_with_from_includes_original_table_name
196
+ relation = Comment.joins(:post).order(:id)
197
+ subquery = Comment.from("#{Comment.table_name} /*! USE INDEX (PRIMARY) */").joins(:post).order(:id)
198
+ assert_equal relation.pluck(:id), subquery.pluck(:id)
199
+ end
200
+
201
+ def test_select_with_from_includes_quoted_original_table_name
202
+ relation = Comment.joins(:post).select(:id).order(:id)
203
+ subquery = Comment.from("#{Comment.quoted_table_name} /*! USE INDEX (PRIMARY) */").joins(:post).select(:id).order(:id)
204
+ assert_equal relation.map(&:id), subquery.map(&:id)
205
+ end
206
+
207
+ def test_pluck_with_from_includes_quoted_original_table_name
208
+ relation = Comment.joins(:post).order(:id)
209
+ subquery = Comment.from("#{Comment.quoted_table_name} /*! USE INDEX (PRIMARY) */").joins(:post).order(:id)
210
+ assert_equal relation.pluck(:id), subquery.pluck(:id)
211
+ end
212
+
213
+ def test_select_with_subquery_in_from_uses_original_table_name
214
+ puts "test_select_with_subquery_in_from_uses_original_table_name"
215
+ relation = Comment.joins(:post).select(:id).order(:id)
216
+ puts "After relation"
217
+ # Avoid subquery flattening by adding distinct to work with SQLite < 3.20.0.
218
+ subquery = Comment.from(Comment.all.distinct, Comment.quoted_table_name).joins(:post).select(:id).order(:id)
219
+ puts "After subquery"
220
+ assert_equal relation.map(&:id), subquery.map(&:id)
221
+ end
222
+
223
+ def test_pluck_with_subquery_in_from_uses_original_table_name
224
+ relation = Comment.joins(:post).order(:id)
225
+ subquery = Comment.from(Comment.all, Comment.quoted_table_name).joins(:post).order(:id)
226
+ assert_equal relation.pluck(:id), subquery.pluck(:id)
227
+ end
228
+
185
229
  def test_select_with_subquery_in_from_does_not_use_original_table_name
186
- relation = Comment.group(:type).select('COUNT(post_id) AS post_count, type')
187
- subquery = Comment.from(relation).select('type','post_count')
188
- assert_equal(relation.map(&:post_count).sort,subquery.map(&:post_count).sort)
230
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count, type")
231
+ subquery = Comment.from(relation, "grouped_#{Comment.table_name}").select("type", "post_count")
232
+ assert_equal(relation.map(&:post_count).sort, subquery.map(&:post_count).sort)
189
233
  end
190
234
 
191
235
  def test_group_with_subquery_in_from_does_not_use_original_table_name
192
- relation = Comment.group(:type).select('COUNT(post_id) AS post_count,type')
193
- subquery = Comment.from(relation).group('type').average("post_count")
194
- assert_equal(relation.map(&:post_count).sort,subquery.values.sort)
236
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count,type")
237
+ subquery = Comment.from(relation, "grouped_#{Comment.table_name}").group("type").average("post_count")
238
+ assert_equal(relation.map(&:post_count).sort, subquery.values.sort)
239
+ end
240
+
241
+ def test_select_with_subquery_string_in_from_does_not_use_original_table_name
242
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count, type")
243
+ subquery = Comment.from("(#{relation.to_sql}) #{Comment.table_name}_grouped").select("type", "post_count")
244
+ assert_equal(relation.map(&:post_count).sort, subquery.map(&:post_count).sort)
245
+ end
246
+
247
+ def test_group_with_subquery_string_in_from_does_not_use_original_table_name
248
+ puts "test_group_with_subquery_string_in_from_does_not_use_original_table_name"
249
+ relation = Comment.group(:type).select("COUNT(post_id) AS post_count,type")
250
+ subquery = Comment.from("(#{relation.to_sql}) #{Comment.table_name}_grouped").group("type").average("post_count")
251
+ assert_equal(relation.map(&:post_count).sort, subquery.values.sort)
252
+ end
253
+
254
+ def test_finding_with_subquery_with_eager_loading_in_from
255
+ relation = Comment.includes(:post).where("posts.type": "Post").order(:id)
256
+ assert_equal relation.to_a, Comment.select("*").from(relation).to_a
257
+ assert_equal relation.to_a, Comment.select("subquery.*").from(relation).to_a
258
+ assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).to_a
259
+ end
260
+
261
+ def test_finding_with_subquery_with_eager_loading_in_where
262
+ relation = Comment.includes(:post).where("posts.type": "Post")
263
+ assert_equal relation.sort_by(&:id), Comment.where(id: relation).sort_by(&:id)
195
264
  end
196
265
 
197
266
  def test_finding_with_conditions
198
- assert_equal ["David"], Author.where(:name => 'David').map(&:name)
199
- assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name)
200
- assert_equal ['Mary'], Author.where("name = ?", 'Mary').map(&:name)
267
+ assert_equal ["David"], Author.where(name: "David").map(&:name)
268
+ assert_equal ["Mary"], Author.where(["name = ?", "Mary"]).map(&:name)
269
+ assert_equal ["Mary"], Author.where("name = ?", "Mary").map(&:name)
201
270
  end
202
271
 
203
272
  def test_finding_with_order
204
- topics = Topic.order('id')
273
+ topics = Topic.order("id")
205
274
  assert_equal 5, topics.to_a.size
206
275
  assert_equal topics(:first).title, topics.first.title
207
276
  end
@@ -213,20 +282,42 @@ class RelationTest < ActiveRecord::TestCase
213
282
  end
214
283
 
215
284
  def test_finding_with_assoc_order
216
- topics = Topic.order(:id => :desc)
285
+ topics = Topic.order(id: :desc)
217
286
  assert_equal 5, topics.to_a.size
218
287
  assert_equal topics(:fifth).title, topics.first.title
219
288
  end
220
289
 
221
- def test_finding_with_reverted_assoc_order
222
- topics = Topic.order(:id => :asc).reverse_order
290
+ def test_finding_with_arel_assoc_order
291
+ topics = Topic.order(Arel.sql("id") => :desc)
292
+ assert_equal 5, topics.to_a.size
293
+ assert_equal topics(:fifth).title, topics.first.title
294
+ end
295
+
296
+ def test_finding_with_reversed_assoc_order
297
+ topics = Topic.order(id: :asc).reverse_order
298
+ assert_equal 5, topics.to_a.size
299
+ assert_equal topics(:fifth).title, topics.first.title
300
+ end
301
+
302
+ def test_finding_with_reversed_arel_assoc_order
303
+ topics = Topic.order(Arel.sql("id") => :asc).reverse_order
223
304
  assert_equal 5, topics.to_a.size
224
305
  assert_equal topics(:fifth).title, topics.first.title
225
306
  end
226
307
 
227
308
  def test_reverse_order_with_function
228
- topics = Topic.order("length(title)").reverse_order
229
- assert_equal topics(:second).title, topics.first.title
309
+ topics = Topic.order("lower(title)").reverse_order
310
+ assert_equal topics(:third).title, topics.first.title
311
+ end
312
+
313
+ def test_reverse_arel_order_with_function
314
+ topics = Topic.order(Topic.arel_table[:title].lower).reverse_order
315
+ assert_equal topics(:third).title, topics.first.title
316
+ end
317
+
318
+ def test_reverse_arel_assoc_order_with_function
319
+ topics = Topic.order(Arel.sql("lower(title)") => :asc).reverse_order
320
+ assert_equal topics(:third).title, topics.first.title
230
321
  end
231
322
 
232
323
  def test_reverse_order_with_function_other_predicates
@@ -238,16 +329,22 @@ class RelationTest < ActiveRecord::TestCase
238
329
 
239
330
  def test_reverse_order_with_multiargument_function
240
331
  assert_raises(ActiveRecord::IrreversibleOrderError) do
241
- Topic.order("concat(author_name, title)").reverse_order
332
+ Topic.order(Arel.sql("concat(author_name, title)")).reverse_order
242
333
  end
243
334
  assert_raises(ActiveRecord::IrreversibleOrderError) do
244
- Topic.order("concat(lower(author_name), title)").reverse_order
335
+ Topic.order(Arel.sql("concat(lower(author_name), title)")).reverse_order
245
336
  end
246
337
  assert_raises(ActiveRecord::IrreversibleOrderError) do
247
- Topic.order("concat(author_name, lower(title))").reverse_order
338
+ Topic.order(Arel.sql("concat(author_name, lower(title))")).reverse_order
248
339
  end
249
340
  assert_raises(ActiveRecord::IrreversibleOrderError) do
250
- Topic.order("concat(lower(author_name), title, length(title)").reverse_order
341
+ Topic.order(Arel.sql("concat(lower(author_name), title, length(title)")).reverse_order
342
+ end
343
+ end
344
+
345
+ def test_reverse_arel_assoc_order_with_multiargument_function
346
+ assert_nothing_raised do
347
+ Topic.order(Arel.sql("REPLACE(title, '', '')") => :asc).reverse_order
251
348
  end
252
349
  end
253
350
 
@@ -255,10 +352,19 @@ class RelationTest < ActiveRecord::TestCase
255
352
  assert_raises(ActiveRecord::IrreversibleOrderError) do
256
353
  Topic.order("title NULLS FIRST").reverse_order
257
354
  end
355
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
356
+ Topic.order("title NULLS FIRST").reverse_order
357
+ end
258
358
  assert_raises(ActiveRecord::IrreversibleOrderError) do
259
359
  Topic.order("title nulls last").reverse_order
260
360
  end
261
- end
361
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
362
+ Topic.order("title NULLS FIRST, author_name").reverse_order
363
+ end
364
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
365
+ Topic.order("author_name, title nulls last").reverse_order
366
+ end
367
+ end if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
262
368
 
263
369
  def test_default_reverse_order_on_table_without_primary_key
264
370
  assert_raises(ActiveRecord::IrreversibleOrderError) do
@@ -267,7 +373,7 @@ class RelationTest < ActiveRecord::TestCase
267
373
  end
268
374
 
269
375
  def test_order_with_hash_and_symbol_generates_the_same_sql
270
- assert_equal Topic.order(:id).to_sql, Topic.order(:id => :asc).to_sql
376
+ assert_equal Topic.order(:id).to_sql, Topic.order(id: :asc).to_sql
271
377
  end
272
378
 
273
379
  def test_finding_with_desc_order_with_string
@@ -277,7 +383,7 @@ class RelationTest < ActiveRecord::TestCase
277
383
  end
278
384
 
279
385
  def test_finding_with_asc_order_with_string
280
- topics = Topic.order(id: 'asc')
386
+ topics = Topic.order(id: "asc")
281
387
  assert_equal 5, topics.to_a.size
282
388
  assert_equal [topics(:first), topics(:second), topics(:third), topics(:fourth), topics(:fifth)], topics.to_a
283
389
  end
@@ -291,7 +397,7 @@ class RelationTest < ActiveRecord::TestCase
291
397
  assert_includes Topic.order(id: "DESC").to_sql, "DESC"
292
398
  assert_includes Topic.order(id: "desc").to_sql, "DESC"
293
399
  assert_includes Topic.order(id: :DESC).to_sql, "DESC"
294
- assert_includes Topic.order(id: :desc).to_sql,"DESC"
400
+ assert_includes Topic.order(id: :desc).to_sql, "DESC"
295
401
  end
296
402
 
297
403
  def test_raising_exception_on_invalid_hash_params
@@ -305,7 +411,7 @@ class RelationTest < ActiveRecord::TestCase
305
411
  end
306
412
 
307
413
  def test_finding_with_order_concatenated
308
- topics = Topic.order('author_name').order('title')
414
+ topics = Topic.order("author_name").order("title")
309
415
  assert_equal 5, topics.to_a.size
310
416
  assert_equal topics(:fourth).title, topics.first.title
311
417
  end
@@ -323,19 +429,24 @@ class RelationTest < ActiveRecord::TestCase
323
429
  end
324
430
 
325
431
  def test_finding_with_reorder
326
- topics = Topic.order('author_name').order('title').reorder('id').to_a
432
+ topics = Topic.order("author_name").order("title").reorder("id").to_a
327
433
  topics_titles = topics.map(&:title)
328
- assert_equal ['The First Topic', 'The Second Topic of the day', 'The Third Topic of the day', 'The Fourth Topic of the day', 'The Fifth Topic of the day'], topics_titles
434
+ assert_equal ["The First Topic", "The Second Topic of the day", "The Third Topic of the day", "The Fourth Topic of the day", "The Fifth Topic of the day"], topics_titles
435
+ end
436
+
437
+ def test_reorder_deduplication
438
+ topics = Topic.reorder("id desc", "id desc")
439
+ assert_equal ["id desc"], topics.order_values
329
440
  end
330
441
 
331
442
  def test_finding_with_reorder_by_aliased_attributes
332
- topics = Topic.order('author_name').reorder(:heading)
443
+ topics = Topic.order("author_name").reorder(:heading)
333
444
  assert_equal 5, topics.to_a.size
334
445
  assert_equal topics(:fifth).title, topics.first.title
335
446
  end
336
447
 
337
448
  def test_finding_with_assoc_reorder_by_aliased_attributes
338
- topics = Topic.order('author_name').reorder(heading: :desc)
449
+ topics = Topic.order("author_name").reorder(heading: :desc)
339
450
  assert_equal 5, topics.to_a.size
340
451
  assert_equal topics(:third).title, topics.first.title
341
452
  end
@@ -349,29 +460,29 @@ class RelationTest < ActiveRecord::TestCase
349
460
 
350
461
  def test_finding_with_cross_table_order_and_limit
351
462
  tags = Tag.includes(:taggings).
352
- order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
463
+ order("tags.name asc", "taggings.taggable_id asc", Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).
353
464
  limit(1).to_a
354
465
  assert_equal 1, tags.length
355
466
  end
356
467
 
357
468
  def test_finding_with_complex_order_and_limit
358
- tags = Tag.includes(:taggings).references(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a
469
+ tags = Tag.includes(:taggings).references(:taggings).order(Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).limit(1).to_a
359
470
  assert_equal 1, tags.length
360
471
  end
361
472
 
362
473
  def test_finding_with_complex_order
363
- tags = Tag.includes(:taggings).references(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
474
+ tags = Tag.includes(:taggings).references(:taggings).order(Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).to_a
364
475
  assert_equal 3, tags.length
365
476
  end
366
477
 
367
478
  def test_finding_with_sanitized_order
368
- query = Tag.order(["field(id, ?)", [1,3,2]]).to_sql
479
+ query = Tag.order([Arel.sql("field(id, ?)"), [1, 3, 2]]).to_sql
369
480
  assert_match(/field\(id, 1,3,2\)/, query)
370
481
 
371
- query = Tag.order(["field(id, ?)", []]).to_sql
482
+ query = Tag.order([Arel.sql("field(id, ?)"), []]).to_sql
372
483
  assert_match(/field\(id, NULL\)/, query)
373
484
 
374
- query = Tag.order(["field(id, ?)", nil]).to_sql
485
+ query = Tag.order([Arel.sql("field(id, ?)"), nil]).to_sql
375
486
  assert_match(/field\(id, NULL\)/, query)
376
487
  end
377
488
 
@@ -393,149 +504,32 @@ class RelationTest < ActiveRecord::TestCase
393
504
  end
394
505
 
395
506
  def test_select_with_block
396
- even_ids = Developer.all.select {|d| d.id % 2 == 0 }.map(&:id)
507
+ even_ids = Developer.all.select { |d| d.id % 2 == 0 }.map(&:id)
397
508
  assert_equal [2, 4, 6, 8, 10], even_ids.sort
398
509
  end
399
510
 
400
- def test_none
401
- assert_no_queries(ignore_none: false) do
402
- assert_equal [], Developer.none
403
- assert_equal [], Developer.all.none
404
- end
405
- end
406
-
407
- def test_none_chainable
408
- assert_no_queries(ignore_none: false) do
409
- assert_equal [], Developer.none.where(:name => 'David')
410
- end
411
- end
412
-
413
- def test_none_chainable_to_existing_scope_extension_method
414
- assert_no_queries(ignore_none: false) do
415
- assert_equal 1, Topic.anonymous_extension.none.one
416
- end
417
- end
418
-
419
- def test_none_chained_to_methods_firing_queries_straight_to_db
420
- assert_no_queries(ignore_none: false) do
421
- assert_equal [], Developer.none.pluck(:id, :name)
422
- assert_equal 0, Developer.none.delete_all
423
- assert_equal 0, Developer.none.update_all(:name => 'David')
424
- assert_equal 0, Developer.none.delete(1)
425
- assert_equal false, Developer.none.exists?(1)
426
- end
427
- end
428
-
429
- def test_null_relation_content_size_methods
430
- assert_no_queries(ignore_none: false) do
431
- assert_equal 0, Developer.none.size
432
- assert_equal 0, Developer.none.count
433
- assert_equal true, Developer.none.empty?
434
- assert_equal true, Developer.none.none?
435
- assert_equal false, Developer.none.any?
436
- assert_equal false, Developer.none.one?
437
- assert_equal false, Developer.none.many?
438
- end
439
- end
440
-
441
- def test_null_relation_calculations_methods
442
- assert_no_queries(ignore_none: false) do
443
- assert_equal 0, Developer.none.count
444
- assert_equal 0, Developer.none.calculate(:count, nil)
445
- assert_equal nil, Developer.none.calculate(:average, 'salary')
446
- end
447
- end
448
-
449
- def test_null_relation_metadata_methods
450
- assert_equal "", Developer.none.to_sql
451
- assert_equal({}, Developer.none.where_values_hash)
452
- end
453
-
454
- def test_null_relation_where_values_hash
455
- assert_equal({ 'salary' => 100_000 }, Developer.none.where(salary: 100_000).where_values_hash)
456
- end
457
-
458
- def test_null_relation_sum
459
- ac = Aircraft.new
460
- assert_equal Hash.new, ac.engines.group(:id).sum(:id)
461
- assert_equal 0, ac.engines.count
462
- ac.save
463
- assert_equal Hash.new, ac.engines.group(:id).sum(:id)
464
- assert_equal 0, ac.engines.count
465
- end
466
-
467
- def test_null_relation_count
468
- ac = Aircraft.new
469
- assert_equal Hash.new, ac.engines.group(:id).count
470
- assert_equal 0, ac.engines.count
471
- ac.save
472
- assert_equal Hash.new, ac.engines.group(:id).count
473
- assert_equal 0, ac.engines.count
474
- end
475
-
476
- def test_null_relation_size
477
- ac = Aircraft.new
478
- assert_equal Hash.new, ac.engines.group(:id).size
479
- assert_equal 0, ac.engines.size
480
- ac.save
481
- assert_equal Hash.new, ac.engines.group(:id).size
482
- assert_equal 0, ac.engines.size
483
- end
484
-
485
- def test_null_relation_average
486
- ac = Aircraft.new
487
- assert_equal Hash.new, ac.engines.group(:car_id).average(:id)
488
- assert_equal nil, ac.engines.average(:id)
489
- ac.save
490
- assert_equal Hash.new, ac.engines.group(:car_id).average(:id)
491
- assert_equal nil, ac.engines.average(:id)
492
- end
493
-
494
- def test_null_relation_minimum
495
- ac = Aircraft.new
496
- assert_equal Hash.new, ac.engines.group(:car_id).minimum(:id)
497
- assert_equal nil, ac.engines.minimum(:id)
498
- ac.save
499
- assert_equal Hash.new, ac.engines.group(:car_id).minimum(:id)
500
- assert_equal nil, ac.engines.minimum(:id)
501
- end
502
-
503
- def test_null_relation_maximum
504
- ac = Aircraft.new
505
- assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id)
506
- assert_equal nil, ac.engines.maximum(:id)
507
- ac.save
508
- assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id)
509
- assert_equal nil, ac.engines.maximum(:id)
510
- end
511
-
512
- def test_null_relation_in_where_condition
513
- assert_operator Comment.count, :>, 0 # precondition, make sure there are comments.
514
- assert_equal 0, Comment.where(post_id: Post.none).to_a.size
515
- end
516
-
517
511
  def test_joins_with_nil_argument
518
512
  assert_nothing_raised { DependentFirm.joins(nil).first }
519
513
  end
520
514
 
521
515
  def test_finding_with_hash_conditions_on_joined_table
522
- firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
516
+ firms = DependentFirm.joins(:account).where(name: "RailsCore", accounts: { credit_limit: 55..60 }).to_a
523
517
  assert_equal 1, firms.size
524
518
  assert_equal companies(:rails_core), firms.first
525
519
  end
526
520
 
527
521
  def test_find_all_with_join
528
- developers_on_project_one = Developer.joins('LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id').
529
- where('project_id=1').to_a
522
+ developers_on_project_one = Developer.joins("LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id").
523
+ where("project_id=1").to_a
530
524
 
531
525
  assert_equal 3, developers_on_project_one.length
532
526
  developer_names = developers_on_project_one.map(&:name)
533
- assert developer_names.include?('David')
534
- assert developer_names.include?('Jamis')
527
+ assert_includes developer_names, "David"
528
+ assert_includes developer_names, "Jamis"
535
529
  end
536
530
 
537
531
  def test_find_on_hash_conditions
538
- assert_equal Topic.all.merge!(:where => {:approved => false}).to_a, Topic.where({ :approved => false }).to_a
532
+ assert_equal Topic.all.merge!(where: { approved: false }).to_a, Topic.where(approved: false).to_a
539
533
  end
540
534
 
541
535
  def test_joins_with_string_array
@@ -553,6 +547,14 @@ class RelationTest < ActiveRecord::TestCase
553
547
  assert_raises(ArgumentError) { Topic.preload() }
554
548
  assert_raises(ArgumentError) { Topic.group() }
555
549
  assert_raises(ArgumentError) { Topic.reorder() }
550
+ assert_raises(ArgumentError) { Topic.order() }
551
+ assert_raises(ArgumentError) { Topic.eager_load() }
552
+ assert_raises(ArgumentError) { Topic.reselect() }
553
+ assert_raises(ArgumentError) { Topic.unscope() }
554
+ assert_raises(ArgumentError) { Topic.joins() }
555
+ assert_raises(ArgumentError) { Topic.left_joins() }
556
+ assert_raises(ArgumentError) { Topic.optimizer_hints() }
557
+ assert_raises(ArgumentError) { Topic.annotate() }
556
558
  end
557
559
 
558
560
  def test_blank_like_arguments_to_query_methods_dont_raise_errors
@@ -561,55 +563,36 @@ class RelationTest < ActiveRecord::TestCase
561
563
  assert_nothing_raised { Topic.preload([]) }
562
564
  assert_nothing_raised { Topic.group([]) }
563
565
  assert_nothing_raised { Topic.reorder([]) }
564
- end
565
-
566
- def test_scoped_responds_to_delegated_methods
567
- relation = Topic.all
568
-
569
- ["map", "uniq", "sort", "insert", "delete", "update"].each do |method|
570
- assert_respond_to relation, method, "Topic.all should respond to #{method.inspect}"
571
- end
572
- end
573
-
574
- def test_respond_to_delegates_to_relation
575
- relation = Topic.all
576
- fake_arel = Struct.new(:responds) {
577
- def respond_to? method, access = false
578
- responds << [method, access]
579
- end
580
- }.new []
581
-
582
- relation.extend(Module.new { attr_accessor :arel })
583
- relation.arel = fake_arel
584
-
585
- relation.respond_to?(:matching_attributes)
586
- assert_equal [:matching_attributes, false], fake_arel.responds.first
587
-
588
- fake_arel.responds = []
589
- relation.respond_to?(:matching_attributes, true)
590
- assert_equal [:matching_attributes, true], fake_arel.responds.first
566
+ assert_nothing_raised { Topic.order([]) }
567
+ assert_nothing_raised { Topic.eager_load([]) }
568
+ assert_nothing_raised { Topic.reselect([]) }
569
+ assert_nothing_raised { Topic.unscope([]) }
570
+ assert_nothing_raised { Topic.joins([]) }
571
+ assert_nothing_raised { Topic.left_joins([]) }
572
+ assert_nothing_raised { Topic.optimizer_hints([]) }
573
+ assert_nothing_raised { Topic.annotate([]) }
591
574
  end
592
575
 
593
576
  def test_respond_to_dynamic_finders
594
577
  relation = Topic.all
595
578
 
596
579
  ["find_by_title", "find_by_title_and_author_name"].each do |method|
597
- assert_respond_to relation, method, "Topic.all should respond to #{method.inspect}"
580
+ assert_respond_to relation, method
598
581
  end
599
582
  end
600
583
 
601
584
  def test_respond_to_class_methods_and_scopes
602
- assert Topic.all.respond_to?(:by_lifo)
585
+ assert_respond_to Topic.all, :by_lifo
603
586
  end
604
587
 
605
588
  def test_find_with_readonly_option
606
- Developer.all.each { |d| assert !d.readonly? }
589
+ Developer.all.each { |d| assert_not d.readonly? }
607
590
  Developer.all.readonly.each { |d| assert d.readonly? }
608
591
  end
609
592
 
610
593
  def test_eager_association_loading_of_stis_with_multiple_references
611
- authors = Author.eager_load(:posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } }).
612
- order('comments.body, very_special_comments_posts.body').where('posts.id = 4').to_a
594
+ authors = Author.eager_load(posts: { special_comments: { post: [ :special_comments, :very_special_comment ] } }).
595
+ order("comments.body, very_special_comments_posts.body").where("posts.id = 4").to_a
613
596
 
614
597
  assert_equal [authors(:david)], authors
615
598
  assert_no_queries do
@@ -620,27 +603,27 @@ class RelationTest < ActiveRecord::TestCase
620
603
 
621
604
  def test_find_with_preloaded_associations
622
605
  assert_queries(2) do
623
- posts = Post.preload(:comments).order('posts.id')
606
+ posts = Post.preload(:comments).order("posts.id")
624
607
  assert posts.first.comments.first
625
608
  end
626
609
 
627
610
  assert_queries(2) do
628
- posts = Post.preload(:comments).order('posts.id')
611
+ posts = Post.preload(:comments).order("posts.id")
629
612
  assert posts.first.comments.first
630
613
  end
631
614
 
632
615
  assert_queries(2) do
633
- posts = Post.preload(:author).order('posts.id')
616
+ posts = Post.preload(:author).order("posts.id")
634
617
  assert posts.first.author
635
618
  end
636
619
 
637
620
  assert_queries(2) do
638
- posts = Post.preload(:author).order('posts.id')
621
+ posts = Post.preload(:author).order("posts.id")
639
622
  assert posts.first.author
640
623
  end
641
624
 
642
625
  assert_queries(3) do
643
- posts = Post.preload(:author, :comments).order('posts.id')
626
+ posts = Post.preload(:author, :comments).order("posts.id")
644
627
  assert posts.first.author
645
628
  assert posts.first.comments.first
646
629
  end
@@ -653,60 +636,57 @@ class RelationTest < ActiveRecord::TestCase
653
636
  end
654
637
  end
655
638
 
639
+ def test_extracted_association
640
+ relation_authors = assert_queries(2) { Post.all.extract_associated(:author) }
641
+ root_authors = assert_queries(2) { Post.extract_associated(:author) }
642
+ assert_equal relation_authors, root_authors
643
+ assert_equal Post.all.collect(&:author), relation_authors
644
+ end
645
+
656
646
  def test_find_with_included_associations
657
647
  assert_queries(2) do
658
- posts = Post.includes(:comments).order('posts.id')
648
+ posts = Post.includes(:comments).order("posts.id")
659
649
  assert posts.first.comments.first
660
650
  end
661
651
 
662
652
  assert_queries(2) do
663
- posts = Post.all.includes(:comments).order('posts.id')
653
+ posts = Post.all.includes(:comments).order("posts.id")
664
654
  assert posts.first.comments.first
665
655
  end
666
656
 
667
657
  assert_queries(2) do
668
- posts = Post.includes(:author).order('posts.id')
658
+ posts = Post.includes(:author).order("posts.id")
669
659
  assert posts.first.author
670
660
  end
671
661
 
672
662
  assert_queries(3) do
673
- posts = Post.includes(:author, :comments).order('posts.id')
663
+ posts = Post.includes(:author, :comments).order("posts.id")
674
664
  assert posts.first.author
675
665
  assert posts.first.comments.first
676
666
  end
677
667
  end
678
668
 
679
- def test_default_scope_with_conditions_string
680
- assert_equal Developer.where(name: 'David').map(&:id).sort, DeveloperCalledDavid.all.map(&:id).sort
681
- assert_nil DeveloperCalledDavid.create!.name
682
- end
683
-
684
- def test_default_scope_with_conditions_hash
685
- assert_equal Developer.where(name: 'Jamis').map(&:id).sort, DeveloperCalledJamis.all.map(&:id).sort
686
- assert_equal 'Jamis', DeveloperCalledJamis.create!.name
687
- end
688
-
689
669
  def test_default_scoping_finder_methods
690
- developers = DeveloperCalledDavid.order('id').map(&:id).sort
691
- assert_equal Developer.where(name: 'David').map(&:id).sort, developers
670
+ developers = DeveloperCalledDavid.order("id").map(&:id).sort
671
+ assert_equal Developer.where(name: "David").map(&:id).sort, developers
692
672
  end
693
673
 
694
674
  def test_includes_with_select
695
- query = Post.select('comments_count AS ranking').order('ranking').includes(:comments)
675
+ query = Post.select("legacy_comments_count AS ranking").order("ranking").includes(:comments)
696
676
  .where(comments: { id: 1 })
697
677
 
698
- assert_equal ['comments_count AS ranking'], query.select_values
678
+ assert_equal ["legacy_comments_count AS ranking"], query.select_values
699
679
  assert_equal 1, query.to_a.size
700
680
  end
701
681
 
702
682
  def test_preloading_with_associations_and_merges
703
- post = Post.create! title: 'Uhuu', body: 'body'
683
+ post = Post.create! title: "Uhuu", body: "body"
704
684
  reader = Reader.create! post_id: post.id, person_id: 1
705
- comment = Comment.create! post_id: post.id, body: 'body'
685
+ comment = Comment.create! post_id: post.id, body: "body"
706
686
 
707
- assert !comment.respond_to?(:readers)
687
+ assert_not_respond_to comment, :readers
708
688
 
709
- post_rel = Post.preload(:readers).joins(:readers).where(title: 'Uhuu')
689
+ post_rel = Post.preload(:readers).joins(:readers).where(title: "Uhuu")
710
690
  result_comment = Comment.joins(:post).merge(post_rel).to_a.first
711
691
  assert_equal comment, result_comment
712
692
 
@@ -715,7 +695,7 @@ class RelationTest < ActiveRecord::TestCase
715
695
  assert_equal [reader], result_comment.post.readers.to_a
716
696
  end
717
697
 
718
- post_rel = Post.includes(:readers).where(title: 'Uhuu')
698
+ post_rel = Post.includes(:readers).where(title: "Uhuu")
719
699
  result_comment = Comment.joins(:post).merge(post_rel).first
720
700
  assert_equal comment, result_comment
721
701
 
@@ -726,17 +706,17 @@ class RelationTest < ActiveRecord::TestCase
726
706
  end
727
707
 
728
708
  def test_preloading_with_associations_default_scopes_and_merges
729
- post = Post.create! title: 'Uhuu', body: 'body'
709
+ post = Post.create! title: "Uhuu", body: "body"
730
710
  reader = Reader.create! post_id: post.id, person_id: 1
731
711
 
732
- post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: 'Uhuu')
712
+ post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: "Uhuu")
733
713
  result_post = PostWithPreloadDefaultScope.all.merge(post_rel).to_a.first
734
714
 
735
715
  assert_no_queries do
736
716
  assert_equal [reader], result_post.readers.to_a
737
717
  end
738
718
 
739
- post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: 'Uhuu')
719
+ post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: "Uhuu")
740
720
  result_post = PostWithIncludesDefaultScope.all.merge(post_rel).to_a.first
741
721
 
742
722
  assert_no_queries do
@@ -748,11 +728,11 @@ class RelationTest < ActiveRecord::TestCase
748
728
  posts = Post.preload(:comments)
749
729
  post = posts.find { |p| p.id == 1 }
750
730
  assert_equal 2, post.comments.size
751
- assert post.comments.include?(comments(:greetings))
731
+ assert_includes post.comments, comments(:greetings)
752
732
 
753
733
  post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
754
734
  assert_equal 2, post.comments.size
755
- assert post.comments.include?(comments(:greetings))
735
+ assert_includes post.comments, comments(:greetings)
756
736
 
757
737
  posts = Post.preload(:last_comment)
758
738
  post = posts.find { |p| p.id == 1 }
@@ -760,10 +740,10 @@ class RelationTest < ActiveRecord::TestCase
760
740
  end
761
741
 
762
742
  def test_to_sql_on_eager_join
763
- expected = assert_sql {
764
- Post.eager_load(:last_comment).order('comments.id DESC').to_a
743
+ expected = capture_sql {
744
+ Post.eager_load(:last_comment).order("comments.id DESC").to_a
765
745
  }.first
766
- actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
746
+ actual = Post.eager_load(:last_comment).order("comments.id DESC").to_sql
767
747
  assert_equal expected, actual
768
748
  end
769
749
 
@@ -774,7 +754,7 @@ class RelationTest < ActiveRecord::TestCase
774
754
  end
775
755
 
776
756
  def test_loading_with_one_association_with_non_preload
777
- posts = Post.eager_load(:last_comment).order('comments.id DESC')
757
+ posts = Post.eager_load(:last_comment).order("comments.id DESC")
778
758
  post = posts.find { |p| p.id == 1 }
779
759
  assert_equal Post.find(1).last_comment, post.last_comment
780
760
  end
@@ -785,7 +765,6 @@ class RelationTest < ActiveRecord::TestCase
785
765
  expected_taggings = taggings(:welcome_general, :thinking_general)
786
766
 
787
767
  assert_no_queries do
788
- assert_equal expected_taggings, author.taggings.distinct.sort_by(&:id)
789
768
  assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id)
790
769
  end
791
770
 
@@ -798,56 +777,74 @@ class RelationTest < ActiveRecord::TestCase
798
777
  author = Author.all.find_by_id!(authors(:david).id)
799
778
  assert_equal "David", author.name
800
779
 
801
- assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, 'invalid') }
780
+ assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, "invalid") }
802
781
  end
803
782
 
804
783
  def test_find_id
805
784
  authors = Author.all
806
785
 
807
786
  david = authors.find(authors(:david).id)
808
- assert_equal 'David', david.name
787
+ assert_equal "David", david.name
809
788
 
810
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
789
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(name: "lifo").find("42") }
811
790
  end
812
791
 
813
792
  def test_find_ids
814
- authors = Author.order('id ASC')
793
+ authors = Author.order("id ASC")
815
794
 
816
795
  results = authors.find(authors(:david).id, authors(:mary).id)
817
796
  assert_kind_of Array, results
818
797
  assert_equal 2, results.size
819
- assert_equal 'David', results[0].name
820
- assert_equal 'Mary', results[1].name
798
+ assert_equal "David", results[0].name
799
+ assert_equal "Mary", results[1].name
821
800
  assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
822
801
 
823
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
824
- assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
802
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(name: "lifo").find(authors(:david).id, "42") }
803
+ assert_raises(ActiveRecord::RecordNotFound) { authors.find(["42", 43]) }
825
804
  end
826
805
 
827
806
  def test_find_in_empty_array
828
- authors = Author.all.where(:id => [])
829
- assert authors.to_a.blank?
807
+ authors = Author.all.where(id: [])
808
+ assert_predicate authors.to_a, :blank?
830
809
  end
831
810
 
832
811
  def test_where_with_ar_object
833
812
  author = Author.first
834
- authors = Author.all.where(:id => author)
813
+ authors = Author.all.where(id: author)
835
814
  assert_equal 1, authors.to_a.length
836
815
  end
837
816
 
838
- def test_find_with_list_of_ar
817
+ def test_where_with_ar_relation
818
+ author = Post.last.author
819
+ posts = Post.all.where(author: author)
820
+ assert_equal 3, posts.to_a.length
821
+ end
822
+
823
+ def test_where_id_with_delegated_ar_object
824
+ decorator = Class.new(SimpleDelegator)
839
825
  author = Author.first
840
- authors = Author.find([author.id])
841
- assert_equal author, authors.first
826
+ assert_equal 1, Author.where(id: decorator.new(author)).to_a.length
827
+ assert_equal 1, Author.where(id: [decorator.new(author)]).to_a.length
842
828
  end
843
829
 
844
- class Mary < Author; end
830
+ def test_where_relation_with_delegated_ar_object
831
+ decorator = Class.new(SimpleDelegator)
832
+ author = Post.last.author
833
+ assert_equal 3, Post.where(author: decorator.new(author)).to_a.length
834
+ assert_equal 3, Post.where(author: [decorator.new(author)]).to_a.length
835
+ end
845
836
 
846
- def test_find_by_classname
847
- Author.create!(:name => Mary.name)
848
- assert_deprecated do
849
- assert_equal 1, Author.where(:name => Mary).size
850
- end
837
+ def test_find_by_with_delegated_ar_object
838
+ decorator = Class.new(SimpleDelegator)
839
+ author = Author.first
840
+ assert_equal author, Author.find_by(id: decorator.new(author))
841
+ assert_equal author, Author.find_by(id: [decorator.new(author)])
842
+ end
843
+
844
+ def test_find_with_list_of_ar
845
+ author = Author.first
846
+ authors = Author.find([author.id])
847
+ assert_equal author, authors.first
851
848
  end
852
849
 
853
850
  def test_find_by_id_with_list_of_ar
@@ -859,25 +856,25 @@ class RelationTest < ActiveRecord::TestCase
859
856
  def test_find_all_using_where_twice_should_or_the_relation
860
857
  david = authors(:david)
861
858
  relation = Author.unscoped
862
- relation = relation.where(:name => david.name)
863
- relation = relation.where(:name => 'Santiago')
864
- relation = relation.where(:id => david.id)
859
+ relation = relation.where(name: david.name)
860
+ relation = relation.where(name: "Santiago")
861
+ relation = relation.where(id: david.id)
865
862
  assert_equal [], relation.to_a
866
863
  end
867
864
 
868
865
  def test_multi_where_ands_queries
869
866
  relation = Author.unscoped
870
867
  david = authors(:david)
871
- sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
872
- assert_match('AND', sql)
868
+ sql = relation.where(name: david.name).where(name: "Santiago").to_sql
869
+ assert_match("AND", sql)
873
870
  end
874
871
 
875
872
  def test_find_all_with_multiple_should_use_and
876
873
  david = authors(:david)
877
874
  relation = [
878
- { :name => david.name },
879
- { :name => 'Santiago' },
880
- { :name => 'tenderlove' },
875
+ { name: david.name },
876
+ { name: "Santiago" },
877
+ { name: "tenderlove" },
881
878
  ].inject(Author.unscoped) do |memo, param|
882
879
  memo.where(param)
883
880
  end
@@ -893,20 +890,18 @@ class RelationTest < ActiveRecord::TestCase
893
890
 
894
891
  def test_find_all_using_where_with_relation
895
892
  david = authors(:david)
896
- # switching the lines below would succeed in current rails
897
- # assert_queries(2) {
898
893
  assert_queries(1) {
899
- relation = Author.where(:id => Author.where(:id => david.id))
894
+ relation = Author.where(id: Author.where(id: david.id))
900
895
  assert_equal [david], relation.to_a
901
896
  }
902
897
 
903
898
  assert_queries(1) {
904
- relation = Author.where('id in (?)', Author.where(id: david).select(:id))
899
+ relation = Author.where("id in (?)", Author.where(id: david).select(:id))
905
900
  assert_equal [david], relation.to_a
906
901
  }
907
902
 
908
903
  assert_queries(1) do
909
- relation = Author.where('id in (:author_ids)', author_ids: Author.where(id: david).select(:id))
904
+ relation = Author.where("id in (:author_ids)", author_ids: Author.where(id: david).select(:id))
910
905
  assert_equal [david], relation.to_a
911
906
  end
912
907
  end
@@ -921,22 +916,20 @@ class RelationTest < ActiveRecord::TestCase
921
916
  end
922
917
 
923
918
  assert_queries(1) do
924
- relation = Post.where('id in (?)', david.posts.select(:id))
925
- assert_equal davids_posts, relation.order(:id).to_a, 'should process Relation as bind variables'
919
+ relation = Post.where("id in (?)", david.posts.select(:id))
920
+ assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as bind variables"
926
921
  end
927
922
 
928
923
  assert_queries(1) do
929
- relation = Post.where('id in (:post_ids)', post_ids: david.posts.select(:id))
930
- assert_equal davids_posts, relation.order(:id).to_a, 'should process Relation as named bind variables'
924
+ relation = Post.where("id in (:post_ids)", post_ids: david.posts.select(:id))
925
+ assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as named bind variables"
931
926
  end
932
927
  end
933
928
 
934
929
  def test_find_all_using_where_with_relation_and_alternate_primary_key
935
930
  cool_first = minivans(:cool_first)
936
- # switching the lines below would succeed in current rails
937
- # assert_queries(2) {
938
931
  assert_queries(1) {
939
- relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
932
+ relation = Minivan.where(minivan_id: Minivan.where(name: cool_first.name))
940
933
  assert_equal [cool_first], relation.to_a
941
934
  }
942
935
  end
@@ -944,10 +937,10 @@ class RelationTest < ActiveRecord::TestCase
944
937
  def test_find_all_using_where_with_relation_does_not_alter_select_values
945
938
  david = authors(:david)
946
939
 
947
- subquery = Author.where(:id => david.id)
940
+ subquery = Author.where(id: david.id)
948
941
 
949
942
  assert_queries(1) {
950
- relation = Author.where(:id => subquery)
943
+ relation = Author.where(id: subquery)
951
944
  assert_equal [david], relation.to_a
952
945
  }
953
946
 
@@ -957,112 +950,32 @@ class RelationTest < ActiveRecord::TestCase
957
950
  def test_find_all_using_where_with_relation_with_joins
958
951
  david = authors(:david)
959
952
  assert_queries(1) {
960
- relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
953
+ relation = Author.where(id: Author.joins(:posts).where(id: david.id))
961
954
  assert_equal [david], relation.to_a
962
955
  }
963
956
  end
964
957
 
965
-
966
958
  def test_find_all_using_where_with_relation_with_select_to_build_subquery
967
959
  david = authors(:david)
968
960
  assert_queries(1) {
969
- relation = Author.where(:name => Author.where(:id => david.id).select(:name))
961
+ relation = Author.where(name: Author.where(id: david.id).select(:name))
970
962
  assert_equal [david], relation.to_a
971
963
  }
972
964
  end
973
965
 
974
- def test_exists
975
- davids = Author.where(:name => 'David')
976
- assert davids.exists?
977
- assert davids.exists?(authors(:david).id)
978
- assert ! davids.exists?(authors(:mary).id)
979
- assert ! davids.exists?("42")
980
- assert ! davids.exists?(42)
981
- assert ! davids.exists?(davids.new.id)
982
-
983
- fake = Author.where(:name => 'fake author')
984
- assert ! fake.exists?
985
- assert ! fake.exists?(authors(:david).id)
986
- end
987
-
988
- def test_exists_uses_existing_scope
989
- post = authors(:david).posts.first
990
- authors = Author.includes(:posts).where(name: "David", posts: { id: post.id })
991
- assert authors.exists?(authors(:david).id)
992
- end
993
-
994
- def test_any_with_scope_on_hash_includes
995
- post = authors(:david).posts.first
996
- categories = Categorization.includes(author: :posts).where(posts: { id: post.id })
997
- assert categories.exists?
998
- end
999
-
1000
966
  def test_last
1001
967
  authors = Author.all
1002
968
  assert_equal authors(:bob), authors.last
1003
969
  end
1004
970
 
1005
- def test_destroy_all
1006
- davids = Author.where(:name => 'David')
1007
-
1008
- # Force load
1009
- assert_equal [authors(:david)], davids.to_a
1010
- assert davids.loaded?
1011
-
1012
- assert_difference('Author.count', -1) { davids.destroy_all }
1013
-
1014
- assert_equal [], davids.to_a
1015
- assert davids.loaded?
1016
- end
1017
-
1018
- def test_destroy_all_with_conditions_is_deprecated
1019
- assert_deprecated do
1020
- assert_difference('Author.count', -1) { Author.destroy_all(name: 'David') }
1021
- end
1022
- end
1023
-
1024
- def test_delete_all
1025
- davids = Author.where(:name => 'David')
1026
-
1027
- assert_difference('Author.count', -1) { davids.delete_all }
1028
- assert ! davids.loaded?
1029
- end
1030
-
1031
- def test_delete_all_with_conditions_is_deprecated
1032
- assert_deprecated do
1033
- assert_difference('Author.count', -1) { Author.delete_all(name: 'David') }
1034
- end
1035
- end
1036
-
1037
- def test_delete_all_loaded
1038
- davids = Author.where(:name => 'David')
1039
-
1040
- # Force load
1041
- assert_equal [authors(:david)], davids.to_a
1042
- assert davids.loaded?
1043
-
1044
- assert_difference('Author.count', -1) { davids.delete_all }
1045
-
1046
- assert_equal [], davids.to_a
1047
- assert davids.loaded?
1048
- end
1049
-
1050
- def test_delete_all_with_unpermitted_relation_raises_error
1051
- assert_raises(ActiveRecord::ActiveRecordError) { Author.limit(10).delete_all }
1052
- assert_raises(ActiveRecord::ActiveRecordError) { Author.distinct.delete_all }
1053
- assert_raises(ActiveRecord::ActiveRecordError) { Author.group(:name).delete_all }
1054
- assert_raises(ActiveRecord::ActiveRecordError) { Author.having('SUM(id) < 3').delete_all }
1055
- assert_raises(ActiveRecord::ActiveRecordError) { Author.offset(10).delete_all }
1056
- end
1057
-
1058
971
  def test_select_with_aggregates
1059
972
  posts = Post.select(:title, :body)
1060
973
 
1061
974
  assert_equal 11, posts.count(:all)
1062
975
  assert_equal 11, posts.size
1063
- assert posts.any?
1064
- assert posts.many?
1065
- assert_not posts.empty?
976
+ assert_predicate posts, :any?
977
+ assert_predicate posts, :many?
978
+ assert_not_empty posts
1066
979
  end
1067
980
 
1068
981
  def test_select_takes_a_variable_list_of_args
@@ -1084,6 +997,10 @@ class RelationTest < ActiveRecord::TestCase
1084
997
  assert_raises(ArgumentError) { Developer.select }
1085
998
  end
1086
999
 
1000
+ def test_select_argument_error_with_block
1001
+ assert_raises(ArgumentError) { Developer.select(:id) { |d| d.id % 2 == 0 } }
1002
+ end
1003
+
1087
1004
  def test_count
1088
1005
  posts = Post.all
1089
1006
 
@@ -1091,8 +1008,13 @@ class RelationTest < ActiveRecord::TestCase
1091
1008
  assert_equal 11, posts.count(:all)
1092
1009
  assert_equal 11, posts.count(:id)
1093
1010
 
1094
- assert_equal 1, posts.where('comments_count > 1').count
1095
- assert_equal 9, posts.where(:comments_count => 0).count
1011
+ assert_equal 3, posts.where("legacy_comments_count > 1").count
1012
+ assert_equal 6, posts.where(comments_count: 0).count
1013
+ end
1014
+
1015
+ def test_count_with_block
1016
+ posts = Post.all
1017
+ assert_equal 8, posts.count { |p| p.comments_count.even? }
1096
1018
  end
1097
1019
 
1098
1020
  def test_count_on_association_relation
@@ -1103,42 +1025,65 @@ class RelationTest < ActiveRecord::TestCase
1103
1025
  assert_equal author.posts.where(author_id: author.id).size, posts.count
1104
1026
 
1105
1027
  assert_equal 0, author.posts.where(author_id: another_author.id).size
1106
- assert author.posts.where(author_id: another_author.id).empty?
1028
+ assert_empty author.posts.where(author_id: another_author.id)
1107
1029
  end
1108
1030
 
1109
1031
  def test_count_with_distinct
1110
1032
  posts = Post.all
1111
1033
 
1112
- assert_equal 3, posts.distinct(true).count(:comments_count)
1034
+ assert_equal 4, posts.distinct(true).count(:comments_count)
1113
1035
  assert_equal 11, posts.distinct(false).count(:comments_count)
1114
1036
 
1115
- assert_equal 3, posts.distinct(true).select(:comments_count).count
1037
+ assert_equal 4, posts.distinct(true).select(:comments_count).count
1116
1038
  assert_equal 11, posts.distinct(false).select(:comments_count).count
1117
1039
  end
1118
1040
 
1119
- def test_update_all_with_scope
1120
- tag = Tag.first
1121
- Post.tagged_with(tag.id).update_all title: "rofl"
1122
- list = Post.tagged_with(tag.id).all.to_a
1123
- assert_operator list.length, :>, 0
1124
- list.each { |post| assert_equal 'rofl', post.title }
1041
+ def test_size_with_distinct
1042
+ posts = Post.distinct.select(:author_id, :comments_count)
1043
+ assert_queries(1) { assert_equal 8, posts.size }
1044
+ assert_queries(1) { assert_equal 8, posts.load.size }
1045
+ end
1046
+
1047
+ def test_size_with_eager_loading_and_custom_order
1048
+ posts = Post.includes(:comments).order("comments.id")
1049
+ assert_queries(1) { assert_equal 11, posts.size }
1050
+ assert_queries(1) { assert_equal 11, posts.load.size }
1051
+ end
1052
+
1053
+ def test_size_with_eager_loading_and_custom_select_and_order
1054
+ posts = Post.includes(:comments).order("comments.id").select(:type)
1055
+ assert_queries(1) { assert_equal 11, posts.size }
1056
+ assert_queries(1) { assert_equal 11, posts.load.size }
1057
+ end
1058
+
1059
+ def test_size_with_eager_loading_and_custom_order_and_distinct
1060
+ posts = Post.includes(:comments).order("comments.id").distinct
1061
+ assert_queries(1) { assert_equal 11, posts.size }
1062
+ assert_queries(1) { assert_equal 11, posts.load.size }
1063
+ end
1064
+
1065
+ def test_size_with_eager_loading_and_manual_distinct_select_and_custom_order
1066
+ accounts = Account.select("DISTINCT accounts.firm_id").order("accounts.firm_id")
1067
+
1068
+ assert_queries(1) { assert_equal 5, accounts.size }
1069
+ assert_queries(1) { assert_equal 5, accounts.load.size }
1125
1070
  end
1126
1071
 
1127
1072
  def test_count_explicit_columns
1128
- Post.update_all(:comments_count => nil)
1073
+ Post.update_all(comments_count: nil)
1129
1074
  posts = Post.all
1130
1075
 
1131
- assert_equal [0], posts.select('comments_count').where('id is not null').group('id').order('id').count.values.uniq
1132
- assert_equal 0, posts.where('id is not null').select('comments_count').count
1076
+ assert_equal [0], posts.select("comments_count").where("id is not null").group("id").order("id").count.values.uniq
1077
+ assert_equal 0, posts.where("id is not null").select("comments_count").count
1133
1078
 
1134
- assert_equal 11, posts.select('comments_count').count('id')
1135
- assert_equal 0, posts.select('comments_count').count
1079
+ assert_equal 11, posts.select("comments_count").count("id")
1080
+ assert_equal 0, posts.select("comments_count").count
1136
1081
  assert_equal 0, posts.count(:comments_count)
1137
- assert_equal 0, posts.count('comments_count')
1082
+ assert_equal 0, posts.count("comments_count")
1138
1083
  end
1139
1084
 
1140
1085
  def test_multiple_selects
1141
- post = Post.all.select('comments_count').select('title').order("id ASC").first
1086
+ post = Post.all.select("comments_count").select("title").order("id ASC").first
1142
1087
  assert_equal "Welcome to the weblog", post.title
1143
1088
  assert_equal 2, post.comments_count
1144
1089
  end
@@ -1147,31 +1092,31 @@ class RelationTest < ActiveRecord::TestCase
1147
1092
  posts = Post.all
1148
1093
 
1149
1094
  assert_queries(1) { assert_equal 11, posts.size }
1150
- assert ! posts.loaded?
1095
+ assert_not_predicate posts, :loaded?
1151
1096
 
1152
- best_posts = posts.where(:comments_count => 0)
1153
- best_posts.to_a # force load
1154
- assert_no_queries { assert_equal 9, best_posts.size }
1097
+ best_posts = posts.where(comments_count: 0)
1098
+ best_posts.load # force load
1099
+ assert_no_queries { assert_equal 6, best_posts.size }
1155
1100
  end
1156
1101
 
1157
1102
  def test_size_with_limit
1158
1103
  posts = Post.limit(10)
1159
1104
 
1160
1105
  assert_queries(1) { assert_equal 10, posts.size }
1161
- assert ! posts.loaded?
1106
+ assert_not_predicate posts, :loaded?
1162
1107
 
1163
- best_posts = posts.where(:comments_count => 0)
1164
- best_posts.to_a # force load
1165
- assert_no_queries { assert_equal 9, best_posts.size }
1108
+ best_posts = posts.where(comments_count: 0)
1109
+ best_posts.load # force load
1110
+ assert_no_queries { assert_equal 6, best_posts.size }
1166
1111
  end
1167
1112
 
1168
1113
  def test_size_with_zero_limit
1169
1114
  posts = Post.limit(0)
1170
1115
 
1171
1116
  assert_no_queries { assert_equal 0, posts.size }
1172
- assert ! posts.loaded?
1117
+ assert_not_predicate posts, :loaded?
1173
1118
 
1174
- posts.to_a # force load
1119
+ posts.load # force load
1175
1120
  assert_no_queries { assert_equal 0, posts.size }
1176
1121
  end
1177
1122
 
@@ -1179,13 +1124,13 @@ class RelationTest < ActiveRecord::TestCase
1179
1124
  posts = Post.limit(0)
1180
1125
 
1181
1126
  assert_no_queries { assert_equal true, posts.empty? }
1182
- assert ! posts.loaded?
1127
+ assert_not_predicate posts, :loaded?
1183
1128
  end
1184
1129
 
1185
1130
  def test_count_complex_chained_relations
1186
- posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
1131
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("legacy_comments_count > 0")
1187
1132
 
1188
- expected = { 1 => 2 }
1133
+ expected = { 1 => 4, 2 => 1 }
1189
1134
  assert_equal expected, posts.count
1190
1135
  end
1191
1136
 
@@ -1193,48 +1138,40 @@ class RelationTest < ActiveRecord::TestCase
1193
1138
  posts = Post.all
1194
1139
 
1195
1140
  assert_queries(1) { assert_equal false, posts.empty? }
1196
- assert ! posts.loaded?
1141
+ assert_not_predicate posts, :loaded?
1197
1142
 
1198
- no_posts = posts.where(:title => "")
1143
+ no_posts = posts.where(title: "")
1199
1144
  assert_queries(1) { assert_equal true, no_posts.empty? }
1200
- assert ! no_posts.loaded?
1145
+ assert_not_predicate no_posts, :loaded?
1201
1146
 
1202
- best_posts = posts.where(:comments_count => 0)
1203
- best_posts.to_a # force load
1147
+ best_posts = posts.where(comments_count: 0)
1148
+ best_posts.load # force load
1204
1149
  assert_no_queries { assert_equal false, best_posts.empty? }
1205
1150
  end
1206
1151
 
1207
1152
  def test_empty_complex_chained_relations
1208
- posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
1153
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("legacy_comments_count > 0")
1209
1154
 
1210
1155
  assert_queries(1) { assert_equal false, posts.empty? }
1211
- assert ! posts.loaded?
1156
+ assert_not_predicate posts, :loaded?
1212
1157
 
1213
- no_posts = posts.where(:title => "")
1158
+ no_posts = posts.where(title: "")
1214
1159
  assert_queries(1) { assert_equal true, no_posts.empty? }
1215
- assert ! no_posts.loaded?
1160
+ assert_not_predicate no_posts, :loaded?
1216
1161
  end
1217
1162
 
1218
1163
  def test_any
1219
1164
  posts = Post.all
1220
1165
 
1221
- # This test was failing when run on its own (as opposed to running the entire suite).
1222
- # The second line in the assert_queries block was causing visit_Arel_Attributes_Attribute
1223
- # in Arel::Visitors::ToSql to trigger a SHOW TABLES query. Running that line here causes
1224
- # the SHOW TABLES result to be cached so we don't have to do it again in the block.
1225
- #
1226
- # This is obviously a rubbish fix but it's the best I can come up with for now...
1227
- posts.where(:id => nil).any?
1228
-
1229
1166
  assert_queries(3) do
1230
1167
  assert posts.any? # Uses COUNT()
1231
- assert ! posts.where(:id => nil).any?
1168
+ assert_not_predicate posts.where(id: nil), :any?
1232
1169
 
1233
- assert posts.any? {|p| p.id > 0 }
1234
- assert ! posts.any? {|p| p.id <= 0 }
1170
+ assert posts.any? { |p| p.id > 0 }
1171
+ assert_not posts.any? { |p| p.id <= 0 }
1235
1172
  end
1236
1173
 
1237
- assert posts.loaded?
1174
+ assert_predicate posts, :loaded?
1238
1175
  end
1239
1176
 
1240
1177
  def test_many
@@ -1242,50 +1179,50 @@ class RelationTest < ActiveRecord::TestCase
1242
1179
 
1243
1180
  assert_queries(2) do
1244
1181
  assert posts.many? # Uses COUNT()
1245
- assert posts.many? {|p| p.id > 0 }
1246
- assert ! posts.many? {|p| p.id < 2 }
1182
+ assert posts.many? { |p| p.id > 0 }
1183
+ assert_not posts.many? { |p| p.id < 2 }
1247
1184
  end
1248
1185
 
1249
- assert posts.loaded?
1186
+ assert_predicate posts, :loaded?
1250
1187
  end
1251
1188
 
1252
1189
  def test_many_with_limits
1253
1190
  posts = Post.all
1254
1191
 
1255
- assert posts.many?
1256
- assert ! posts.limit(1).many?
1192
+ assert_predicate posts, :many?
1193
+ assert_not_predicate posts.limit(1), :many?
1257
1194
  end
1258
1195
 
1259
1196
  def test_none?
1260
1197
  posts = Post.all
1261
1198
  assert_queries(1) do
1262
- assert ! posts.none? # Uses COUNT()
1199
+ assert_not posts.none? # Uses COUNT()
1263
1200
  end
1264
1201
 
1265
- assert ! posts.loaded?
1202
+ assert_not_predicate posts, :loaded?
1266
1203
 
1267
1204
  assert_queries(1) do
1268
- assert posts.none? {|p| p.id < 0 }
1269
- assert ! posts.none? {|p| p.id == 1 }
1205
+ assert posts.none? { |p| p.id < 0 }
1206
+ assert_not posts.none? { |p| p.id == 1 }
1270
1207
  end
1271
1208
 
1272
- assert posts.loaded?
1209
+ assert_predicate posts, :loaded?
1273
1210
  end
1274
1211
 
1275
1212
  def test_one
1276
1213
  posts = Post.all
1277
1214
  assert_queries(1) do
1278
- assert ! posts.one? # Uses COUNT()
1215
+ assert_not posts.one? # Uses COUNT()
1279
1216
  end
1280
1217
 
1281
- assert ! posts.loaded?
1218
+ assert_not_predicate posts, :loaded?
1282
1219
 
1283
1220
  assert_queries(1) do
1284
- assert ! posts.one? {|p| p.id < 3 }
1285
- assert posts.one? {|p| p.id == 1 }
1221
+ assert_not posts.one? { |p| p.id < 3 }
1222
+ assert posts.one? { |p| p.id == 1 }
1286
1223
  end
1287
1224
 
1288
- assert posts.loaded?
1225
+ assert_predicate posts, :loaded?
1289
1226
  end
1290
1227
 
1291
1228
  def test_to_a_should_dup_target
@@ -1306,11 +1243,11 @@ class RelationTest < ActiveRecord::TestCase
1306
1243
  end
1307
1244
 
1308
1245
  def test_scoped_build
1309
- posts = Post.where(:title => 'You told a lie')
1246
+ posts = Post.where(title: "You told a lie")
1310
1247
 
1311
1248
  post = posts.new
1312
1249
  assert_kind_of Post, post
1313
- assert_equal 'You told a lie', post.title
1250
+ assert_equal "You told a lie", post.title
1314
1251
  end
1315
1252
 
1316
1253
  def test_create
@@ -1318,11 +1255,11 @@ class RelationTest < ActiveRecord::TestCase
1318
1255
 
1319
1256
  sparrow = birds.create
1320
1257
  assert_kind_of Bird, sparrow
1321
- assert !sparrow.persisted?
1258
+ assert_not_predicate sparrow, :persisted?
1322
1259
 
1323
- hen = birds.where(:name => 'hen').create
1324
- assert hen.persisted?
1325
- assert_equal 'hen', hen.name
1260
+ hen = birds.where(name: "hen").create
1261
+ assert_predicate hen, :persisted?
1262
+ assert_equal "hen", hen.name
1326
1263
  end
1327
1264
 
1328
1265
  def test_create_bang
@@ -1330,201 +1267,317 @@ class RelationTest < ActiveRecord::TestCase
1330
1267
 
1331
1268
  assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
1332
1269
 
1333
- hen = birds.where(:name => 'hen').create!
1270
+ hen = birds.where(name: "hen").create!
1334
1271
  assert_kind_of Bird, hen
1335
- assert hen.persisted?
1336
- assert_equal 'hen', hen.name
1272
+ assert_predicate hen, :persisted?
1273
+ assert_equal "hen", hen.name
1274
+ end
1275
+
1276
+ def test_create_with_polymorphic_association
1277
+ author = authors(:david)
1278
+ post = posts(:welcome)
1279
+ comment = Comment.where(post: post, author: author).create!(body: "hello")
1280
+
1281
+ assert_equal author, comment.author
1282
+ assert_equal post, comment.post
1337
1283
  end
1338
1284
 
1339
1285
  def test_first_or_create
1340
- parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
1286
+ parrot = Bird.where(color: "green").first_or_create(name: "parrot")
1341
1287
  assert_kind_of Bird, parrot
1342
- assert parrot.persisted?
1343
- assert_equal 'parrot', parrot.name
1344
- assert_equal 'green', parrot.color
1288
+ assert_predicate parrot, :persisted?
1289
+ assert_equal "parrot", parrot.name
1290
+ assert_equal "green", parrot.color
1345
1291
 
1346
- same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
1292
+ same_parrot = Bird.where(color: "green").first_or_create(name: "parakeet")
1347
1293
  assert_kind_of Bird, same_parrot
1348
- assert same_parrot.persisted?
1294
+ assert_predicate same_parrot, :persisted?
1349
1295
  assert_equal parrot, same_parrot
1296
+
1297
+ canary = Bird.where(Bird.arel_table[:color].is_distinct_from("green")).first_or_create(name: "canary")
1298
+ assert_equal "canary", canary.name
1299
+ assert_nil canary.color
1350
1300
  end
1351
1301
 
1352
1302
  def test_first_or_create_with_no_parameters
1353
- parrot = Bird.where(:color => 'green').first_or_create
1303
+ parrot = Bird.where(color: "green").first_or_create
1354
1304
  assert_kind_of Bird, parrot
1355
- assert !parrot.persisted?
1356
- assert_equal 'green', parrot.color
1305
+ assert_not_predicate parrot, :persisted?
1306
+ assert_equal "green", parrot.color
1357
1307
  end
1358
1308
 
1359
1309
  def test_first_or_create_with_block
1360
- parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
1310
+ canary = Bird.create!(color: "yellow", name: "canary")
1311
+ parrot = Bird.where(color: "green").first_or_create do |bird|
1312
+ bird.name = "parrot"
1313
+ bird.enable_count = true
1314
+ assert_equal canary, Bird.find_by!(name: "canary")
1315
+ end
1316
+ assert_equal 1, parrot.total_count
1361
1317
  assert_kind_of Bird, parrot
1362
- assert parrot.persisted?
1363
- assert_equal 'green', parrot.color
1364
- assert_equal 'parrot', parrot.name
1318
+ assert_predicate parrot, :persisted?
1319
+ assert_equal "green", parrot.color
1320
+ assert_equal "parrot", parrot.name
1365
1321
 
1366
- same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
1322
+ same_parrot = Bird.where(color: "green").first_or_create { |bird| bird.name = "parakeet" }
1367
1323
  assert_equal parrot, same_parrot
1368
1324
  end
1369
1325
 
1370
1326
  def test_first_or_create_with_array
1371
- several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
1327
+ several_green_birds = Bird.where(color: "green").first_or_create([{ name: "parrot" }, { name: "parakeet" }])
1372
1328
  assert_kind_of Array, several_green_birds
1373
1329
  several_green_birds.each { |bird| assert bird.persisted? }
1374
1330
 
1375
- same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
1331
+ same_parrot = Bird.where(color: "green").first_or_create([{ name: "hummingbird" }, { name: "macaw" }])
1376
1332
  assert_kind_of Bird, same_parrot
1377
1333
  assert_equal several_green_birds.first, same_parrot
1378
1334
  end
1379
1335
 
1380
1336
  def test_first_or_create_bang_with_valid_options
1381
- parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
1337
+ parrot = Bird.where(color: "green").first_or_create!(name: "parrot")
1382
1338
  assert_kind_of Bird, parrot
1383
- assert parrot.persisted?
1384
- assert_equal 'parrot', parrot.name
1385
- assert_equal 'green', parrot.color
1339
+ assert_predicate parrot, :persisted?
1340
+ assert_equal "parrot", parrot.name
1341
+ assert_equal "green", parrot.color
1386
1342
 
1387
- same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
1343
+ same_parrot = Bird.where(color: "green").first_or_create!(name: "parakeet")
1388
1344
  assert_kind_of Bird, same_parrot
1389
- assert same_parrot.persisted?
1345
+ assert_predicate same_parrot, :persisted?
1390
1346
  assert_equal parrot, same_parrot
1391
1347
  end
1392
1348
 
1393
1349
  def test_first_or_create_bang_with_invalid_options
1394
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
1350
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!(pirate_id: 1) }
1395
1351
  end
1396
1352
 
1397
1353
  def test_first_or_create_bang_with_no_parameters
1398
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
1354
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create! }
1399
1355
  end
1400
1356
 
1401
1357
  def test_first_or_create_bang_with_valid_block
1402
- parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
1358
+ canary = Bird.create!(color: "yellow", name: "canary")
1359
+ parrot = Bird.where(color: "green").first_or_create! do |bird|
1360
+ bird.name = "parrot"
1361
+ bird.enable_count = true
1362
+ assert_equal canary, Bird.find_by!(name: "canary")
1363
+ end
1364
+ assert_equal 1, parrot.total_count
1403
1365
  assert_kind_of Bird, parrot
1404
- assert parrot.persisted?
1405
- assert_equal 'green', parrot.color
1406
- assert_equal 'parrot', parrot.name
1366
+ assert_predicate parrot, :persisted?
1367
+ assert_equal "green", parrot.color
1368
+ assert_equal "parrot", parrot.name
1407
1369
 
1408
- same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
1370
+ same_parrot = Bird.where(color: "green").first_or_create! { |bird| bird.name = "parakeet" }
1409
1371
  assert_equal parrot, same_parrot
1410
1372
  end
1411
1373
 
1412
1374
  def test_first_or_create_bang_with_invalid_block
1413
1375
  assert_raise(ActiveRecord::RecordInvalid) do
1414
- Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
1376
+ Bird.where(color: "green").first_or_create! { |bird| bird.pirate_id = 1 }
1415
1377
  end
1416
1378
  end
1417
1379
 
1418
- def test_first_or_create_with_valid_array
1419
- several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
1380
+ def test_first_or_create_bang_with_valid_array
1381
+ several_green_birds = Bird.where(color: "green").first_or_create!([{ name: "parrot" }, { name: "parakeet" }])
1420
1382
  assert_kind_of Array, several_green_birds
1421
1383
  several_green_birds.each { |bird| assert bird.persisted? }
1422
1384
 
1423
- same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
1385
+ same_parrot = Bird.where(color: "green").first_or_create!([{ name: "hummingbird" }, { name: "macaw" }])
1424
1386
  assert_kind_of Bird, same_parrot
1425
1387
  assert_equal several_green_birds.first, same_parrot
1426
1388
  end
1427
1389
 
1428
- def test_first_or_create_with_invalid_array
1429
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) }
1390
+ def test_first_or_create_bang_with_invalid_array
1391
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!([ { name: "parrot" }, { pirate_id: 1 } ]) }
1430
1392
  end
1431
1393
 
1432
1394
  def test_first_or_initialize
1433
- parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
1395
+ parrot = Bird.where(color: "green").first_or_initialize(name: "parrot")
1434
1396
  assert_kind_of Bird, parrot
1435
- assert !parrot.persisted?
1436
- assert parrot.valid?
1437
- assert parrot.new_record?
1438
- assert_equal 'parrot', parrot.name
1439
- assert_equal 'green', parrot.color
1397
+ assert_not_predicate parrot, :persisted?
1398
+ assert_predicate parrot, :valid?
1399
+ assert_predicate parrot, :new_record?
1400
+ assert_equal "parrot", parrot.name
1401
+ assert_equal "green", parrot.color
1402
+
1403
+ canary = Bird.where(Bird.arel_table[:color].is_distinct_from("green")).first_or_initialize(name: "canary")
1404
+ assert_equal "canary", canary.name
1405
+ assert_nil canary.color
1440
1406
  end
1441
1407
 
1442
1408
  def test_first_or_initialize_with_no_parameters
1443
- parrot = Bird.where(:color => 'green').first_or_initialize
1409
+ parrot = Bird.where(color: "green").first_or_initialize
1444
1410
  assert_kind_of Bird, parrot
1445
- assert !parrot.persisted?
1446
- assert !parrot.valid?
1447
- assert parrot.new_record?
1448
- assert_equal 'green', parrot.color
1411
+ assert_not_predicate parrot, :persisted?
1412
+ assert_not_predicate parrot, :valid?
1413
+ assert_predicate parrot, :new_record?
1414
+ assert_equal "green", parrot.color
1449
1415
  end
1450
1416
 
1451
1417
  def test_first_or_initialize_with_block
1452
- parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
1418
+ canary = Bird.create!(color: "yellow", name: "canary")
1419
+ parrot = Bird.where(color: "green").first_or_initialize do |bird|
1420
+ bird.name = "parrot"
1421
+ bird.enable_count = true
1422
+ assert_equal canary, Bird.find_by!(name: "canary")
1423
+ end
1424
+ assert_equal 1, parrot.total_count
1453
1425
  assert_kind_of Bird, parrot
1454
- assert !parrot.persisted?
1455
- assert parrot.valid?
1456
- assert parrot.new_record?
1457
- assert_equal 'green', parrot.color
1458
- assert_equal 'parrot', parrot.name
1426
+ assert_not_predicate parrot, :persisted?
1427
+ assert_predicate parrot, :valid?
1428
+ assert_predicate parrot, :new_record?
1429
+ assert_equal "green", parrot.color
1430
+ assert_equal "parrot", parrot.name
1459
1431
  end
1460
1432
 
1461
1433
  def test_find_or_create_by
1462
- assert_nil Bird.find_by(name: 'bob')
1434
+ assert_nil Bird.find_by(name: "bob")
1463
1435
 
1464
- bird = Bird.find_or_create_by(name: 'bob')
1465
- assert bird.persisted?
1436
+ bird = Bird.find_or_create_by(name: "bob")
1437
+ assert_predicate bird, :persisted?
1466
1438
 
1467
- assert_equal bird, Bird.find_or_create_by(name: 'bob')
1439
+ assert_equal bird, Bird.find_or_create_by(name: "bob")
1468
1440
  end
1469
1441
 
1470
1442
  def test_find_or_create_by_with_create_with
1471
- assert_nil Bird.find_by(name: 'bob')
1443
+ assert_nil Bird.find_by(name: "bob")
1472
1444
 
1473
- bird = Bird.create_with(color: 'green').find_or_create_by(name: 'bob')
1474
- assert bird.persisted?
1475
- assert_equal 'green', bird.color
1445
+ bird = Bird.create_with(color: "green").find_or_create_by(name: "bob")
1446
+ assert_predicate bird, :persisted?
1447
+ assert_equal "green", bird.color
1476
1448
 
1477
- assert_equal bird, Bird.create_with(color: 'blue').find_or_create_by(name: 'bob')
1449
+ assert_equal bird, Bird.create_with(color: "blue").find_or_create_by(name: "bob")
1478
1450
  end
1479
1451
 
1480
1452
  def test_find_or_create_by!
1481
- assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: 'green') }
1453
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: "green") }
1454
+ end
1455
+
1456
+ def test_create_or_find_by
1457
+ assert_nil Subscriber.find_by(nick: "bob")
1458
+
1459
+ subscriber = Subscriber.create!(nick: "bob")
1460
+
1461
+ assert_equal subscriber, Subscriber.create_or_find_by(nick: "bob")
1462
+ assert_not_equal subscriber, Subscriber.create_or_find_by(nick: "cat")
1463
+ end
1464
+
1465
+ def test_create_or_find_by_should_not_raise_due_to_validation_errors
1466
+ assert_nothing_raised do
1467
+ bird = Bird.create_or_find_by(color: "green")
1468
+ assert_predicate bird, :invalid?
1469
+ end
1470
+ end
1471
+
1472
+ def test_create_or_find_by_with_non_unique_attributes
1473
+ Subscriber.create!(nick: "bob", name: "the builder")
1474
+
1475
+ assert_raises(ActiveRecord::RecordNotFound) do
1476
+ Subscriber.create_or_find_by(nick: "bob", name: "the cat")
1477
+ end
1478
+ end
1479
+
1480
+ def test_create_or_find_by_within_transaction
1481
+ assert_nil Subscriber.find_by(nick: "bob")
1482
+
1483
+ subscriber = Subscriber.create!(nick: "bob")
1484
+
1485
+ Subscriber.transaction do
1486
+ assert_equal subscriber, Subscriber.create_or_find_by(nick: "bob")
1487
+ assert_not_equal subscriber, Subscriber.create_or_find_by(nick: "cat")
1488
+ end
1489
+ end
1490
+
1491
+ def test_create_or_find_by_with_bang
1492
+ assert_nil Subscriber.find_by(nick: "bob")
1493
+
1494
+ subscriber = Subscriber.create!(nick: "bob")
1495
+
1496
+ assert_equal subscriber, Subscriber.create_or_find_by!(nick: "bob")
1497
+ assert_not_equal subscriber, Subscriber.create_or_find_by!(nick: "cat")
1498
+ end
1499
+
1500
+ def test_create_or_find_by_with_bang_should_raise_due_to_validation_errors
1501
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.create_or_find_by!(color: "green") }
1502
+ end
1503
+
1504
+ def test_create_or_find_by_with_bang_with_non_unique_attributes
1505
+ Subscriber.create!(nick: "bob", name: "the builder")
1506
+
1507
+ assert_raises(ActiveRecord::RecordNotFound) do
1508
+ Subscriber.create_or_find_by!(nick: "bob", name: "the cat")
1509
+ end
1510
+ end
1511
+
1512
+ def test_create_or_find_by_with_bang_within_transaction
1513
+ assert_nil Subscriber.find_by(nick: "bob")
1514
+
1515
+ subscriber = Subscriber.create!(nick: "bob")
1516
+
1517
+ Subscriber.transaction do
1518
+ assert_equal subscriber, Subscriber.create_or_find_by!(nick: "bob")
1519
+ assert_not_equal subscriber, Subscriber.create_or_find_by!(nick: "cat")
1520
+ end
1482
1521
  end
1483
1522
 
1484
1523
  def test_find_or_initialize_by
1485
- assert_nil Bird.find_by(name: 'bob')
1524
+ assert_nil Bird.find_by(name: "bob")
1486
1525
 
1487
- bird = Bird.find_or_initialize_by(name: 'bob')
1488
- assert bird.new_record?
1526
+ bird = Bird.find_or_initialize_by(name: "bob")
1527
+ assert_predicate bird, :new_record?
1489
1528
  bird.save!
1490
1529
 
1491
- assert_equal bird, Bird.find_or_initialize_by(name: 'bob')
1530
+ assert_equal bird, Bird.find_or_initialize_by(name: "bob")
1492
1531
  end
1493
1532
 
1494
- def test_explicit_create_scope
1495
- hens = Bird.where(:name => 'hen')
1496
- assert_equal 'hen', hens.new.name
1533
+ def test_explicit_create_with
1534
+ hens = Bird.where(name: "hen")
1535
+ assert_equal "hen", hens.new.name
1497
1536
 
1498
- hens = hens.create_with(:name => 'cock')
1499
- assert_equal 'cock', hens.new.name
1537
+ hens = hens.create_with(name: "cock")
1538
+ assert_equal "cock", hens.new.name
1539
+ end
1540
+
1541
+ def test_create_with_nested_attributes
1542
+ assert_difference("Project.count", 1) do
1543
+ developers = Developer.where(name: "Aaron")
1544
+ developers = developers.create_with(
1545
+ projects_attributes: [{ name: "p1" }]
1546
+ )
1547
+ developers.create!
1548
+ end
1500
1549
  end
1501
1550
 
1502
1551
  def test_except
1503
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1552
+ relation = Post.where(author_id: 1).order("id ASC").limit(1)
1504
1553
  assert_equal [posts(:welcome)], relation.to_a
1505
1554
 
1506
1555
  author_posts = relation.except(:order, :limit)
1507
- assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1556
+ assert_equal Post.where(author_id: 1).sort_by(&:id), author_posts.sort_by(&:id)
1557
+ assert_equal author_posts.sort_by(&:id), relation.scoping { Post.except(:order, :limit).sort_by(&:id) }
1508
1558
 
1509
1559
  all_posts = relation.except(:where, :order, :limit)
1510
- assert_equal Post.all, all_posts
1560
+ assert_equal Post.all.sort_by(&:id), all_posts.sort_by(&:id)
1561
+ assert_equal all_posts.sort_by(&:id), relation.scoping { Post.except(:where, :order, :limit).sort_by(&:id) }
1511
1562
  end
1512
1563
 
1513
1564
  def test_only
1514
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1565
+ relation = Post.where(author_id: 1).order("id ASC").limit(1)
1515
1566
  assert_equal [posts(:welcome)], relation.to_a
1516
1567
 
1517
1568
  author_posts = relation.only(:where)
1518
- assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1569
+ assert_equal Post.where(author_id: 1).sort_by(&:id), author_posts.sort_by(&:id)
1570
+ assert_equal author_posts.sort_by(&:id), relation.scoping { Post.only(:where).sort_by(&:id) }
1519
1571
 
1520
- all_posts = relation.only(:limit)
1521
- assert_equal Post.limit(1).to_a.first, all_posts.first
1572
+ all_posts = relation.only(:order)
1573
+ assert_equal Post.order("id ASC").to_a, all_posts.to_a
1574
+ assert_equal all_posts.to_a, relation.scoping { Post.only(:order).to_a }
1522
1575
  end
1523
1576
 
1524
1577
  def test_anonymous_extension
1525
- relation = Post.where(:author_id => 1).order('id ASC').extending do
1578
+ relation = Post.where(author_id: 1).order("id ASC").extending do
1526
1579
  def author
1527
- 'lifo'
1580
+ "lifo"
1528
1581
  end
1529
1582
  end
1530
1583
 
@@ -1533,7 +1586,7 @@ class RelationTest < ActiveRecord::TestCase
1533
1586
  end
1534
1587
 
1535
1588
  def test_named_extension
1536
- relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
1589
+ relation = Post.where(author_id: 1).order("id ASC").extending(Post::NamedExtension)
1537
1590
  assert_equal "lifo", relation.author
1538
1591
  assert_equal "lifo", relation.limit(1).author
1539
1592
  end
@@ -1543,29 +1596,29 @@ class RelationTest < ActiveRecord::TestCase
1543
1596
  end
1544
1597
 
1545
1598
  def test_default_scope_order_with_scope_order
1546
- assert_equal 'zyke', CoolCar.order_using_new_style.limit(1).first.name
1547
- assert_equal 'zyke', FastCar.order_using_new_style.limit(1).first.name
1599
+ assert_equal "zyke", CoolCar.order_using_new_style.limit(1).first.name
1600
+ assert_equal "zyke", FastCar.order_using_new_style.limit(1).first.name
1548
1601
  end
1549
1602
 
1550
1603
  def test_order_using_scoping
1551
- car1 = CoolCar.order('id DESC').scoping do
1552
- CoolCar.all.merge!(order: 'id asc').first
1604
+ car1 = CoolCar.order("id DESC").scoping do
1605
+ CoolCar.all.merge!(order: "id asc").first
1553
1606
  end
1554
- assert_equal 'zyke', car1.name
1607
+ assert_equal "zyke", car1.name
1555
1608
 
1556
- car2 = FastCar.order('id DESC').scoping do
1557
- FastCar.all.merge!(order: 'id asc').first
1609
+ car2 = FastCar.order("id DESC").scoping do
1610
+ FastCar.all.merge!(order: "id asc").first
1558
1611
  end
1559
- assert_equal 'zyke', car2.name
1612
+ assert_equal "zyke", car2.name
1560
1613
  end
1561
1614
 
1562
1615
  def test_unscoped_block_style
1563
- assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name}
1564
- assert_equal 'honda', FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name}
1616
+ assert_equal "honda", CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name }
1617
+ assert_equal "honda", FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name }
1565
1618
  end
1566
1619
 
1567
1620
  def test_intersection_with_array
1568
- relation = Author.where(:name => "David")
1621
+ relation = Author.where(name: "David")
1569
1622
  rails_author = relation.first
1570
1623
 
1571
1624
  assert_equal [rails_author], [rails_author] & relation
@@ -1577,114 +1630,47 @@ class RelationTest < ActiveRecord::TestCase
1577
1630
  end
1578
1631
 
1579
1632
  def test_ordering_with_extra_spaces
1580
- assert_equal authors(:david), Author.order('id DESC , name DESC').last
1581
- end
1582
-
1583
- def test_update_all_with_blank_argument
1584
- assert_raises(ArgumentError) { Comment.update_all({}) }
1585
- end
1586
-
1587
- def test_update_all_with_joins
1588
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1589
- count = comments.count
1590
-
1591
- assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
1592
- assert_equal posts(:thinking), comments(:greetings).post
1593
- end
1594
-
1595
- def test_update_all_with_joins_and_limit
1596
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).limit(1)
1597
- assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1598
- end
1599
-
1600
- def test_update_all_with_joins_and_limit_and_order
1601
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('comments.id').limit(1)
1602
- assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1603
- assert_equal posts(:thinking), comments(:greetings).post
1604
- assert_equal posts(:welcome), comments(:more_greetings).post
1605
- end
1606
-
1607
- def test_update_all_with_joins_and_offset
1608
- all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1609
- count = all_comments.count
1610
- comments = all_comments.offset(1)
1611
-
1612
- assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1613
- end
1614
-
1615
- def test_update_all_with_joins_and_offset_and_order
1616
- all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id')
1617
- count = all_comments.count
1618
- comments = all_comments.offset(1)
1619
-
1620
- assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1621
- assert_equal posts(:thinking), comments(:more_greetings).post
1622
- assert_equal posts(:welcome), comments(:greetings).post
1623
- end
1624
-
1625
- def test_update_on_relation
1626
- topic1 = TopicWithCallbacks.create! title: 'arel', author_name: nil
1627
- topic2 = TopicWithCallbacks.create! title: 'activerecord', author_name: nil
1628
- topics = TopicWithCallbacks.where(id: [topic1.id, topic2.id])
1629
- topics.update(title: 'adequaterecord')
1630
-
1631
- assert_equal 'adequaterecord', topic1.reload.title
1632
- assert_equal 'adequaterecord', topic2.reload.title
1633
- # Testing that the before_update callbacks have run
1634
- assert_equal 'David', topic1.reload.author_name
1635
- assert_equal 'David', topic2.reload.author_name
1636
- end
1637
-
1638
- def test_update_on_relation_passing_active_record_object_is_deprecated
1639
- topic = Topic.create!(title: 'Foo', author_name: nil)
1640
- assert_deprecated(/update/) do
1641
- Topic.where(id: topic.id).update(topic, title: 'Bar')
1642
- end
1633
+ assert_equal authors(:david), Author.order("id DESC , name DESC").last
1643
1634
  end
1644
1635
 
1645
1636
  def test_distinct
1646
- tag1 = Tag.create(:name => 'Foo')
1647
- tag2 = Tag.create(:name => 'Foo')
1637
+ tag1 = Tag.create(name: "Foo")
1638
+ tag2 = Tag.create(name: "Foo")
1648
1639
 
1649
- query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
1640
+ query = Tag.select(:name).where(id: [tag1.id, tag2.id])
1650
1641
 
1651
- assert_equal ['Foo', 'Foo'], query.map(&:name)
1642
+ assert_equal ["Foo", "Foo"], query.map(&:name)
1652
1643
  assert_sql(/DISTINCT/) do
1653
- assert_equal ['Foo'], query.distinct.map(&:name)
1654
- assert_deprecated { assert_equal ['Foo'], query.uniq.map(&:name) }
1644
+ assert_equal ["Foo"], query.distinct.map(&:name)
1655
1645
  end
1656
1646
  assert_sql(/DISTINCT/) do
1657
- assert_equal ['Foo'], query.distinct(true).map(&:name)
1658
- assert_deprecated { assert_equal ['Foo'], query.uniq(true).map(&:name) }
1659
- end
1660
- assert_equal ['Foo', 'Foo'], query.distinct(true).distinct(false).map(&:name)
1661
-
1662
- assert_deprecated do
1663
- assert_equal ['Foo', 'Foo'], query.uniq(true).uniq(false).map(&:name)
1647
+ assert_equal ["Foo"], query.distinct(true).map(&:name)
1664
1648
  end
1649
+ assert_equal ["Foo", "Foo"], query.distinct(true).distinct(false).map(&:name)
1665
1650
  end
1666
1651
 
1667
1652
  def test_doesnt_add_having_values_if_options_are_blank
1668
- scope = Post.having('')
1669
- assert scope.having_clause.empty?
1653
+ scope = Post.having("")
1654
+ assert_empty scope.having_clause
1670
1655
 
1671
1656
  scope = Post.having([])
1672
- assert scope.having_clause.empty?
1657
+ assert_empty scope.having_clause
1673
1658
  end
1674
1659
 
1675
1660
  def test_having_with_binds_for_both_where_and_having
1676
1661
  post = Post.first
1677
- having_then_where = Post.having(id: post.id).where(title: post.title).group(:id)
1678
- where_then_having = Post.where(title: post.title).having(id: post.id).group(:id)
1662
+ having_then_where = Post.having(id: post.id).where(title: post.title).group(:id, :author_id, :title, :body, :type, :legacy_comments_count, :taggings_with_delete_all_count, :taggings_with_destroy_count, :tags_count, :indestructible_tags_count, :tags_with_destroy_count, :tags_with_nullify_count)
1663
+ where_then_having = Post.where(title: post.title).having(id: post.id).group(:id, :author_id, :title, :body, :type, :legacy_comments_count, :taggings_with_delete_all_count, :taggings_with_destroy_count, :tags_count, :indestructible_tags_count, :tags_with_destroy_count, :tags_with_nullify_count)
1679
1664
 
1680
1665
  assert_equal [post], having_then_where
1681
1666
  assert_equal [post], where_then_having
1682
1667
  end
1683
1668
 
1684
1669
  def test_multiple_where_and_having_clauses
1670
+ puts "test_multiple_where_and_having_clauses"
1685
1671
  post = Post.first
1686
1672
  having_then_where = Post.having(id: post.id).where(title: post.title)
1687
- .having(id: post.id).where(title: post.title).group(:id)
1673
+ .having(id: post.id).where(title: post.title).group(:id, :author_id, :title, :body, :type, :legacy_comments_count, :taggings_with_delete_all_count, :taggings_with_destroy_count, :tags_count, :indestructible_tags_count, :tags_with_destroy_count, :tags_with_nullify_count)
1688
1674
 
1689
1675
  assert_equal [post], having_then_where
1690
1676
  end
@@ -1695,72 +1681,86 @@ class RelationTest < ActiveRecord::TestCase
1695
1681
 
1696
1682
  def test_references_triggers_eager_loading
1697
1683
  scope = Post.includes(:comments)
1698
- assert !scope.eager_loading?
1699
- assert scope.references(:comments).eager_loading?
1684
+ assert_not_predicate scope, :eager_loading?
1685
+ assert_predicate scope.references(:comments), :eager_loading?
1700
1686
  end
1701
1687
 
1702
1688
  def test_references_doesnt_trigger_eager_loading_if_reference_not_included
1703
1689
  scope = Post.references(:comments)
1704
- assert !scope.eager_loading?
1690
+ assert_not_predicate scope, :eager_loading?
1705
1691
  end
1706
1692
 
1707
1693
  def test_automatically_added_where_references
1708
- scope = Post.where(:comments => { :body => "Bla" })
1709
- assert_equal ['comments'], scope.references_values
1694
+ scope = Post.where(comments: { body: "Bla" })
1695
+ assert_equal ["comments"], scope.references_values
1710
1696
 
1711
- scope = Post.where('comments.body' => 'Bla')
1712
- assert_equal ['comments'], scope.references_values
1697
+ scope = Post.where("comments.body" => "Bla")
1698
+ assert_equal ["comments"], scope.references_values
1713
1699
  end
1714
1700
 
1715
1701
  def test_automatically_added_where_not_references
1716
1702
  scope = Post.where.not(comments: { body: "Bla" })
1717
- assert_equal ['comments'], scope.references_values
1703
+ assert_equal ["comments"], scope.references_values
1718
1704
 
1719
- scope = Post.where.not('comments.body' => 'Bla')
1720
- assert_equal ['comments'], scope.references_values
1705
+ scope = Post.where.not("comments.body" => "Bla")
1706
+ assert_equal ["comments"], scope.references_values
1721
1707
  end
1722
1708
 
1723
1709
  def test_automatically_added_having_references
1724
- scope = Post.having(:comments => { :body => "Bla" })
1725
- assert_equal ['comments'], scope.references_values
1710
+ scope = Post.having(comments: { body: "Bla" })
1711
+ assert_equal ["comments"], scope.references_values
1726
1712
 
1727
- scope = Post.having('comments.body' => 'Bla')
1728
- assert_equal ['comments'], scope.references_values
1713
+ scope = Post.having("comments.body" => "Bla")
1714
+ assert_equal ["comments"], scope.references_values
1729
1715
  end
1730
1716
 
1731
1717
  def test_automatically_added_order_references
1732
- scope = Post.order('comments.body')
1733
- assert_equal ['comments'], scope.references_values
1718
+ scope = Post.order("comments.body")
1719
+ assert_equal ["comments"], scope.references_values
1734
1720
 
1735
- scope = Post.order('comments.body', 'yaks.body')
1736
- assert_equal ['comments', 'yaks'], scope.references_values
1721
+ scope = Post.order("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}")
1722
+ if current_adapter?(:OracleAdapter)
1723
+ assert_equal ["COMMENTS"], scope.references_values
1724
+ else
1725
+ assert_equal ["comments"], scope.references_values
1726
+ end
1727
+
1728
+ scope = Post.order("comments.body", "yaks.body")
1729
+ assert_equal ["comments", "yaks"], scope.references_values
1737
1730
 
1738
1731
  # Don't infer yaks, let's not go down that road again...
1739
- scope = Post.order('comments.body, yaks.body')
1740
- assert_equal ['comments'], scope.references_values
1732
+ scope = Post.order("comments.body, yaks.body")
1733
+ assert_equal ["comments"], scope.references_values
1741
1734
 
1742
- scope = Post.order('comments.body asc')
1743
- assert_equal ['comments'], scope.references_values
1735
+ scope = Post.order("comments.body asc")
1736
+ assert_equal ["comments"], scope.references_values
1744
1737
 
1745
- scope = Post.order('foo(comments.body)')
1738
+ scope = Post.order("foo(comments.body)")
1746
1739
  assert_equal [], scope.references_values
1747
1740
  end
1748
1741
 
1749
1742
  def test_automatically_added_reorder_references
1750
- scope = Post.reorder('comments.body')
1743
+ scope = Post.reorder("comments.body")
1751
1744
  assert_equal %w(comments), scope.references_values
1752
1745
 
1753
- scope = Post.reorder('comments.body', 'yaks.body')
1746
+ scope = Post.reorder("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}")
1747
+ if current_adapter?(:OracleAdapter)
1748
+ assert_equal ["COMMENTS"], scope.references_values
1749
+ else
1750
+ assert_equal ["comments"], scope.references_values
1751
+ end
1752
+
1753
+ scope = Post.reorder("comments.body", "yaks.body")
1754
1754
  assert_equal %w(comments yaks), scope.references_values
1755
1755
 
1756
1756
  # Don't infer yaks, let's not go down that road again...
1757
- scope = Post.reorder('comments.body, yaks.body')
1757
+ scope = Post.reorder("comments.body, yaks.body")
1758
1758
  assert_equal %w(comments), scope.references_values
1759
1759
 
1760
- scope = Post.reorder('comments.body asc')
1760
+ scope = Post.reorder("comments.body asc")
1761
1761
  assert_equal %w(comments), scope.references_values
1762
1762
 
1763
- scope = Post.reorder('foo(comments.body)')
1763
+ scope = Post.reorder("foo(comments.body)")
1764
1764
  assert_equal [], scope.references_values
1765
1765
  end
1766
1766
 
@@ -1776,6 +1776,27 @@ class RelationTest < ActiveRecord::TestCase
1776
1776
  assert_nil relation.order_values.first
1777
1777
  end
1778
1778
 
1779
+ def test_reorder_with_first
1780
+ sql_log = capture_sql do
1781
+ message = <<~MSG.squish
1782
+ `.reorder(nil)` with `.first` / `.first!` no longer
1783
+ takes non-deterministic result in Rails 7.0.
1784
+ To continue taking non-deterministic result, use `.take` / `.take!` instead.
1785
+ MSG
1786
+ assert_deprecated(message) do
1787
+ assert Post.order(:title).reorder(nil).first
1788
+ end
1789
+ end
1790
+ assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
1791
+ end
1792
+
1793
+ def test_reorder_with_take
1794
+ sql_log = capture_sql do
1795
+ assert Post.order(:title).reorder(nil).take
1796
+ end
1797
+ assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
1798
+ end
1799
+
1779
1800
  def test_presence
1780
1801
  topics = Topic.all
1781
1802
 
@@ -1785,7 +1806,7 @@ class RelationTest < ActiveRecord::TestCase
1785
1806
  # checking if there are topics is used before you actually display them,
1786
1807
  # thus it shouldn't invoke an extra count query.
1787
1808
  assert_no_queries { assert topics.present? }
1788
- assert_no_queries { assert !topics.blank? }
1809
+ assert_no_queries { assert_not topics.blank? }
1789
1810
 
1790
1811
  # shows count of topics and loops after loading the query should not trigger extra queries either.
1791
1812
  assert_no_queries { topics.size }
@@ -1795,7 +1816,25 @@ class RelationTest < ActiveRecord::TestCase
1795
1816
  # count always trigger the COUNT query.
1796
1817
  assert_queries(1) { topics.count }
1797
1818
 
1798
- assert topics.loaded?
1819
+ assert_predicate topics, :loaded?
1820
+ end
1821
+
1822
+ def test_delete_by
1823
+ david = authors(:david)
1824
+
1825
+ assert_difference("Post.count", -3) { david.posts.delete_by(body: "hello") }
1826
+
1827
+ deleted = Author.delete_by(id: david.id)
1828
+ assert_equal 1, deleted
1829
+ end
1830
+
1831
+ def test_destroy_by
1832
+ david = authors(:david)
1833
+
1834
+ assert_difference("Post.count", -3) { david.posts.destroy_by(body: "hello") }
1835
+
1836
+ destroyed = Author.destroy_by(id: david.id)
1837
+ assert_equal [david], destroyed
1799
1838
  end
1800
1839
 
1801
1840
  test "find_by with hash conditions returns the first matching record" do
@@ -1807,11 +1846,11 @@ class RelationTest < ActiveRecord::TestCase
1807
1846
  end
1808
1847
 
1809
1848
  test "find_by with multi-arg conditions returns the first matching record" do
1810
- assert_equal posts(:eager_other), Post.order(:id).find_by('author_id = ?', 2)
1849
+ assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = ?", 2)
1811
1850
  end
1812
1851
 
1813
1852
  test "find_by returns nil if the record is missing" do
1814
- assert_equal nil, Post.all.find_by("1 = 0")
1853
+ assert_nil Post.all.find_by("1 = 0")
1815
1854
  end
1816
1855
 
1817
1856
  test "find_by doesn't have implicit ordering" do
@@ -1831,7 +1870,7 @@ class RelationTest < ActiveRecord::TestCase
1831
1870
  end
1832
1871
 
1833
1872
  test "find_by! with multi-arg conditions returns the first matching record" do
1834
- assert_equal posts(:eager_other), Post.order(:id).find_by!('author_id = ?', 2)
1873
+ assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = ?", 2)
1835
1874
  end
1836
1875
 
1837
1876
  test "find_by! doesn't have implicit ordering" do
@@ -1853,7 +1892,7 @@ class RelationTest < ActiveRecord::TestCase
1853
1892
  relation.to_a
1854
1893
 
1855
1894
  assert_raises(ActiveRecord::ImmutableRelation) do
1856
- relation.where! 'foo'
1895
+ relation.where! "foo"
1857
1896
  end
1858
1897
  end
1859
1898
 
@@ -1871,7 +1910,7 @@ class RelationTest < ActiveRecord::TestCase
1871
1910
  relation.to_a
1872
1911
 
1873
1912
  assert_raises(ActiveRecord::ImmutableRelation) do
1874
- relation.merge! where: 'foo'
1913
+ relation.merge! where: "foo"
1875
1914
  end
1876
1915
  end
1877
1916
 
@@ -1886,7 +1925,7 @@ class RelationTest < ActiveRecord::TestCase
1886
1925
 
1887
1926
  test "relations with cached arel can't be mutated [internal API]" do
1888
1927
  relation = Post.all
1889
- relation.count
1928
+ relation.arel
1890
1929
 
1891
1930
  assert_raises(ActiveRecord::ImmutableRelation) { relation.limit!(5) }
1892
1931
  assert_raises(ActiveRecord::ImmutableRelation) { relation.where!("1 = 2") }
@@ -1902,6 +1941,18 @@ class RelationTest < ActiveRecord::TestCase
1902
1941
  assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
1903
1942
  end
1904
1943
 
1944
+ test "relations don't load all records in #inspect" do
1945
+ assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
1946
+ Post.all.inspect
1947
+ end
1948
+ end
1949
+
1950
+ test "loading query is annotated in #inspect" do
1951
+ assert_sql(%r(/\* loading for inspect \*/)) do
1952
+ Post.all.inspect
1953
+ end
1954
+ end
1955
+
1905
1956
  test "already-loaded relations don't perform a new query in #inspect" do
1906
1957
  relation = Post.limit(2)
1907
1958
  relation.to_a
@@ -1913,19 +1964,27 @@ class RelationTest < ActiveRecord::TestCase
1913
1964
  end
1914
1965
  end
1915
1966
 
1916
- test 'using a custom table affects the wheres' do
1917
- table_alias = Post.arel_table.alias('omg_posts')
1967
+ test "using a custom table affects the wheres" do
1968
+ post = posts(:welcome)
1969
+
1970
+ assert_equal post, custom_post_relation.where!(title: post.title).take
1971
+ end
1972
+
1973
+ test "using a custom table with joins affects the joins" do
1974
+ post = posts(:welcome)
1975
+
1976
+ assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).take
1977
+ end
1918
1978
 
1919
- table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias)
1920
- predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata)
1921
- relation = ActiveRecord::Relation.new(Post, table_alias, predicate_builder)
1922
- relation.where!(:foo => "bar")
1979
+ test "arel_table respects a custom table" do
1980
+ assert_equal [posts(:sti_comments)], custom_post_relation.ranked_by_comments.limit_by(1).to_a
1981
+ end
1923
1982
 
1924
- node = relation.arel.constraints.first.grep(Arel::Attributes::Attribute).first
1925
- assert_equal table_alias, node.relation
1983
+ test "alias_tracker respects a custom table" do
1984
+ assert_equal posts(:welcome), custom_post_relation("categories_posts").joins(:categories).first
1926
1985
  end
1927
1986
 
1928
- test '#load' do
1987
+ test "#load" do
1929
1988
  relation = Post.all
1930
1989
  assert_queries(1) do
1931
1990
  assert_equal relation, relation.load
@@ -1933,13 +1992,13 @@ class RelationTest < ActiveRecord::TestCase
1933
1992
  assert_no_queries { relation.to_a }
1934
1993
  end
1935
1994
 
1936
- test 'group with select and includes' do
1937
- authors_count = Post.select('author_id, COUNT(author_id) AS num_posts').
1938
- group('author_id').order('author_id').includes(:author).to_a
1995
+ test "group with select and includes" do
1996
+ authors_count = Post.select("author_id, COUNT(author_id) AS num_posts").
1997
+ group("author_id").order("author_id").includes(:author).to_a
1939
1998
 
1940
1999
  assert_no_queries do
1941
2000
  result = authors_count.map do |post|
1942
- [post.num_posts, post.author.try(:name)]
2001
+ [post.num_posts, post.author&.name]
1943
2002
  end
1944
2003
 
1945
2004
  expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
@@ -1953,74 +2012,240 @@ class RelationTest < ActiveRecord::TestCase
1953
2012
  assert_equal [1, 1, 1], posts.map(&:author_address_id)
1954
2013
  end
1955
2014
 
2015
+ test "joins with select custom attribute" do
2016
+ contract = Company.create!(name: "test").contracts.create!
2017
+ company = Company.joins(:contracts).select(:id, :metadata).find(contract.company_id)
2018
+ assert_equal contract.metadata, company.metadata
2019
+ end
2020
+
2021
+ test "joins with order by custom attribute" do
2022
+ companies = Company.create!([{ name: "test1" }, { name: "test2" }])
2023
+ companies.each { |company| company.contracts.create! }
2024
+ assert_equal companies, Company.joins(:contracts).order(:metadata, :count)
2025
+ assert_equal companies.reverse, Company.joins(:contracts).order(metadata: :desc, count: :desc)
2026
+ end
2027
+
1956
2028
  test "delegations do not leak to other classes" do
1957
2029
  Topic.all.by_lifo
1958
2030
  assert Topic.all.class.method_defined?(:by_lifo)
1959
- assert !Post.all.respond_to?(:by_lifo)
2031
+ assert_not_respond_to Post.all, :by_lifo
1960
2032
  end
1961
2033
 
1962
- def test_unscope_removes_binds
1963
- left = Post.where(id: Arel::Nodes::BindParam.new)
1964
- column = Post.columns_hash['id']
1965
- left.bind_values += [[column, 20]]
2034
+ def test_unscope_with_subquery
2035
+ p1 = Post.where(id: 1)
2036
+ p2 = Post.where(id: 2)
2037
+
2038
+ assert_not_equal p1, p2
2039
+
2040
+ comments = Comment.where(post: p1).unscope(where: :post_id).where(post: p2)
1966
2041
 
1967
- relation = left.unscope(where: :id)
1968
- assert_equal [], relation.bind_values
2042
+ assert_not_equal p1.first.comments, comments
2043
+ assert_equal p2.first.comments, comments
1969
2044
  end
1970
2045
 
1971
- def test_merging_removes_rhs_bind_parameters
1972
- left = Post.where(id: 20)
1973
- right = Post.where(id: [1,2,3,4])
2046
+ def test_unscope_with_merge
2047
+ p0 = Post.where(author_id: 0)
2048
+ p1 = Post.where(author_id: 1, comments_count: 1)
1974
2049
 
1975
- merged = left.merge(right)
1976
- assert_equal [], merged.bind_values
2050
+ assert_equal [posts(:authorless)], p0
2051
+ assert_equal [posts(:thinking)], p1
2052
+
2053
+ comments = Comment.merge(p0).unscope(where: :author_id).where(post: p1)
2054
+
2055
+ assert_not_equal p0.first.comments, comments
2056
+ assert_equal p1.first.comments, comments
1977
2057
  end
1978
2058
 
1979
- def test_merging_keeps_lhs_bind_parameters
1980
- binds = [ActiveRecord::Relation::QueryAttribute.new("id", 20, Post.type_for_attribute("id"))]
2059
+ def test_unscope_with_unknown_column
2060
+ comment = comments(:greetings)
2061
+ comment.update!(comments: 1)
2062
+
2063
+ comments = Comment.where(comments: 1).unscope(where: :unknown_column)
2064
+ assert_equal [comment], comments
2065
+
2066
+ comments = Comment.where(comments: 1).unscope(where: { comments: :unknown_column })
2067
+ assert_equal [comment], comments
2068
+ end
2069
+
2070
+ def test_unscope_specific_where_value
2071
+ posts = Post.where(title: "Welcome to the weblog", body: "Such a lovely day")
2072
+
2073
+ assert_equal 1, posts.count
2074
+ assert_equal 1, posts.unscope(where: :title).count
2075
+ assert_equal 1, posts.unscope(where: :body).count
2076
+ end
1981
2077
 
1982
- right = Post.where(id: 20)
1983
- left = Post.where(id: 10)
2078
+ def test_unscope_with_aliased_column
2079
+ posts = Post.where(author: authors(:mary), text: "hullo").order(:id)
2080
+ assert_equal [posts(:misc_by_mary)], posts
1984
2081
 
1985
- merged = left.merge(right)
1986
- assert_equal binds, merged.bound_attributes
2082
+ posts = posts.unscope(where: :"posts.text")
2083
+ assert_equal posts(:eager_other, :misc_by_mary, :other_by_mary), posts
1987
2084
  end
1988
2085
 
1989
- def test_merging_reorders_bind_params
1990
- post = Post.first
1991
- right = Post.where(id: post.id)
1992
- left = Post.where(title: post.title)
2086
+ def test_unscope_with_table_name_qualified_column
2087
+ comments = Comment.joins(:post).where("posts.id": posts(:thinking))
2088
+ assert_equal [comments(:does_it_hurt)], comments
2089
+
2090
+ comments = comments.where(id: comments(:greetings))
2091
+ assert_empty comments
2092
+
2093
+ comments = comments.unscope(where: :"posts.id")
2094
+ assert_equal [comments(:greetings)], comments
2095
+ end
2096
+
2097
+ def test_unscope_with_table_name_qualified_hash
2098
+ comments = Comment.joins(:post).where("posts.id": posts(:thinking))
2099
+ assert_equal [comments(:does_it_hurt)], comments
2100
+
2101
+ comments = comments.where(id: comments(:greetings))
2102
+ assert_empty comments
2103
+
2104
+ comments = comments.unscope(where: { posts: :id })
2105
+ assert_equal [comments(:greetings)], comments
2106
+ end
2107
+
2108
+ def test_unscope_with_arel_sql
2109
+ posts = Post.where(Arel.sql("'Welcome to the weblog'").eq(Post.arel_table[:title]))
2110
+
2111
+ assert_equal 1, posts.count
2112
+ assert_equal Post.count, posts.unscope(where: :title).count
2113
+
2114
+ posts = Post.where(Arel.sql("posts.title").eq("Welcome to the weblog"))
1993
2115
 
1994
- merged = left.merge(right)
1995
- assert_equal post, merged.first
2116
+ assert_equal 1, posts.count
2117
+ assert_equal 1, posts.unscope(where: :title).count
2118
+ end
2119
+
2120
+ def test_unscope_grouped_where
2121
+ posts = Post.where(
2122
+ title: ["Welcome to the weblog", "So I was thinking", nil]
2123
+ )
2124
+
2125
+ assert_equal 2, posts.count
2126
+ assert_equal Post.count, posts.unscope(where: :title).count
2127
+ end
2128
+
2129
+ def test_locked_should_not_build_arel
2130
+ posts = Post.locked
2131
+ assert_predicate posts, :locked?
2132
+ assert_nothing_raised { posts.lock!(false) }
1996
2133
  end
1997
2134
 
1998
2135
  def test_relation_join_method
1999
- assert_equal 'Thank you for the welcome,Thank you again for the welcome', Post.first.comments.join(",")
2136
+ assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.order(:id).join(",")
2000
2137
  end
2001
2138
 
2002
- def test_connection_adapters_can_reorder_binds
2003
- posts = Post.limit(1).offset(2)
2139
+ def test_relation_with_private_kernel_method
2140
+ accounts = Account.all
2141
+ assert_equal [accounts(:signals37)], accounts.open
2142
+ assert_equal [accounts(:signals37)], accounts.available
2143
+
2144
+ sub_accounts = SubAccount.all
2145
+ assert_equal [accounts(:signals37)], sub_accounts.open
2146
+ assert_equal [accounts(:signals37)], sub_accounts.available
2004
2147
 
2005
- stubbed_connection = Post.connection.dup
2006
- def stubbed_connection.combine_bind_parameters(**kwargs)
2007
- offset = kwargs[:offset]
2008
- kwargs[:offset] = kwargs[:limit]
2009
- kwargs[:limit] = offset
2010
- super(**kwargs)
2148
+ assert_equal [topics(:second)], topics(:first).open_replies
2149
+ end
2150
+
2151
+ def test_where_with_take_memoization
2152
+ 5.times do |idx|
2153
+ Post.create!(title: idx.to_s, body: idx.to_s)
2011
2154
  end
2012
2155
 
2013
- posts.define_singleton_method(:connection) do
2014
- stubbed_connection
2156
+ posts = Post.all
2157
+ first_post = posts.take
2158
+ third_post = posts.where(title: "3").take
2159
+
2160
+ assert_equal "3", third_post.title
2161
+ assert_not_same first_post, third_post
2162
+ end
2163
+
2164
+ def test_find_by_with_take_memoization
2165
+ 5.times do |idx|
2166
+ Post.create!(title: idx.to_s, body: idx.to_s)
2015
2167
  end
2016
2168
 
2017
- assert_equal 2, posts.to_a.length
2169
+ posts = Post.all
2170
+ first_post = posts.take
2171
+ third_post = posts.find_by(title: "3")
2172
+
2173
+ assert_equal "3", third_post.title
2174
+ assert_not_same first_post, third_post
2018
2175
  end
2019
2176
 
2020
- def test_update_all_can_receive_active_record_objects
2021
- assert_deprecated do
2022
- Comment.update_all(post_id: Post.first)
2023
- assert(Comment.all.all? { |c| c.post_id == Post.first.id })
2177
+ test "#skip_query_cache!" do
2178
+ Post.cache do
2179
+ assert_queries(1) do
2180
+ Post.all.load
2181
+ Post.all.load
2182
+ end
2183
+
2184
+ assert_queries(2) do
2185
+ Post.all.skip_query_cache!.load
2186
+ Post.all.skip_query_cache!.load
2187
+ end
2024
2188
  end
2025
2189
  end
2190
+
2191
+ test "#skip_query_cache! with an eager load" do
2192
+ Post.cache do
2193
+ assert_queries(1) do
2194
+ Post.eager_load(:comments).load
2195
+ Post.eager_load(:comments).load
2196
+ end
2197
+
2198
+ assert_queries(2) do
2199
+ Post.eager_load(:comments).skip_query_cache!.load
2200
+ Post.eager_load(:comments).skip_query_cache!.load
2201
+ end
2202
+ end
2203
+ end
2204
+
2205
+ test "#skip_query_cache! with a preload" do
2206
+ Post.cache do
2207
+ assert_queries(2) do
2208
+ Post.preload(:comments).load
2209
+ Post.preload(:comments).load
2210
+ end
2211
+
2212
+ assert_queries(4) do
2213
+ Post.preload(:comments).skip_query_cache!.load
2214
+ Post.preload(:comments).skip_query_cache!.load
2215
+ end
2216
+ end
2217
+ end
2218
+
2219
+ test "#where with set" do
2220
+ david = authors(:david)
2221
+ mary = authors(:mary)
2222
+
2223
+ authors = Author.where(name: ["David", "Mary"].to_set)
2224
+ assert_equal [david, mary], authors.order(:id)
2225
+ end
2226
+
2227
+ test "#where with empty set" do
2228
+ authors = Author.where(name: Set.new)
2229
+ assert_empty authors
2230
+ end
2231
+
2232
+ (ActiveRecord::Relation::MULTI_VALUE_METHODS - [:extending]).each do |method|
2233
+ test "#{method} with blank value" do
2234
+ authors = Author.public_send(method, [""])
2235
+ assert_empty authors.public_send(:"#{method}_values")
2236
+ end
2237
+ end
2238
+
2239
+ private
2240
+ def custom_post_relation(alias_name = "omg_posts")
2241
+ table_alias = Post.arel_table.alias(alias_name)
2242
+ table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias)
2243
+ predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata)
2244
+
2245
+ ActiveRecord::Relation.create(
2246
+ Post,
2247
+ table: table_alias,
2248
+ predicate_builder: predicate_builder
2249
+ )
2250
+ end
2026
2251
  end