ibm_db 5.2.0-x86-mingw32 → 5.4.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (625) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/README +1 -1
  5. data/debug.log +1 -0
  6. data/ext/Makefile +28 -24
  7. data/ext/ibm_db.c +66 -65
  8. data/ext/ibm_db.o +0 -0
  9. data/ext/ibm_db.so +0 -0
  10. data/ext/mkmf.log +26 -24
  11. data/ext/ruby_ibm_db_cli.c +1 -0
  12. data/ext/ruby_ibm_db_cli.o +0 -0
  13. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1520 -1282
  14. data/lib/ibm_db.so +1 -0
  15. data/lib/mswin32/ibm_db.rb +3 -1
  16. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  17. data/lib/mswin32/rb3x/i386/ruby31/ibm_db.so +0 -0
  18. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  19. data/test/activejob/destroy_association_async_test.rb +305 -0
  20. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  21. data/test/activejob/helper.rb +15 -0
  22. data/test/assets/schema_dump_5_1.yml +345 -0
  23. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  24. data/test/cases/adapter_test.rb +432 -218
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  26. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  28. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  31. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  32. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  33. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  34. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  35. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  36. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  37. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  38. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  39. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  40. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  41. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  42. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  43. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  44. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  45. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  46. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  47. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  48. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  49. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  50. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  51. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  52. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  53. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  54. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  55. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  56. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  57. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  58. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  59. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  60. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  61. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  62. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  63. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  64. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  65. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  66. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  67. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  68. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  69. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  70. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  71. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  72. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  73. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  74. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  75. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  76. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  77. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  78. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  79. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  80. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  81. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  82. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  83. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  84. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  85. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  86. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  87. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  88. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  89. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  90. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  91. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  92. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  93. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  94. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  95. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  96. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  97. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  98. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  99. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  100. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  101. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  102. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  103. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  104. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  105. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  106. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  107. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  108. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  109. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  110. data/test/cases/aggregations_test.rb +14 -12
  111. data/test/cases/annotate_test.rb +46 -0
  112. data/test/cases/ar_schema_test.rb +153 -86
  113. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  114. data/test/cases/arel/attributes/math_test.rb +83 -0
  115. data/test/cases/arel/attributes_test.rb +27 -0
  116. data/test/cases/arel/collectors/bind_test.rb +40 -0
  117. data/test/cases/arel/collectors/composite_test.rb +47 -0
  118. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  119. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  120. data/test/cases/arel/crud_test.rb +65 -0
  121. data/test/cases/arel/delete_manager_test.rb +53 -0
  122. data/test/cases/arel/factory_methods_test.rb +46 -0
  123. data/test/cases/arel/helper.rb +45 -0
  124. data/test/cases/arel/insert_manager_test.rb +241 -0
  125. data/test/cases/arel/nodes/and_test.rb +30 -0
  126. data/test/cases/arel/nodes/as_test.rb +36 -0
  127. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  128. data/test/cases/arel/nodes/bin_test.rb +35 -0
  129. data/test/cases/arel/nodes/binary_test.rb +29 -0
  130. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  131. data/test/cases/arel/nodes/case_test.rb +96 -0
  132. data/test/cases/arel/nodes/casted_test.rb +18 -0
  133. data/test/cases/arel/nodes/comment_test.rb +22 -0
  134. data/test/cases/arel/nodes/count_test.rb +35 -0
  135. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  136. data/test/cases/arel/nodes/descending_test.rb +46 -0
  137. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  138. data/test/cases/arel/nodes/equality_test.rb +62 -0
  139. data/test/cases/arel/nodes/extract_test.rb +43 -0
  140. data/test/cases/arel/nodes/false_test.rb +21 -0
  141. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  142. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  143. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  144. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  145. data/test/cases/arel/nodes/node_test.rb +22 -0
  146. data/test/cases/arel/nodes/not_test.rb +31 -0
  147. data/test/cases/arel/nodes/or_test.rb +36 -0
  148. data/test/cases/arel/nodes/over_test.rb +69 -0
  149. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  150. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  151. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  152. data/test/cases/arel/nodes/sum_test.rb +35 -0
  153. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  154. data/test/cases/arel/nodes/true_test.rb +21 -0
  155. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  156. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  157. data/test/cases/arel/nodes/window_test.rb +81 -0
  158. data/test/cases/arel/nodes_test.rb +34 -0
  159. data/test/cases/arel/select_manager_test.rb +1238 -0
  160. data/test/cases/arel/support/fake_record.rb +135 -0
  161. data/test/cases/arel/table_test.rb +216 -0
  162. data/test/cases/arel/update_manager_test.rb +126 -0
  163. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  164. data/test/cases/arel/visitors/dot_test.rb +90 -0
  165. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  166. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  167. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  168. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  169. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  170. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  171. data/test/cases/associations/callbacks_test.rb +56 -38
  172. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  173. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  174. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  175. data/test/cases/associations/eager_singularization_test.rb +21 -21
  176. data/test/cases/associations/eager_test.rb +559 -415
  177. data/test/cases/associations/extension_test.rb +18 -12
  178. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  179. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  180. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  181. data/test/cases/associations/has_one_associations_test.rb +294 -129
  182. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  183. data/test/cases/associations/inner_join_association_test.rb +114 -38
  184. data/test/cases/associations/inverse_associations_test.rb +606 -398
  185. data/test/cases/associations/join_model_test.rb +158 -148
  186. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  187. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  188. data/test/cases/associations/required_test.rb +35 -10
  189. data/test/cases/associations_test.rb +241 -110
  190. data/test/cases/attribute_methods/read_test.rb +11 -11
  191. data/test/cases/attribute_methods_test.rb +413 -298
  192. data/test/cases/attributes_test.rb +145 -27
  193. data/test/cases/autosave_association_test.rb +681 -436
  194. data/test/cases/base_prevent_writes_test.rb +229 -0
  195. data/test/cases/base_test.rb +599 -542
  196. data/test/cases/batches_test.rb +288 -82
  197. data/test/cases/binary_test.rb +26 -31
  198. data/test/cases/bind_parameter_test.rb +194 -21
  199. data/test/cases/boolean_test.rb +52 -0
  200. data/test/cases/cache_key_test.rb +110 -5
  201. data/test/cases/calculations_test.rb +740 -177
  202. data/test/cases/callbacks_test.rb +74 -207
  203. data/test/cases/clone_test.rb +15 -10
  204. data/test/cases/coders/json_test.rb +2 -0
  205. data/test/cases/coders/yaml_column_test.rb +16 -13
  206. data/test/cases/collection_cache_key_test.rb +177 -20
  207. data/test/cases/column_alias_test.rb +9 -7
  208. data/test/cases/column_definition_test.rb +10 -68
  209. data/test/cases/comment_test.rb +166 -107
  210. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  211. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  212. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  213. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  214. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  215. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  216. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  217. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  218. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  219. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  220. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  221. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  222. data/test/cases/connection_management_test.rb +13 -11
  223. data/test/cases/connection_pool_test.rb +316 -83
  224. data/test/cases/core_test.rb +82 -58
  225. data/test/cases/counter_cache_test.rb +204 -50
  226. data/test/cases/custom_locking_test.rb +5 -3
  227. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  228. data/test/cases/database_configurations/resolver_test.rb +150 -0
  229. data/test/cases/database_configurations_test.rb +145 -0
  230. data/test/cases/database_selector_test.rb +296 -0
  231. data/test/cases/database_statements_test.rb +18 -16
  232. data/test/cases/date_test.rb +8 -16
  233. data/test/cases/date_time_precision_test.rb +100 -78
  234. data/test/cases/date_time_test.rb +23 -8
  235. data/test/cases/defaults_test.rb +106 -71
  236. data/test/cases/delegated_type_test.rb +57 -0
  237. data/test/cases/dirty_test.rb +419 -223
  238. data/test/cases/disconnected_test.rb +6 -6
  239. data/test/cases/dup_test.rb +54 -27
  240. data/test/cases/enum_test.rb +461 -82
  241. data/test/cases/errors_test.rb +7 -7
  242. data/test/cases/explain_subscriber_test.rb +17 -15
  243. data/test/cases/explain_test.rb +11 -19
  244. data/test/cases/filter_attributes_test.rb +153 -0
  245. data/test/cases/finder_respond_to_test.rb +14 -14
  246. data/test/cases/finder_test.rb +669 -287
  247. data/test/cases/fixture_set/file_test.rb +34 -38
  248. data/test/cases/fixtures_test.rb +833 -176
  249. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  250. data/test/cases/habtm_destroy_order_test.rb +25 -25
  251. data/test/cases/helper.rb +78 -49
  252. data/test/cases/hot_compatibility_test.rb +33 -32
  253. data/test/cases/i18n_test.rb +18 -17
  254. data/test/cases/inheritance_test.rb +180 -115
  255. data/test/cases/insert_all_test.rb +489 -0
  256. data/test/cases/instrumentation_test.rb +101 -0
  257. data/test/cases/integration_test.rb +119 -31
  258. data/test/cases/invalid_connection_test.rb +18 -16
  259. data/test/cases/invertible_migration_test.rb +183 -43
  260. data/test/cases/json_attribute_test.rb +35 -0
  261. data/test/cases/json_serialization_test.rb +57 -58
  262. data/test/cases/json_shared_test_cases.rb +290 -0
  263. data/test/cases/locking_test.rb +413 -119
  264. data/test/cases/log_subscriber_test.rb +68 -26
  265. data/test/cases/marshal_serialization_test.rb +39 -0
  266. data/test/cases/migration/change_schema_test.rb +118 -72
  267. data/test/cases/migration/change_table_test.rb +138 -30
  268. data/test/cases/migration/check_constraint_test.rb +162 -0
  269. data/test/cases/migration/column_attributes_test.rb +45 -35
  270. data/test/cases/migration/column_positioning_test.rb +18 -6
  271. data/test/cases/migration/columns_test.rb +93 -77
  272. data/test/cases/migration/command_recorder_test.rb +121 -34
  273. data/test/cases/migration/compatibility_test.rb +578 -23
  274. data/test/cases/migration/create_join_table_test.rb +35 -25
  275. data/test/cases/migration/foreign_key_test.rb +503 -284
  276. data/test/cases/migration/helper.rb +4 -3
  277. data/test/cases/migration/index_test.rb +119 -70
  278. data/test/cases/migration/logger_test.rb +9 -6
  279. data/test/cases/migration/pending_migrations_test.rb +88 -34
  280. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  281. data/test/cases/migration/references_index_test.rb +38 -19
  282. data/test/cases/migration/references_statements_test.rb +15 -14
  283. data/test/cases/migration/rename_table_test.rb +53 -30
  284. data/test/cases/migration_test.rb +637 -269
  285. data/test/cases/migrator_test.rb +191 -135
  286. data/test/cases/mixin_test.rb +7 -11
  287. data/test/cases/modules_test.rb +36 -34
  288. data/test/cases/multi_db_migrator_test.rb +223 -0
  289. data/test/cases/multiparameter_attributes_test.rb +60 -33
  290. data/test/cases/multiple_db_test.rb +16 -22
  291. data/test/cases/nested_attributes_test.rb +341 -320
  292. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  293. data/test/cases/null_relation_test.rb +84 -0
  294. data/test/cases/numeric_data_test.rb +93 -0
  295. data/test/cases/persistence_test.rb +361 -269
  296. data/test/cases/pooled_connections_test.rb +18 -26
  297. data/test/cases/prepared_statement_status_test.rb +48 -0
  298. data/test/cases/primary_keys_test.rb +210 -104
  299. data/test/cases/query_cache_test.rb +610 -141
  300. data/test/cases/quoting_test.rb +132 -31
  301. data/test/cases/readonly_test.rb +49 -48
  302. data/test/cases/reaper_test.rb +146 -32
  303. data/test/cases/reflection_test.rb +167 -156
  304. data/test/cases/relation/delegation_test.rb +49 -36
  305. data/test/cases/relation/delete_all_test.rb +117 -0
  306. data/test/cases/relation/merging_test.rb +319 -42
  307. data/test/cases/relation/mutation_test.rb +55 -93
  308. data/test/cases/relation/or_test.rb +129 -29
  309. data/test/cases/relation/predicate_builder_test.rb +21 -6
  310. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  311. data/test/cases/relation/select_test.rb +67 -0
  312. data/test/cases/relation/update_all_test.rb +317 -0
  313. data/test/cases/relation/where_chain_test.rb +68 -32
  314. data/test/cases/relation/where_clause_test.rb +136 -61
  315. data/test/cases/relation/where_test.rb +155 -48
  316. data/test/cases/relation_test.rb +266 -112
  317. data/test/cases/relations_test.rb +969 -744
  318. data/test/cases/reload_models_test.rb +13 -9
  319. data/test/cases/reserved_word_test.rb +141 -0
  320. data/test/cases/result_test.rb +68 -17
  321. data/test/cases/sanitize_test.rb +87 -71
  322. data/test/cases/schema_dumper_test.rb +221 -128
  323. data/test/cases/schema_loading_test.rb +3 -2
  324. data/test/cases/scoping/default_scoping_test.rb +185 -144
  325. data/test/cases/scoping/named_scoping_test.rb +177 -89
  326. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  327. data/test/cases/secure_token_test.rb +18 -3
  328. data/test/cases/serialization_test.rb +30 -28
  329. data/test/cases/serialized_attribute_test.rb +133 -42
  330. data/test/cases/signed_id_test.rb +168 -0
  331. data/test/cases/statement_cache_test.rb +41 -24
  332. data/test/cases/statement_invalid_test.rb +42 -0
  333. data/test/cases/store_test.rb +180 -55
  334. data/test/cases/strict_loading_test.rb +473 -0
  335. data/test/cases/suppressor_test.rb +26 -12
  336. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  337. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  338. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  339. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  340. data/test/cases/test_case.rb +51 -40
  341. data/test/cases/test_databases_test.rb +79 -0
  342. data/test/cases/test_fixtures_test.rb +79 -19
  343. data/test/cases/time_precision_test.rb +98 -76
  344. data/test/cases/timestamp_test.rb +102 -99
  345. data/test/cases/touch_later_test.rb +12 -10
  346. data/test/cases/transaction_callbacks_test.rb +344 -90
  347. data/test/cases/transaction_isolation_test.rb +12 -12
  348. data/test/cases/transactions_test.rb +612 -162
  349. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  350. data/test/cases/type/date_time_test.rb +4 -2
  351. data/test/cases/type/integer_test.rb +4 -2
  352. data/test/cases/type/string_test.rb +10 -8
  353. data/test/cases/type/time_test.rb +28 -0
  354. data/test/cases/type/type_map_test.rb +29 -28
  355. data/test/cases/type/unsigned_integer_test.rb +19 -0
  356. data/test/cases/type_test.rb +2 -0
  357. data/test/cases/types_test.rb +3 -1
  358. data/test/cases/unconnected_test.rb +14 -1
  359. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  360. data/test/cases/validations/absence_validation_test.rb +19 -17
  361. data/test/cases/validations/association_validation_test.rb +30 -28
  362. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  363. data/test/cases/validations/i18n_validation_test.rb +22 -21
  364. data/test/cases/validations/length_validation_test.rb +34 -33
  365. data/test/cases/validations/numericality_validation_test.rb +181 -0
  366. data/test/cases/validations/presence_validation_test.rb +21 -19
  367. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  368. data/test/cases/validations_repair_helper.rb +2 -0
  369. data/test/cases/validations_test.rb +61 -26
  370. data/test/cases/view_test.rb +122 -116
  371. data/test/cases/yaml_serialization_test.rb +79 -34
  372. data/test/config.example.yml +19 -19
  373. data/test/config.rb +3 -1
  374. data/test/config.yml +16 -6
  375. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  376. data/test/fixtures/author_addresses.yml +1 -8
  377. data/test/fixtures/authors.yml +1 -7
  378. data/test/fixtures/binaries.yml +4 -0
  379. data/test/fixtures/books.yml +9 -2
  380. data/test/fixtures/categories_posts.yml +3 -0
  381. data/test/fixtures/citations.yml +5 -0
  382. data/test/fixtures/comments.yml +7 -0
  383. data/test/fixtures/companies.yml +5 -0
  384. data/test/fixtures/computers.yml +2 -0
  385. data/test/fixtures/customers.yml +10 -1
  386. data/test/fixtures/developers.yml +1 -1
  387. data/test/fixtures/essays.yml +10 -0
  388. data/test/fixtures/faces.yml +3 -3
  389. data/test/fixtures/humans.yml +5 -0
  390. data/test/fixtures/interests.yml +7 -7
  391. data/test/fixtures/memberships.yml +7 -0
  392. data/test/fixtures/minimalistics.yml +3 -0
  393. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  394. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  395. data/test/fixtures/naked/yml/parrots.yml +1 -0
  396. data/test/fixtures/other_books.yml +26 -0
  397. data/test/fixtures/other_posts.yml +1 -0
  398. data/test/fixtures/parrots.yml +7 -1
  399. data/test/fixtures/pirates.yml +3 -0
  400. data/test/fixtures/posts.yml +11 -3
  401. data/test/fixtures/readers.yml +6 -0
  402. data/test/fixtures/reserved_words/values.yml +2 -2
  403. data/test/fixtures/sponsors.yml +3 -0
  404. data/test/fixtures/strict_zines.yml +2 -0
  405. data/test/fixtures/subscribers.yml +1 -1
  406. data/test/fixtures/tasks.yml +1 -1
  407. data/test/fixtures/warehouse-things.yml +3 -0
  408. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  409. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  410. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  411. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  412. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  413. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  414. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  415. data/test/migrations/rename/1_we_need_things.rb +2 -0
  416. data/test/migrations/rename/2_rename_things.rb +2 -0
  417. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  418. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  419. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  420. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  421. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  422. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  423. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  424. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  425. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  426. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  427. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  428. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  429. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  430. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  431. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  432. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  433. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  434. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  435. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  436. data/test/models/account.rb +46 -0
  437. data/test/models/admin/account.rb +3 -1
  438. data/test/models/admin/randomly_named_c1.rb +2 -0
  439. data/test/models/admin/user.rb +16 -8
  440. data/test/models/admin.rb +4 -2
  441. data/test/models/aircraft.rb +3 -1
  442. data/test/models/arunit2_model.rb +2 -0
  443. data/test/models/author.rb +153 -102
  444. data/test/models/auto_id.rb +2 -0
  445. data/test/models/autoloadable/extra_firm.rb +2 -0
  446. data/test/models/binary.rb +3 -1
  447. data/test/models/binary_field.rb +6 -0
  448. data/test/models/bird.rb +13 -1
  449. data/test/models/book.rb +14 -4
  450. data/test/models/book_destroy_async.rb +24 -0
  451. data/test/models/boolean.rb +5 -0
  452. data/test/models/bulb.rb +13 -4
  453. data/test/models/cake_designer.rb +2 -0
  454. data/test/models/car.rb +17 -10
  455. data/test/models/carrier.rb +2 -0
  456. data/test/models/cart.rb +5 -0
  457. data/test/models/cat.rb +2 -0
  458. data/test/models/categorization.rb +8 -6
  459. data/test/models/category.rb +28 -16
  460. data/test/models/chef.rb +2 -0
  461. data/test/models/citation.rb +5 -1
  462. data/test/models/club.rb +13 -10
  463. data/test/models/college.rb +4 -2
  464. data/test/models/column.rb +2 -0
  465. data/test/models/column_name.rb +2 -0
  466. data/test/models/comment.rb +32 -10
  467. data/test/models/company.rb +102 -106
  468. data/test/models/company_in_module.rb +27 -26
  469. data/test/models/computer.rb +3 -1
  470. data/test/models/contact.rb +15 -13
  471. data/test/models/content.rb +5 -3
  472. data/test/models/contract.rb +21 -3
  473. data/test/models/country.rb +2 -4
  474. data/test/models/course.rb +3 -1
  475. data/test/models/customer.rb +10 -8
  476. data/test/models/customer_carrier.rb +2 -0
  477. data/test/models/dashboard.rb +2 -0
  478. data/test/models/default.rb +2 -0
  479. data/test/models/department.rb +2 -0
  480. data/test/models/destroy_async_parent.rb +15 -0
  481. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  482. data/test/models/developer.rb +152 -85
  483. data/test/models/dl_keyed_belongs_to.rb +13 -0
  484. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  485. data/test/models/dl_keyed_has_many.rb +5 -0
  486. data/test/models/dl_keyed_has_many_through.rb +5 -0
  487. data/test/models/dl_keyed_has_one.rb +5 -0
  488. data/test/models/dl_keyed_join.rb +10 -0
  489. data/test/models/dog.rb +2 -0
  490. data/test/models/dog_lover.rb +2 -0
  491. data/test/models/doubloon.rb +3 -1
  492. data/test/models/drink_designer.rb +17 -0
  493. data/test/models/edge.rb +4 -2
  494. data/test/models/electron.rb +2 -0
  495. data/test/models/engine.rb +3 -2
  496. data/test/models/entrant.rb +2 -0
  497. data/test/models/entry.rb +5 -0
  498. data/test/models/essay.rb +6 -3
  499. data/test/models/essay_destroy_async.rb +12 -0
  500. data/test/models/event.rb +3 -1
  501. data/test/models/eye.rb +5 -3
  502. data/test/models/face.rb +14 -6
  503. data/test/models/family.rb +6 -0
  504. data/test/models/family_tree.rb +6 -0
  505. data/test/models/friendship.rb +5 -3
  506. data/test/models/frog.rb +8 -0
  507. data/test/models/guid.rb +3 -1
  508. data/test/models/guitar.rb +2 -0
  509. data/test/models/hotel.rb +5 -3
  510. data/test/models/human.rb +39 -0
  511. data/test/models/image.rb +3 -1
  512. data/test/models/interest.rb +14 -3
  513. data/test/models/invoice.rb +4 -2
  514. data/test/models/item.rb +3 -1
  515. data/test/models/job.rb +5 -3
  516. data/test/models/joke.rb +4 -2
  517. data/test/models/keyboard.rb +3 -1
  518. data/test/models/legacy_thing.rb +2 -0
  519. data/test/models/lesson.rb +2 -0
  520. data/test/models/line_item.rb +3 -1
  521. data/test/models/liquid.rb +2 -0
  522. data/test/models/matey.rb +3 -1
  523. data/test/models/measurement.rb +4 -0
  524. data/test/models/member.rb +23 -20
  525. data/test/models/member_detail.rb +3 -0
  526. data/test/models/member_type.rb +2 -0
  527. data/test/models/membership.rb +4 -1
  528. data/test/models/mentor.rb +3 -1
  529. data/test/models/message.rb +5 -0
  530. data/test/models/minimalistic.rb +2 -0
  531. data/test/models/minivan.rb +3 -2
  532. data/test/models/mixed_case_monkey.rb +3 -1
  533. data/test/models/molecule.rb +2 -0
  534. data/test/models/mouse.rb +6 -0
  535. data/test/models/movie.rb +2 -0
  536. data/test/models/node.rb +4 -2
  537. data/test/models/non_primary_key.rb +2 -0
  538. data/test/models/notification.rb +2 -0
  539. data/test/models/numeric_data.rb +12 -0
  540. data/test/models/order.rb +4 -2
  541. data/test/models/organization.rb +9 -7
  542. data/test/models/other_dog.rb +3 -1
  543. data/test/models/owner.rb +6 -4
  544. data/test/models/parrot.rb +12 -4
  545. data/test/models/person.rb +59 -54
  546. data/test/models/personal_legacy_thing.rb +3 -1
  547. data/test/models/pet.rb +4 -2
  548. data/test/models/pet_treasure.rb +2 -0
  549. data/test/models/pirate.rb +67 -43
  550. data/test/models/possession.rb +3 -1
  551. data/test/models/post.rb +184 -86
  552. data/test/models/price_estimate.rb +11 -1
  553. data/test/models/professor.rb +3 -1
  554. data/test/models/project.rb +14 -12
  555. data/test/models/publisher/article.rb +2 -0
  556. data/test/models/publisher/magazine.rb +2 -0
  557. data/test/models/publisher.rb +2 -0
  558. data/test/models/randomly_named_c1.rb +2 -0
  559. data/test/models/rating.rb +5 -1
  560. data/test/models/reader.rb +7 -5
  561. data/test/models/recipe.rb +2 -0
  562. data/test/models/record.rb +2 -0
  563. data/test/models/reference.rb +6 -3
  564. data/test/models/reply.rb +39 -21
  565. data/test/models/room.rb +6 -0
  566. data/test/models/section.rb +6 -0
  567. data/test/models/seminar.rb +6 -0
  568. data/test/models/session.rb +6 -0
  569. data/test/models/ship.rb +12 -9
  570. data/test/models/ship_part.rb +5 -3
  571. data/test/models/shop.rb +4 -2
  572. data/test/models/shop_account.rb +2 -0
  573. data/test/models/speedometer.rb +2 -0
  574. data/test/models/sponsor.rb +8 -5
  575. data/test/models/squeak.rb +6 -0
  576. data/test/models/strict_zine.rb +7 -0
  577. data/test/models/string_key_object.rb +2 -0
  578. data/test/models/student.rb +2 -0
  579. data/test/models/subscriber.rb +4 -2
  580. data/test/models/subscription.rb +5 -1
  581. data/test/models/tag.rb +6 -3
  582. data/test/models/tagging.rb +13 -6
  583. data/test/models/task.rb +2 -0
  584. data/test/models/topic.rb +54 -19
  585. data/test/models/toy.rb +4 -0
  586. data/test/models/traffic_light.rb +2 -0
  587. data/test/models/treasure.rb +5 -3
  588. data/test/models/treaty.rb +2 -4
  589. data/test/models/tree.rb +2 -0
  590. data/test/models/tuning_peg.rb +2 -0
  591. data/test/models/tyre.rb +2 -0
  592. data/test/models/user.rb +12 -4
  593. data/test/models/uuid_child.rb +2 -0
  594. data/test/models/uuid_item.rb +2 -0
  595. data/test/models/uuid_parent.rb +2 -0
  596. data/test/models/vegetables.rb +12 -3
  597. data/test/models/vertex.rb +6 -4
  598. data/test/models/warehouse_thing.rb +2 -0
  599. data/test/models/wheel.rb +3 -1
  600. data/test/models/without_table.rb +3 -1
  601. data/test/models/zine.rb +3 -1
  602. data/test/schema/mysql2_specific_schema.rb +49 -35
  603. data/test/schema/oracle_specific_schema.rb +13 -15
  604. data/test/schema/postgresql_specific_schema.rb +51 -40
  605. data/test/schema/schema.rb +334 -154
  606. data/test/schema/sqlite_specific_schema.rb +9 -16
  607. data/test/support/config.rb +26 -26
  608. data/test/support/connection.rb +14 -8
  609. data/test/support/connection_helper.rb +3 -1
  610. data/test/support/ddl_helper.rb +2 -0
  611. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  618. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  619. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  620. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  621. data/test/support/schema_dumping_helper.rb +2 -0
  622. data/test/support/stubs/strong_parameters.rb +40 -0
  623. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  624. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  625. metadata +192 -14
@@ -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