ibm_db 4.0.0-x86-mingw32 → 5.0.2-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (570) hide show
  1. checksums.yaml +5 -5
  2. data/MANIFEST +14 -14
  3. data/README +208 -208
  4. data/ext/Makefile +269 -0
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +322 -291
  8. data/ext/gil_release_version +3 -0
  9. data/ext/ibm_db.c +11879 -11887
  10. data/ext/mkmf.log +110 -0
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/ext/unicode_support_version +3 -0
  15. data/init.rb +41 -41
  16. data/lib/IBM_DB.rb +27 -27
  17. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3533 -3452
  18. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -5
  19. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  20. data/lib/mswin32/ibm_db.rb +90 -90
  21. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +49 -49
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +351 -351
  26. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -193
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -50
  28. data/test/cases/adapters/mysql2/boolean_test.rb +100 -100
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -63
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -54
  31. data/test/cases/adapters/mysql2/connection_test.rb +210 -210
  32. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -45
  33. data/test/cases/adapters/mysql2/enum_test.rb +26 -26
  34. data/test/cases/adapters/mysql2/explain_test.rb +21 -21
  35. data/test/cases/adapters/mysql2/json_test.rb +195 -195
  36. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -83
  37. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -152
  38. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -59
  39. data/test/cases/adapters/mysql2/schema_test.rb +126 -126
  40. data/test/cases/adapters/mysql2/sp_test.rb +36 -36
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -14
  42. data/test/cases/adapters/mysql2/table_options_test.rb +42 -42
  43. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -66
  44. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -98
  45. data/test/cases/adapters/postgresql/array_test.rb +339 -339
  46. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -82
  47. data/test/cases/adapters/postgresql/bytea_test.rb +134 -134
  48. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -26
  49. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -38
  50. data/test/cases/adapters/postgresql/cidr_test.rb +25 -25
  51. data/test/cases/adapters/postgresql/citext_test.rb +78 -78
  52. data/test/cases/adapters/postgresql/collation_test.rb +53 -53
  53. data/test/cases/adapters/postgresql/composite_test.rb +132 -132
  54. data/test/cases/adapters/postgresql/connection_test.rb +257 -257
  55. data/test/cases/adapters/postgresql/datatype_test.rb +92 -92
  56. data/test/cases/adapters/postgresql/domain_test.rb +47 -47
  57. data/test/cases/adapters/postgresql/enum_test.rb +91 -91
  58. data/test/cases/adapters/postgresql/explain_test.rb +20 -20
  59. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -63
  60. data/test/cases/adapters/postgresql/full_text_test.rb +44 -44
  61. data/test/cases/adapters/postgresql/geometric_test.rb +378 -378
  62. data/test/cases/adapters/postgresql/hstore_test.rb +382 -382
  63. data/test/cases/adapters/postgresql/infinity_test.rb +69 -69
  64. data/test/cases/adapters/postgresql/integer_test.rb +25 -25
  65. data/test/cases/adapters/postgresql/json_test.rb +237 -237
  66. data/test/cases/adapters/postgresql/ltree_test.rb +53 -53
  67. data/test/cases/adapters/postgresql/money_test.rb +96 -96
  68. data/test/cases/adapters/postgresql/network_test.rb +94 -94
  69. data/test/cases/adapters/postgresql/numbers_test.rb +49 -49
  70. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -405
  71. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -22
  72. data/test/cases/adapters/postgresql/quoting_test.rb +44 -44
  73. data/test/cases/adapters/postgresql/range_test.rb +343 -343
  74. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -111
  75. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -34
  76. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -119
  77. data/test/cases/adapters/postgresql/schema_test.rb +597 -597
  78. data/test/cases/adapters/postgresql/serial_test.rb +154 -154
  79. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -41
  80. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -90
  81. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -33
  82. data/test/cases/adapters/postgresql/utils_test.rb +62 -62
  83. data/test/cases/adapters/postgresql/uuid_test.rb +294 -294
  84. data/test/cases/adapters/postgresql/xml_test.rb +54 -54
  85. data/test/cases/adapters/sqlite3/collation_test.rb +53 -53
  86. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -98
  87. data/test/cases/adapters/sqlite3/explain_test.rb +21 -21
  88. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -101
  89. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -441
  90. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -24
  91. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -20
  92. data/test/cases/aggregations_test.rb +168 -168
  93. data/test/cases/ar_schema_test.rb +146 -146
  94. data/test/cases/associations/association_scope_test.rb +16 -16
  95. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1141
  96. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -41
  97. data/test/cases/associations/callbacks_test.rb +190 -190
  98. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  99. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  100. data/test/cases/associations/eager_load_nested_include_test.rb +126 -126
  101. data/test/cases/associations/eager_singularization_test.rb +148 -148
  102. data/test/cases/associations/eager_test.rb +1514 -1514
  103. data/test/cases/associations/extension_test.rb +87 -87
  104. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -1004
  105. data/test/cases/associations/has_many_associations_test.rb +2501 -2501
  106. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1271
  107. data/test/cases/associations/has_one_associations_test.rb +707 -707
  108. data/test/cases/associations/has_one_through_associations_test.rb +383 -383
  109. data/test/cases/associations/inner_join_association_test.rb +139 -139
  110. data/test/cases/associations/inverse_associations_test.rb +733 -733
  111. data/test/cases/associations/join_model_test.rb +777 -777
  112. data/test/cases/associations/left_outer_join_association_test.rb +88 -88
  113. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  114. data/test/cases/associations/required_test.rb +102 -102
  115. data/test/cases/associations_test.rb +385 -385
  116. data/test/cases/attribute_decorators_test.rb +126 -125
  117. data/test/cases/attribute_methods/read_test.rb +60 -60
  118. data/test/cases/attribute_methods_test.rb +1009 -1009
  119. data/test/cases/attribute_set_test.rb +270 -270
  120. data/test/cases/attribute_test.rb +246 -246
  121. data/test/cases/attributes_test.rb +253 -253
  122. data/test/cases/autosave_association_test.rb +1708 -1708
  123. data/test/cases/base_test.rb +1713 -1713
  124. data/test/cases/batches_test.rb +489 -489
  125. data/test/cases/binary_test.rb +44 -44
  126. data/test/cases/bind_parameter_test.rb +110 -110
  127. data/test/cases/cache_key_test.rb +26 -25
  128. data/test/cases/calculations_test.rb +798 -798
  129. data/test/cases/callbacks_test.rb +636 -636
  130. data/test/cases/clone_test.rb +40 -40
  131. data/test/cases/coders/json_test.rb +15 -15
  132. data/test/cases/coders/yaml_column_test.rb +63 -63
  133. data/test/cases/collection_cache_key_test.rb +115 -115
  134. data/test/cases/column_alias_test.rb +17 -17
  135. data/test/cases/column_definition_test.rb +92 -92
  136. data/test/cases/comment_test.rb +145 -143
  137. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -56
  138. data/test/cases/connection_adapters/connection_handler_test.rb +160 -160
  139. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  140. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -255
  141. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -69
  142. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  143. data/test/cases/connection_adapters/schema_cache_test.rb +61 -61
  144. data/test/cases/connection_adapters/type_lookup_test.rb +118 -118
  145. data/test/cases/connection_management_test.rb +112 -112
  146. data/test/cases/connection_pool_test.rb +521 -521
  147. data/test/cases/connection_specification/resolver_test.rb +131 -131
  148. data/test/cases/core_test.rb +112 -112
  149. data/test/cases/counter_cache_test.rb +214 -214
  150. data/test/cases/custom_locking_test.rb +17 -17
  151. data/test/cases/database_statements_test.rb +34 -34
  152. data/test/cases/date_test.rb +44 -44
  153. data/test/cases/date_time_precision_test.rb +107 -106
  154. data/test/cases/date_time_test.rb +61 -61
  155. data/test/cases/defaults_test.rb +219 -218
  156. data/test/cases/dirty_test.rb +763 -763
  157. data/test/cases/disconnected_test.rb +30 -30
  158. data/test/cases/dup_test.rb +157 -157
  159. data/test/cases/enum_test.rb +444 -444
  160. data/test/cases/errors_test.rb +16 -16
  161. data/test/cases/explain_subscriber_test.rb +64 -64
  162. data/test/cases/explain_test.rb +87 -87
  163. data/test/cases/finder_respond_to_test.rb +60 -60
  164. data/test/cases/finder_test.rb +1294 -1294
  165. data/test/cases/fixture_set/file_test.rb +156 -156
  166. data/test/cases/fixtures_test.rb +988 -988
  167. data/test/cases/forbidden_attributes_protection_test.rb +165 -165
  168. data/test/cases/habtm_destroy_order_test.rb +61 -61
  169. data/test/cases/helper.rb +204 -204
  170. data/test/cases/hot_compatibility_test.rb +142 -142
  171. data/test/cases/i18n_test.rb +45 -45
  172. data/test/cases/inheritance_test.rb +606 -606
  173. data/test/cases/integration_test.rb +155 -155
  174. data/test/cases/invalid_connection_test.rb +24 -24
  175. data/test/cases/invertible_migration_test.rb +387 -387
  176. data/test/cases/json_serialization_test.rb +311 -311
  177. data/test/cases/locking_test.rb +493 -493
  178. data/test/cases/log_subscriber_test.rb +225 -225
  179. data/test/cases/migration/change_schema_test.rb +458 -458
  180. data/test/cases/migration/change_table_test.rb +256 -256
  181. data/test/cases/migration/column_attributes_test.rb +176 -176
  182. data/test/cases/migration/column_positioning_test.rb +56 -56
  183. data/test/cases/migration/columns_test.rb +310 -310
  184. data/test/cases/migration/command_recorder_test.rb +350 -350
  185. data/test/cases/migration/compatibility_test.rb +118 -118
  186. data/test/cases/migration/create_join_table_test.rb +157 -157
  187. data/test/cases/migration/foreign_key_test.rb +362 -360
  188. data/test/cases/migration/helper.rb +39 -39
  189. data/test/cases/migration/index_test.rb +218 -218
  190. data/test/cases/migration/logger_test.rb +36 -36
  191. data/test/cases/migration/pending_migrations_test.rb +52 -52
  192. data/test/cases/migration/references_foreign_key_test.rb +221 -216
  193. data/test/cases/migration/references_index_test.rb +101 -101
  194. data/test/cases/migration/references_statements_test.rb +136 -136
  195. data/test/cases/migration/rename_table_test.rb +93 -93
  196. data/test/cases/migration_test.rb +1157 -1157
  197. data/test/cases/migrator_test.rb +471 -470
  198. data/test/cases/mixin_test.rb +68 -68
  199. data/test/cases/modules_test.rb +172 -172
  200. data/test/cases/multiparameter_attributes_test.rb +372 -372
  201. data/test/cases/multiple_db_test.rb +122 -122
  202. data/test/cases/nested_attributes_test.rb +1098 -1098
  203. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  204. data/test/cases/persistence_test.rb +1001 -1001
  205. data/test/cases/pooled_connections_test.rb +81 -81
  206. data/test/cases/primary_keys_test.rb +376 -376
  207. data/test/cases/query_cache_test.rb +446 -446
  208. data/test/cases/quoting_test.rb +202 -202
  209. data/test/cases/readonly_test.rb +119 -119
  210. data/test/cases/reaper_test.rb +85 -85
  211. data/test/cases/reflection_test.rb +509 -509
  212. data/test/cases/relation/delegation_test.rb +63 -63
  213. data/test/cases/relation/merging_test.rb +157 -157
  214. data/test/cases/relation/mutation_test.rb +183 -183
  215. data/test/cases/relation/or_test.rb +92 -92
  216. data/test/cases/relation/predicate_builder_test.rb +16 -16
  217. data/test/cases/relation/record_fetch_warning_test.rb +40 -40
  218. data/test/cases/relation/where_chain_test.rb +105 -105
  219. data/test/cases/relation/where_clause_test.rb +182 -182
  220. data/test/cases/relation/where_test.rb +322 -322
  221. data/test/cases/relation_test.rb +328 -328
  222. data/test/cases/relations_test.rb +2026 -2026
  223. data/test/cases/reload_models_test.rb +22 -22
  224. data/test/cases/result_test.rb +90 -90
  225. data/test/cases/sanitize_test.rb +176 -176
  226. data/test/cases/schema_dumper_test.rb +457 -457
  227. data/test/cases/schema_loading_test.rb +52 -52
  228. data/test/cases/scoping/default_scoping_test.rb +528 -528
  229. data/test/cases/scoping/named_scoping_test.rb +561 -561
  230. data/test/cases/scoping/relation_scoping_test.rb +400 -400
  231. data/test/cases/secure_token_test.rb +32 -32
  232. data/test/cases/serialization_test.rb +104 -104
  233. data/test/cases/serialized_attribute_test.rb +364 -364
  234. data/test/cases/statement_cache_test.rb +136 -136
  235. data/test/cases/store_test.rb +195 -195
  236. data/test/cases/suppressor_test.rb +63 -63
  237. data/test/cases/tasks/database_tasks_test.rb +462 -462
  238. data/test/cases/tasks/mysql_rake_test.rb +345 -345
  239. data/test/cases/tasks/postgresql_rake_test.rb +304 -304
  240. data/test/cases/tasks/sqlite_rake_test.rb +220 -220
  241. data/test/cases/test_case.rb +131 -131
  242. data/test/cases/test_fixtures_test.rb +36 -36
  243. data/test/cases/time_precision_test.rb +103 -102
  244. data/test/cases/timestamp_test.rb +501 -501
  245. data/test/cases/touch_later_test.rb +121 -121
  246. data/test/cases/transaction_callbacks_test.rb +518 -518
  247. data/test/cases/transaction_isolation_test.rb +106 -106
  248. data/test/cases/transactions_test.rb +835 -834
  249. data/test/cases/type/adapter_specific_registry_test.rb +133 -133
  250. data/test/cases/type/date_time_test.rb +14 -14
  251. data/test/cases/type/integer_test.rb +27 -27
  252. data/test/cases/type/string_test.rb +22 -22
  253. data/test/cases/type/type_map_test.rb +177 -177
  254. data/test/cases/type_test.rb +39 -39
  255. data/test/cases/types_test.rb +24 -24
  256. data/test/cases/unconnected_test.rb +33 -33
  257. data/test/cases/validations/absence_validation_test.rb +73 -73
  258. data/test/cases/validations/association_validation_test.rb +97 -97
  259. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  260. data/test/cases/validations/i18n_validation_test.rb +86 -86
  261. data/test/cases/validations/length_validation_test.rb +79 -79
  262. data/test/cases/validations/presence_validation_test.rb +103 -103
  263. data/test/cases/validations/uniqueness_validation_test.rb +548 -548
  264. data/test/cases/validations_repair_helper.rb +19 -19
  265. data/test/cases/validations_test.rb +194 -194
  266. data/test/cases/view_test.rb +216 -216
  267. data/test/cases/yaml_serialization_test.rb +121 -121
  268. data/test/config.example.yml +97 -97
  269. data/test/config.rb +5 -5
  270. data/test/connections/native_ibm_db/connection.rb +44 -0
  271. data/test/fixtures/accounts.yml +29 -29
  272. data/test/fixtures/admin/accounts.yml +2 -2
  273. data/test/fixtures/admin/users.yml +10 -10
  274. data/test/fixtures/author_addresses.yml +17 -17
  275. data/test/fixtures/author_favorites.yml +3 -3
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -9
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -31
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -3
  295. data/test/fixtures/content_positions.yml +3 -3
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -5
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -4
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -2
  333. data/test/fixtures/naked/yml/trees.yml +3 -3
  334. data/test/fixtures/nodes.yml +29 -29
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -6
  337. data/test/fixtures/other_dogs.yml +2 -2
  338. data/test/fixtures/other_posts.yml +7 -7
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +12 -15
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -16
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -3
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/user.rb +40 -40
  414. data/test/models/aircraft.rb +5 -5
  415. data/test/models/arunit2_model.rb +3 -3
  416. data/test/models/author.rb +209 -209
  417. data/test/models/auto_id.rb +4 -4
  418. data/test/models/autoloadable/extra_firm.rb +2 -2
  419. data/test/models/binary.rb +2 -2
  420. data/test/models/bird.rb +12 -12
  421. data/test/models/book.rb +23 -23
  422. data/test/models/boolean.rb +2 -2
  423. data/test/models/bulb.rb +52 -52
  424. data/test/models/cake_designer.rb +3 -3
  425. data/test/models/car.rb +29 -29
  426. data/test/models/carrier.rb +2 -2
  427. data/test/models/cat.rb +10 -10
  428. data/test/models/categorization.rb +19 -19
  429. data/test/models/category.rb +35 -35
  430. data/test/models/chef.rb +8 -8
  431. data/test/models/citation.rb +3 -3
  432. data/test/models/club.rb +25 -25
  433. data/test/models/college.rb +10 -10
  434. data/test/models/column.rb +3 -3
  435. data/test/models/column_name.rb +3 -3
  436. data/test/models/comment.rb +76 -76
  437. data/test/models/company.rb +230 -230
  438. data/test/models/company_in_module.rb +98 -98
  439. data/test/models/computer.rb +3 -3
  440. data/test/models/contact.rb +41 -41
  441. data/test/models/content.rb +40 -40
  442. data/test/models/contract.rb +20 -20
  443. data/test/models/country.rb +7 -7
  444. data/test/models/course.rb +6 -6
  445. data/test/models/customer.rb +83 -83
  446. data/test/models/customer_carrier.rb +14 -14
  447. data/test/models/dashboard.rb +3 -3
  448. data/test/models/default.rb +2 -2
  449. data/test/models/department.rb +4 -4
  450. data/test/models/developer.rb +274 -274
  451. data/test/models/dog.rb +5 -5
  452. data/test/models/dog_lover.rb +5 -5
  453. data/test/models/doubloon.rb +12 -12
  454. data/test/models/drink_designer.rb +3 -3
  455. data/test/models/edge.rb +5 -5
  456. data/test/models/electron.rb +5 -5
  457. data/test/models/engine.rb +4 -4
  458. data/test/models/entrant.rb +3 -3
  459. data/test/models/essay.rb +5 -5
  460. data/test/models/event.rb +3 -3
  461. data/test/models/eye.rb +37 -37
  462. data/test/models/face.rb +9 -9
  463. data/test/models/friendship.rb +6 -6
  464. data/test/models/guid.rb +2 -2
  465. data/test/models/guitar.rb +4 -4
  466. data/test/models/hotel.rb +11 -11
  467. data/test/models/image.rb +3 -3
  468. data/test/models/interest.rb +5 -5
  469. data/test/models/invoice.rb +4 -4
  470. data/test/models/item.rb +7 -7
  471. data/test/models/job.rb +7 -7
  472. data/test/models/joke.rb +7 -7
  473. data/test/models/keyboard.rb +3 -3
  474. data/test/models/legacy_thing.rb +3 -3
  475. data/test/models/lesson.rb +11 -11
  476. data/test/models/line_item.rb +3 -3
  477. data/test/models/liquid.rb +4 -4
  478. data/test/models/man.rb +11 -11
  479. data/test/models/matey.rb +4 -4
  480. data/test/models/member.rb +42 -42
  481. data/test/models/member_detail.rb +8 -8
  482. data/test/models/member_type.rb +3 -3
  483. data/test/models/membership.rb +35 -35
  484. data/test/models/mentor.rb +2 -2
  485. data/test/models/minimalistic.rb +2 -2
  486. data/test/models/minivan.rb +9 -9
  487. data/test/models/mixed_case_monkey.rb +3 -3
  488. data/test/models/mocktail_designer.rb +2 -2
  489. data/test/models/molecule.rb +6 -6
  490. data/test/models/movie.rb +5 -5
  491. data/test/models/node.rb +5 -5
  492. data/test/models/non_primary_key.rb +2 -2
  493. data/test/models/notification.rb +3 -3
  494. data/test/models/order.rb +4 -4
  495. data/test/models/organization.rb +14 -14
  496. data/test/models/other_dog.rb +5 -5
  497. data/test/models/owner.rb +37 -37
  498. data/test/models/parrot.rb +28 -28
  499. data/test/models/person.rb +142 -142
  500. data/test/models/personal_legacy_thing.rb +4 -4
  501. data/test/models/pet.rb +18 -18
  502. data/test/models/pet_treasure.rb +6 -6
  503. data/test/models/pirate.rb +92 -92
  504. data/test/models/possession.rb +3 -3
  505. data/test/models/post.rb +273 -273
  506. data/test/models/price_estimate.rb +4 -4
  507. data/test/models/professor.rb +5 -5
  508. data/test/models/project.rb +40 -40
  509. data/test/models/publisher.rb +2 -2
  510. data/test/models/publisher/article.rb +4 -4
  511. data/test/models/publisher/magazine.rb +3 -3
  512. data/test/models/rating.rb +4 -4
  513. data/test/models/reader.rb +23 -23
  514. data/test/models/recipe.rb +3 -3
  515. data/test/models/record.rb +2 -2
  516. data/test/models/reference.rb +22 -22
  517. data/test/models/reply.rb +61 -61
  518. data/test/models/ship.rb +39 -39
  519. data/test/models/ship_part.rb +8 -8
  520. data/test/models/shop.rb +17 -17
  521. data/test/models/shop_account.rb +6 -6
  522. data/test/models/speedometer.rb +6 -6
  523. data/test/models/sponsor.rb +7 -7
  524. data/test/models/string_key_object.rb +3 -3
  525. data/test/models/student.rb +4 -4
  526. data/test/models/subject.rb +16 -16
  527. data/test/models/subscriber.rb +8 -8
  528. data/test/models/subscription.rb +4 -4
  529. data/test/models/tag.rb +13 -13
  530. data/test/models/tagging.rb +13 -13
  531. data/test/models/task.rb +5 -5
  532. data/test/models/topic.rb +118 -118
  533. data/test/models/toy.rb +6 -6
  534. data/test/models/traffic_light.rb +4 -4
  535. data/test/models/treasure.rb +14 -14
  536. data/test/models/treaty.rb +7 -7
  537. data/test/models/tree.rb +3 -3
  538. data/test/models/tuning_peg.rb +4 -4
  539. data/test/models/tyre.rb +11 -11
  540. data/test/models/user.rb +14 -14
  541. data/test/models/uuid_child.rb +3 -3
  542. data/test/models/uuid_item.rb +6 -6
  543. data/test/models/uuid_parent.rb +3 -3
  544. data/test/models/vegetables.rb +24 -24
  545. data/test/models/vehicle.rb +6 -6
  546. data/test/models/vertex.rb +9 -9
  547. data/test/models/warehouse_thing.rb +5 -5
  548. data/test/models/wheel.rb +3 -3
  549. data/test/models/without_table.rb +3 -3
  550. data/test/models/zine.rb +3 -3
  551. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  552. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  553. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  554. data/test/schema/mysql2_specific_schema.rb +68 -68
  555. data/test/schema/oracle_specific_schema.rb +40 -40
  556. data/test/schema/postgresql_specific_schema.rb +114 -114
  557. data/test/schema/schema.rb +1057 -1057
  558. data/test/schema/schema.rb.original +1057 -1057
  559. data/test/schema/sqlite_specific_schema.rb +18 -18
  560. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  561. data/test/support/config.rb +43 -43
  562. data/test/support/connection.rb +23 -23
  563. data/test/support/connection_helper.rb +14 -14
  564. data/test/support/ddl_helper.rb +8 -8
  565. data/test/support/schema_dumping_helper.rb +20 -20
  566. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -22
  567. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -182
  568. metadata +24 -13
  569. data/test/fixtures/author_addresses.original +0 -11
  570. data/test/fixtures/authors.original +0 -17
@@ -1,2026 +1,2026 @@
1
- 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'
19
- require "models/possession"
20
- require "models/reader"
21
- require "models/categorization"
22
- require "models/edge"
23
-
24
- 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
32
-
33
- def test_do_not_double_quote_string_id
34
- van = Minivan.last
35
- assert van
36
- assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id
37
- end
38
-
39
- def test_do_not_double_quote_string_id_with_array
40
- van = Minivan.last
41
- assert van
42
- assert_equal van, Minivan.where(:minivan_id => [van]).to_a.first
43
- end
44
-
45
- def test_two_scopes_with_includes_should_not_drop_any_include
46
- # heat habtm cache
47
- car = Car.incl_engines.incl_tyres.first
48
- car.tyres.length
49
- car.engines.length
50
-
51
- car = Car.incl_engines.incl_tyres.first
52
- assert_no_queries { car.tyres.length }
53
- assert_no_queries { car.engines.length }
54
- end
55
-
56
- def test_dynamic_finder
57
- x = Post.where('author_id = ?', 1)
58
- assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders'
59
- end
60
-
61
- def test_multivalue_where
62
- posts = Post.where('author_id = ? AND id = ?', 1, 1)
63
- assert_equal 1, posts.to_a.size
64
- end
65
-
66
- def test_scoped
67
- topics = Topic.all
68
- assert_kind_of ActiveRecord::Relation, topics
69
- assert_equal 5, topics.size
70
- end
71
-
72
- def test_to_json
73
- assert_nothing_raised { Bird.all.to_json }
74
- assert_nothing_raised { Bird.all.to_a.to_json }
75
- end
76
-
77
- def test_to_yaml
78
- assert_nothing_raised { Bird.all.to_yaml }
79
- assert_nothing_raised { Bird.all.to_a.to_yaml }
80
- end
81
-
82
- def test_to_xml
83
- assert_nothing_raised { Bird.all.to_xml }
84
- assert_nothing_raised { Bird.all.to_a.to_xml }
85
- end
86
-
87
- def test_scoped_all
88
- topics = Topic.all.to_a
89
- assert_kind_of Array, topics
90
- assert_no_queries { assert_equal 5, topics.size }
91
- end
92
-
93
- def test_loaded_all
94
- topics = Topic.all
95
-
96
- assert_queries(1) do
97
- 2.times { assert_equal 5, topics.to_a.size }
98
- end
99
-
100
- assert topics.loaded?
101
- end
102
-
103
- def test_scoped_first
104
- topics = Topic.all.order('id ASC')
105
-
106
- assert_queries(1) do
107
- 2.times { assert_equal "The First Topic", topics.first.title }
108
- end
109
-
110
- assert ! topics.loaded?
111
- end
112
-
113
- def test_loaded_first
114
- topics = Topic.all.order('id ASC')
115
- topics.to_a # force load
116
-
117
- assert_no_queries do
118
- assert_equal "The First Topic", topics.first.title
119
- end
120
-
121
- assert topics.loaded?
122
- end
123
-
124
- def test_loaded_first_with_limit
125
- topics = Topic.all.order('id ASC')
126
- topics.to_a # force load
127
-
128
- assert_no_queries do
129
- assert_equal ["The First Topic",
130
- "The Second Topic of the day"], topics.first(2).map(&:title)
131
- end
132
-
133
- assert topics.loaded?
134
- end
135
-
136
- def test_first_get_more_than_available
137
- topics = Topic.all.order('id ASC')
138
- unloaded_first = topics.first(10)
139
- topics.to_a # force load
140
-
141
- assert_no_queries do
142
- loaded_first = topics.first(10)
143
- assert_equal unloaded_first, loaded_first
144
- end
145
- end
146
-
147
- def test_reload
148
- topics = Topic.all
149
-
150
- assert_queries(1) do
151
- 2.times { topics.to_a }
152
- end
153
-
154
- assert topics.loaded?
155
-
156
- original_size = topics.to_a.size
157
- Topic.create! :title => 'fake'
158
-
159
- assert_queries(1) { topics.reload }
160
- assert_equal original_size + 1, topics.size
161
- assert topics.loaded?
162
- end
163
-
164
- 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
- end
170
-
171
- def test_finding_with_subquery_with_binds
172
- 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
176
- end
177
-
178
- def test_finding_with_subquery_without_select_does_not_change_the_select
179
- relation = Topic.where(approved: true)
180
- assert_raises(ActiveRecord::StatementInvalid) do
181
- Topic.from(relation).to_a
182
- end
183
- end
184
-
185
- 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)
189
- end
190
-
191
- 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)
195
- end
196
-
197
- 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)
201
- end
202
-
203
- def test_finding_with_order
204
- topics = Topic.order('id')
205
- assert_equal 5, topics.to_a.size
206
- assert_equal topics(:first).title, topics.first.title
207
- end
208
-
209
- def test_finding_with_arel_order
210
- topics = Topic.order(Topic.arel_table[:id].asc)
211
- assert_equal 5, topics.to_a.size
212
- assert_equal topics(:first).title, topics.first.title
213
- end
214
-
215
- def test_finding_with_assoc_order
216
- topics = Topic.order(:id => :desc)
217
- assert_equal 5, topics.to_a.size
218
- assert_equal topics(:fifth).title, topics.first.title
219
- end
220
-
221
- def test_finding_with_reverted_assoc_order
222
- topics = Topic.order(:id => :asc).reverse_order
223
- assert_equal 5, topics.to_a.size
224
- assert_equal topics(:fifth).title, topics.first.title
225
- end
226
-
227
- def test_reverse_order_with_function
228
- topics = Topic.order("length(title)").reverse_order
229
- assert_equal topics(:second).title, topics.first.title
230
- end
231
-
232
- def test_reverse_order_with_function_other_predicates
233
- topics = Topic.order("author_name, length(title), id").reverse_order
234
- assert_equal topics(:second).title, topics.first.title
235
- topics = Topic.order("length(author_name), id, length(title)").reverse_order
236
- assert_equal topics(:fifth).title, topics.first.title
237
- end
238
-
239
- def test_reverse_order_with_multiargument_function
240
- assert_raises(ActiveRecord::IrreversibleOrderError) do
241
- Topic.order("concat(author_name, title)").reverse_order
242
- end
243
- assert_raises(ActiveRecord::IrreversibleOrderError) do
244
- Topic.order("concat(lower(author_name), title)").reverse_order
245
- end
246
- assert_raises(ActiveRecord::IrreversibleOrderError) do
247
- Topic.order("concat(author_name, lower(title))").reverse_order
248
- end
249
- assert_raises(ActiveRecord::IrreversibleOrderError) do
250
- Topic.order("concat(lower(author_name), title, length(title)").reverse_order
251
- end
252
- end
253
-
254
- def test_reverse_order_with_nulls_first_or_last
255
- assert_raises(ActiveRecord::IrreversibleOrderError) do
256
- Topic.order("title NULLS FIRST").reverse_order
257
- end
258
- assert_raises(ActiveRecord::IrreversibleOrderError) do
259
- Topic.order("title nulls last").reverse_order
260
- end
261
- end
262
-
263
- def test_default_reverse_order_on_table_without_primary_key
264
- assert_raises(ActiveRecord::IrreversibleOrderError) do
265
- Edge.all.reverse_order
266
- end
267
- end
268
-
269
- 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
271
- end
272
-
273
- def test_finding_with_desc_order_with_string
274
- topics = Topic.order(id: "desc")
275
- assert_equal 5, topics.to_a.size
276
- assert_equal [topics(:fifth), topics(:fourth), topics(:third), topics(:second), topics(:first)], topics.to_a
277
- end
278
-
279
- def test_finding_with_asc_order_with_string
280
- topics = Topic.order(id: 'asc')
281
- assert_equal 5, topics.to_a.size
282
- assert_equal [topics(:first), topics(:second), topics(:third), topics(:fourth), topics(:fifth)], topics.to_a
283
- end
284
-
285
- def test_support_upper_and_lower_case_directions
286
- assert_includes Topic.order(id: "ASC").to_sql, "ASC"
287
- assert_includes Topic.order(id: "asc").to_sql, "ASC"
288
- assert_includes Topic.order(id: :ASC).to_sql, "ASC"
289
- assert_includes Topic.order(id: :asc).to_sql, "ASC"
290
-
291
- assert_includes Topic.order(id: "DESC").to_sql, "DESC"
292
- assert_includes Topic.order(id: "desc").to_sql, "DESC"
293
- assert_includes Topic.order(id: :DESC).to_sql, "DESC"
294
- assert_includes Topic.order(id: :desc).to_sql,"DESC"
295
- end
296
-
297
- def test_raising_exception_on_invalid_hash_params
298
- e = assert_raise(ArgumentError) { Topic.order(:name, "id DESC", id: :asfsdf) }
299
- assert_equal 'Direction "asfsdf" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]', e.message
300
- end
301
-
302
- def test_finding_last_with_arel_order
303
- topics = Topic.order(Topic.arel_table[:id].asc)
304
- assert_equal topics(:fifth).title, topics.last.title
305
- end
306
-
307
- def test_finding_with_order_concatenated
308
- topics = Topic.order('author_name').order('title')
309
- assert_equal 5, topics.to_a.size
310
- assert_equal topics(:fourth).title, topics.first.title
311
- end
312
-
313
- def test_finding_with_order_by_aliased_attributes
314
- topics = Topic.order(:heading)
315
- assert_equal 5, topics.to_a.size
316
- assert_equal topics(:fifth).title, topics.first.title
317
- end
318
-
319
- def test_finding_with_assoc_order_by_aliased_attributes
320
- topics = Topic.order(heading: :desc)
321
- assert_equal 5, topics.to_a.size
322
- assert_equal topics(:third).title, topics.first.title
323
- end
324
-
325
- def test_finding_with_reorder
326
- topics = Topic.order('author_name').order('title').reorder('id').to_a
327
- 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
329
- end
330
-
331
- def test_finding_with_reorder_by_aliased_attributes
332
- topics = Topic.order('author_name').reorder(:heading)
333
- assert_equal 5, topics.to_a.size
334
- assert_equal topics(:fifth).title, topics.first.title
335
- end
336
-
337
- def test_finding_with_assoc_reorder_by_aliased_attributes
338
- topics = Topic.order('author_name').reorder(heading: :desc)
339
- assert_equal 5, topics.to_a.size
340
- assert_equal topics(:third).title, topics.first.title
341
- end
342
-
343
- def test_finding_with_order_and_take
344
- entrants = Entrant.order("id ASC").limit(2).to_a
345
-
346
- assert_equal 2, entrants.size
347
- assert_equal entrants(:first).name, entrants.first.name
348
- end
349
-
350
- def test_finding_with_cross_table_order_and_limit
351
- tags = Tag.includes(:taggings).
352
- order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
353
- limit(1).to_a
354
- assert_equal 1, tags.length
355
- end
356
-
357
- 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
359
- assert_equal 1, tags.length
360
- end
361
-
362
- def test_finding_with_complex_order
363
- tags = Tag.includes(:taggings).references(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
364
- assert_equal 3, tags.length
365
- end
366
-
367
- def test_finding_with_sanitized_order
368
- query = Tag.order(["field(id, ?)", [1,3,2]]).to_sql
369
- assert_match(/field\(id, 1,3,2\)/, query)
370
-
371
- query = Tag.order(["field(id, ?)", []]).to_sql
372
- assert_match(/field\(id, NULL\)/, query)
373
-
374
- query = Tag.order(["field(id, ?)", nil]).to_sql
375
- assert_match(/field\(id, NULL\)/, query)
376
- end
377
-
378
- def test_finding_with_order_limit_and_offset
379
- entrants = Entrant.order("id ASC").limit(2).offset(1)
380
-
381
- assert_equal 2, entrants.to_a.size
382
- assert_equal entrants(:second).name, entrants.first.name
383
-
384
- entrants = Entrant.order("id ASC").limit(2).offset(2)
385
- assert_equal 1, entrants.to_a.size
386
- assert_equal entrants(:third).name, entrants.first.name
387
- end
388
-
389
- def test_finding_with_group
390
- developers = Developer.group("salary").select("salary").to_a
391
- assert_equal 4, developers.size
392
- assert_equal 4, developers.map(&:salary).uniq.size
393
- end
394
-
395
- def test_select_with_block
396
- even_ids = Developer.all.select {|d| d.id % 2 == 0 }.map(&:id)
397
- assert_equal [2, 4, 6, 8, 10], even_ids.sort
398
- end
399
-
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
- def test_joins_with_nil_argument
518
- assert_nothing_raised { DependentFirm.joins(nil).first }
519
- end
520
-
521
- def test_finding_with_hash_conditions_on_joined_table
522
- firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
523
- assert_equal 1, firms.size
524
- assert_equal companies(:rails_core), firms.first
525
- end
526
-
527
- 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
530
-
531
- assert_equal 3, developers_on_project_one.length
532
- developer_names = developers_on_project_one.map(&:name)
533
- assert developer_names.include?('David')
534
- assert developer_names.include?('Jamis')
535
- end
536
-
537
- def test_find_on_hash_conditions
538
- assert_equal Topic.all.merge!(:where => {:approved => false}).to_a, Topic.where({ :approved => false }).to_a
539
- end
540
-
541
- def test_joins_with_string_array
542
- person_with_reader_and_post = Post.joins([
543
- "INNER JOIN categorizations ON categorizations.post_id = posts.id",
544
- "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
545
- ]
546
- ).to_a
547
- assert_equal 1, person_with_reader_and_post.size
548
- end
549
-
550
- def test_no_arguments_to_query_methods_raise_errors
551
- assert_raises(ArgumentError) { Topic.references() }
552
- assert_raises(ArgumentError) { Topic.includes() }
553
- assert_raises(ArgumentError) { Topic.preload() }
554
- assert_raises(ArgumentError) { Topic.group() }
555
- assert_raises(ArgumentError) { Topic.reorder() }
556
- end
557
-
558
- def test_blank_like_arguments_to_query_methods_dont_raise_errors
559
- assert_nothing_raised { Topic.references([]) }
560
- assert_nothing_raised { Topic.includes([]) }
561
- assert_nothing_raised { Topic.preload([]) }
562
- assert_nothing_raised { Topic.group([]) }
563
- 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
591
- end
592
-
593
- def test_respond_to_dynamic_finders
594
- relation = Topic.all
595
-
596
- ["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}"
598
- end
599
- end
600
-
601
- def test_respond_to_class_methods_and_scopes
602
- assert Topic.all.respond_to?(:by_lifo)
603
- end
604
-
605
- def test_find_with_readonly_option
606
- Developer.all.each { |d| assert !d.readonly? }
607
- Developer.all.readonly.each { |d| assert d.readonly? }
608
- end
609
-
610
- 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
613
-
614
- assert_equal [authors(:david)], authors
615
- assert_no_queries do
616
- authors.first.posts.first.special_comments.first.post.special_comments
617
- authors.first.posts.first.special_comments.first.post.very_special_comment
618
- end
619
- end
620
-
621
- def test_find_with_preloaded_associations
622
- assert_queries(2) do
623
- posts = Post.preload(:comments).order('posts.id')
624
- assert posts.first.comments.first
625
- end
626
-
627
- assert_queries(2) do
628
- posts = Post.preload(:comments).order('posts.id')
629
- assert posts.first.comments.first
630
- end
631
-
632
- assert_queries(2) do
633
- posts = Post.preload(:author).order('posts.id')
634
- assert posts.first.author
635
- end
636
-
637
- assert_queries(2) do
638
- posts = Post.preload(:author).order('posts.id')
639
- assert posts.first.author
640
- end
641
-
642
- assert_queries(3) do
643
- posts = Post.preload(:author, :comments).order('posts.id')
644
- assert posts.first.author
645
- assert posts.first.comments.first
646
- end
647
- end
648
-
649
- def test_preload_applies_to_all_chained_preloaded_scopes
650
- assert_queries(3) do
651
- post = Post.with_comments.with_tags.first
652
- assert post
653
- end
654
- end
655
-
656
- def test_find_with_included_associations
657
- assert_queries(2) do
658
- posts = Post.includes(:comments).order('posts.id')
659
- assert posts.first.comments.first
660
- end
661
-
662
- assert_queries(2) do
663
- posts = Post.all.includes(:comments).order('posts.id')
664
- assert posts.first.comments.first
665
- end
666
-
667
- assert_queries(2) do
668
- posts = Post.includes(:author).order('posts.id')
669
- assert posts.first.author
670
- end
671
-
672
- assert_queries(3) do
673
- posts = Post.includes(:author, :comments).order('posts.id')
674
- assert posts.first.author
675
- assert posts.first.comments.first
676
- end
677
- end
678
-
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
- 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
692
- end
693
-
694
- def test_includes_with_select
695
- query = Post.select('comments_count AS ranking').order('ranking').includes(:comments)
696
- .where(comments: { id: 1 })
697
-
698
- assert_equal ['comments_count AS ranking'], query.select_values
699
- assert_equal 1, query.to_a.size
700
- end
701
-
702
- def test_preloading_with_associations_and_merges
703
- post = Post.create! title: 'Uhuu', body: 'body'
704
- reader = Reader.create! post_id: post.id, person_id: 1
705
- comment = Comment.create! post_id: post.id, body: 'body'
706
-
707
- assert !comment.respond_to?(:readers)
708
-
709
- post_rel = Post.preload(:readers).joins(:readers).where(title: 'Uhuu')
710
- result_comment = Comment.joins(:post).merge(post_rel).to_a.first
711
- assert_equal comment, result_comment
712
-
713
- assert_no_queries do
714
- assert_equal post, result_comment.post
715
- assert_equal [reader], result_comment.post.readers.to_a
716
- end
717
-
718
- post_rel = Post.includes(:readers).where(title: 'Uhuu')
719
- result_comment = Comment.joins(:post).merge(post_rel).first
720
- assert_equal comment, result_comment
721
-
722
- assert_no_queries do
723
- assert_equal post, result_comment.post
724
- assert_equal [reader], result_comment.post.readers.to_a
725
- end
726
- end
727
-
728
- def test_preloading_with_associations_default_scopes_and_merges
729
- post = Post.create! title: 'Uhuu', body: 'body'
730
- reader = Reader.create! post_id: post.id, person_id: 1
731
-
732
- post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: 'Uhuu')
733
- result_post = PostWithPreloadDefaultScope.all.merge(post_rel).to_a.first
734
-
735
- assert_no_queries do
736
- assert_equal [reader], result_post.readers.to_a
737
- end
738
-
739
- post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: 'Uhuu')
740
- result_post = PostWithIncludesDefaultScope.all.merge(post_rel).to_a.first
741
-
742
- assert_no_queries do
743
- assert_equal [reader], result_post.readers.to_a
744
- end
745
- end
746
-
747
- def test_loading_with_one_association
748
- posts = Post.preload(:comments)
749
- post = posts.find { |p| p.id == 1 }
750
- assert_equal 2, post.comments.size
751
- assert post.comments.include?(comments(:greetings))
752
-
753
- post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
754
- assert_equal 2, post.comments.size
755
- assert post.comments.include?(comments(:greetings))
756
-
757
- posts = Post.preload(:last_comment)
758
- post = posts.find { |p| p.id == 1 }
759
- assert_equal Post.find(1).last_comment, post.last_comment
760
- end
761
-
762
- def test_to_sql_on_eager_join
763
- expected = assert_sql {
764
- Post.eager_load(:last_comment).order('comments.id DESC').to_a
765
- }.first
766
- actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
767
- assert_equal expected, actual
768
- end
769
-
770
- def test_to_sql_on_scoped_proxy
771
- auth = Author.first
772
- Post.where("1=1").written_by(auth)
773
- assert_not auth.posts.to_sql.include?("1=1")
774
- end
775
-
776
- def test_loading_with_one_association_with_non_preload
777
- posts = Post.eager_load(:last_comment).order('comments.id DESC')
778
- post = posts.find { |p| p.id == 1 }
779
- assert_equal Post.find(1).last_comment, post.last_comment
780
- end
781
-
782
- def test_dynamic_find_by_attributes
783
- david = authors(:david)
784
- author = Author.preload(:taggings).find_by_id(david.id)
785
- expected_taggings = taggings(:welcome_general, :thinking_general)
786
-
787
- assert_no_queries do
788
- assert_equal expected_taggings, author.taggings.distinct.sort_by(&:id)
789
- assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id)
790
- end
791
-
792
- authors = Author.all
793
- assert_equal david, authors.find_by_id_and_name(david.id, david.name)
794
- assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
795
- end
796
-
797
- def test_dynamic_find_by_attributes_bang
798
- author = Author.all.find_by_id!(authors(:david).id)
799
- assert_equal "David", author.name
800
-
801
- assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, 'invalid') }
802
- end
803
-
804
- def test_find_id
805
- authors = Author.all
806
-
807
- david = authors.find(authors(:david).id)
808
- assert_equal 'David', david.name
809
-
810
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
811
- end
812
-
813
- def test_find_ids
814
- authors = Author.order('id ASC')
815
-
816
- results = authors.find(authors(:david).id, authors(:mary).id)
817
- assert_kind_of Array, results
818
- assert_equal 2, results.size
819
- assert_equal 'David', results[0].name
820
- assert_equal 'Mary', results[1].name
821
- assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
822
-
823
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
824
- assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
825
- end
826
-
827
- def test_find_in_empty_array
828
- authors = Author.all.where(:id => [])
829
- assert authors.to_a.blank?
830
- end
831
-
832
- def test_where_with_ar_object
833
- author = Author.first
834
- authors = Author.all.where(:id => author)
835
- assert_equal 1, authors.to_a.length
836
- end
837
-
838
- def test_find_with_list_of_ar
839
- author = Author.first
840
- authors = Author.find([author.id])
841
- assert_equal author, authors.first
842
- end
843
-
844
- class Mary < Author; end
845
-
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
851
- end
852
-
853
- def test_find_by_id_with_list_of_ar
854
- author = Author.first
855
- authors = Author.find_by_id([author])
856
- assert_equal author, authors
857
- end
858
-
859
- def test_find_all_using_where_twice_should_or_the_relation
860
- david = authors(:david)
861
- relation = Author.unscoped
862
- relation = relation.where(:name => david.name)
863
- relation = relation.where(:name => 'Santiago')
864
- relation = relation.where(:id => david.id)
865
- assert_equal [], relation.to_a
866
- end
867
-
868
- def test_multi_where_ands_queries
869
- relation = Author.unscoped
870
- david = authors(:david)
871
- sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
872
- assert_match('AND', sql)
873
- end
874
-
875
- def test_find_all_with_multiple_should_use_and
876
- david = authors(:david)
877
- relation = [
878
- { :name => david.name },
879
- { :name => 'Santiago' },
880
- { :name => 'tenderlove' },
881
- ].inject(Author.unscoped) do |memo, param|
882
- memo.where(param)
883
- end
884
- assert_equal [], relation.to_a
885
- end
886
-
887
- def test_typecasting_where_with_array
888
- ids = Author.pluck(:id)
889
- slugs = ids.map { |id| "#{id}-as-a-slug" }
890
-
891
- assert_equal Author.all.to_a, Author.where(id: slugs).to_a
892
- end
893
-
894
- def test_find_all_using_where_with_relation
895
- david = authors(:david)
896
- # switching the lines below would succeed in current rails
897
- # assert_queries(2) {
898
- assert_queries(1) {
899
- relation = Author.where(:id => Author.where(:id => david.id))
900
- assert_equal [david], relation.to_a
901
- }
902
-
903
- assert_queries(1) {
904
- relation = Author.where('id in (?)', Author.where(id: david).select(:id))
905
- assert_equal [david], relation.to_a
906
- }
907
-
908
- assert_queries(1) do
909
- relation = Author.where('id in (:author_ids)', author_ids: Author.where(id: david).select(:id))
910
- assert_equal [david], relation.to_a
911
- end
912
- end
913
-
914
- def test_find_all_using_where_with_relation_with_bound_values
915
- david = authors(:david)
916
- davids_posts = david.posts.order(:id).to_a
917
-
918
- assert_queries(1) do
919
- relation = Post.where(id: david.posts.select(:id))
920
- assert_equal davids_posts, relation.order(:id).to_a
921
- end
922
-
923
- 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'
926
- end
927
-
928
- 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'
931
- end
932
- end
933
-
934
- def test_find_all_using_where_with_relation_and_alternate_primary_key
935
- cool_first = minivans(:cool_first)
936
- # switching the lines below would succeed in current rails
937
- # assert_queries(2) {
938
- assert_queries(1) {
939
- relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
940
- assert_equal [cool_first], relation.to_a
941
- }
942
- end
943
-
944
- def test_find_all_using_where_with_relation_does_not_alter_select_values
945
- david = authors(:david)
946
-
947
- subquery = Author.where(:id => david.id)
948
-
949
- assert_queries(1) {
950
- relation = Author.where(:id => subquery)
951
- assert_equal [david], relation.to_a
952
- }
953
-
954
- assert_equal 0, subquery.select_values.size
955
- end
956
-
957
- def test_find_all_using_where_with_relation_with_joins
958
- david = authors(:david)
959
- assert_queries(1) {
960
- relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
961
- assert_equal [david], relation.to_a
962
- }
963
- end
964
-
965
-
966
- def test_find_all_using_where_with_relation_with_select_to_build_subquery
967
- david = authors(:david)
968
- assert_queries(1) {
969
- relation = Author.where(:name => Author.where(:id => david.id).select(:name))
970
- assert_equal [david], relation.to_a
971
- }
972
- end
973
-
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
- def test_last
1001
- authors = Author.all
1002
- assert_equal authors(:bob), authors.last
1003
- end
1004
-
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
- def test_select_with_aggregates
1059
- posts = Post.select(:title, :body)
1060
-
1061
- assert_equal 11, posts.count(:all)
1062
- assert_equal 11, posts.size
1063
- assert posts.any?
1064
- assert posts.many?
1065
- assert_not posts.empty?
1066
- end
1067
-
1068
- def test_select_takes_a_variable_list_of_args
1069
- david = developers(:david)
1070
-
1071
- developer = Developer.where(id: david.id).select(:name, :salary).first
1072
- assert_equal david.name, developer.name
1073
- assert_equal david.salary, developer.salary
1074
- end
1075
-
1076
- def test_select_takes_an_aliased_attribute
1077
- first = topics(:first)
1078
-
1079
- topic = Topic.where(id: first.id).select(:heading).first
1080
- assert_equal first.heading, topic.heading
1081
- end
1082
-
1083
- def test_select_argument_error
1084
- assert_raises(ArgumentError) { Developer.select }
1085
- end
1086
-
1087
- def test_count
1088
- posts = Post.all
1089
-
1090
- assert_equal 11, posts.count
1091
- assert_equal 11, posts.count(:all)
1092
- assert_equal 11, posts.count(:id)
1093
-
1094
- assert_equal 1, posts.where('comments_count > 1').count
1095
- assert_equal 9, posts.where(:comments_count => 0).count
1096
- end
1097
-
1098
- def test_count_on_association_relation
1099
- author = Author.last
1100
- another_author = Author.first
1101
- posts = Post.where(author_id: author.id)
1102
-
1103
- assert_equal author.posts.where(author_id: author.id).size, posts.count
1104
-
1105
- assert_equal 0, author.posts.where(author_id: another_author.id).size
1106
- assert author.posts.where(author_id: another_author.id).empty?
1107
- end
1108
-
1109
- def test_count_with_distinct
1110
- posts = Post.all
1111
-
1112
- assert_equal 3, posts.distinct(true).count(:comments_count)
1113
- assert_equal 11, posts.distinct(false).count(:comments_count)
1114
-
1115
- assert_equal 3, posts.distinct(true).select(:comments_count).count
1116
- assert_equal 11, posts.distinct(false).select(:comments_count).count
1117
- end
1118
-
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 }
1125
- end
1126
-
1127
- def test_count_explicit_columns
1128
- Post.update_all(:comments_count => nil)
1129
- posts = Post.all
1130
-
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
1133
-
1134
- assert_equal 11, posts.select('comments_count').count('id')
1135
- assert_equal 0, posts.select('comments_count').count
1136
- assert_equal 0, posts.count(:comments_count)
1137
- assert_equal 0, posts.count('comments_count')
1138
- end
1139
-
1140
- def test_multiple_selects
1141
- post = Post.all.select('comments_count').select('title').order("id ASC").first
1142
- assert_equal "Welcome to the weblog", post.title
1143
- assert_equal 2, post.comments_count
1144
- end
1145
-
1146
- def test_size
1147
- posts = Post.all
1148
-
1149
- assert_queries(1) { assert_equal 11, posts.size }
1150
- assert ! posts.loaded?
1151
-
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 }
1155
- end
1156
-
1157
- def test_size_with_limit
1158
- posts = Post.limit(10)
1159
-
1160
- assert_queries(1) { assert_equal 10, posts.size }
1161
- assert ! posts.loaded?
1162
-
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 }
1166
- end
1167
-
1168
- def test_size_with_zero_limit
1169
- posts = Post.limit(0)
1170
-
1171
- assert_no_queries { assert_equal 0, posts.size }
1172
- assert ! posts.loaded?
1173
-
1174
- posts.to_a # force load
1175
- assert_no_queries { assert_equal 0, posts.size }
1176
- end
1177
-
1178
- def test_empty_with_zero_limit
1179
- posts = Post.limit(0)
1180
-
1181
- assert_no_queries { assert_equal true, posts.empty? }
1182
- assert ! posts.loaded?
1183
- end
1184
-
1185
- def test_count_complex_chained_relations
1186
- posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
1187
-
1188
- expected = { 1 => 2 }
1189
- assert_equal expected, posts.count
1190
- end
1191
-
1192
- def test_empty
1193
- posts = Post.all
1194
-
1195
- assert_queries(1) { assert_equal false, posts.empty? }
1196
- assert ! posts.loaded?
1197
-
1198
- no_posts = posts.where(:title => "")
1199
- assert_queries(1) { assert_equal true, no_posts.empty? }
1200
- assert ! no_posts.loaded?
1201
-
1202
- best_posts = posts.where(:comments_count => 0)
1203
- best_posts.to_a # force load
1204
- assert_no_queries { assert_equal false, best_posts.empty? }
1205
- end
1206
-
1207
- def test_empty_complex_chained_relations
1208
- posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
1209
-
1210
- assert_queries(1) { assert_equal false, posts.empty? }
1211
- assert ! posts.loaded?
1212
-
1213
- no_posts = posts.where(:title => "")
1214
- assert_queries(1) { assert_equal true, no_posts.empty? }
1215
- assert ! no_posts.loaded?
1216
- end
1217
-
1218
- def test_any
1219
- posts = Post.all
1220
-
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
- assert_queries(3) do
1230
- assert posts.any? # Uses COUNT()
1231
- assert ! posts.where(:id => nil).any?
1232
-
1233
- assert posts.any? {|p| p.id > 0 }
1234
- assert ! posts.any? {|p| p.id <= 0 }
1235
- end
1236
-
1237
- assert posts.loaded?
1238
- end
1239
-
1240
- def test_many
1241
- posts = Post.all
1242
-
1243
- assert_queries(2) do
1244
- assert posts.many? # Uses COUNT()
1245
- assert posts.many? {|p| p.id > 0 }
1246
- assert ! posts.many? {|p| p.id < 2 }
1247
- end
1248
-
1249
- assert posts.loaded?
1250
- end
1251
-
1252
- def test_many_with_limits
1253
- posts = Post.all
1254
-
1255
- assert posts.many?
1256
- assert ! posts.limit(1).many?
1257
- end
1258
-
1259
- def test_none?
1260
- posts = Post.all
1261
- assert_queries(1) do
1262
- assert ! posts.none? # Uses COUNT()
1263
- end
1264
-
1265
- assert ! posts.loaded?
1266
-
1267
- assert_queries(1) do
1268
- assert posts.none? {|p| p.id < 0 }
1269
- assert ! posts.none? {|p| p.id == 1 }
1270
- end
1271
-
1272
- assert posts.loaded?
1273
- end
1274
-
1275
- def test_one
1276
- posts = Post.all
1277
- assert_queries(1) do
1278
- assert ! posts.one? # Uses COUNT()
1279
- end
1280
-
1281
- assert ! posts.loaded?
1282
-
1283
- assert_queries(1) do
1284
- assert ! posts.one? {|p| p.id < 3 }
1285
- assert posts.one? {|p| p.id == 1 }
1286
- end
1287
-
1288
- assert posts.loaded?
1289
- end
1290
-
1291
- def test_to_a_should_dup_target
1292
- posts = Post.all
1293
-
1294
- original_size = posts.size
1295
- removed = posts.to_a.pop
1296
-
1297
- assert_equal original_size, posts.size
1298
- assert_includes posts.to_a, removed
1299
- end
1300
-
1301
- def test_build
1302
- posts = Post.all
1303
-
1304
- post = posts.new
1305
- assert_kind_of Post, post
1306
- end
1307
-
1308
- def test_scoped_build
1309
- posts = Post.where(:title => 'You told a lie')
1310
-
1311
- post = posts.new
1312
- assert_kind_of Post, post
1313
- assert_equal 'You told a lie', post.title
1314
- end
1315
-
1316
- def test_create
1317
- birds = Bird.all
1318
-
1319
- sparrow = birds.create
1320
- assert_kind_of Bird, sparrow
1321
- assert !sparrow.persisted?
1322
-
1323
- hen = birds.where(:name => 'hen').create
1324
- assert hen.persisted?
1325
- assert_equal 'hen', hen.name
1326
- end
1327
-
1328
- def test_create_bang
1329
- birds = Bird.all
1330
-
1331
- assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
1332
-
1333
- hen = birds.where(:name => 'hen').create!
1334
- assert_kind_of Bird, hen
1335
- assert hen.persisted?
1336
- assert_equal 'hen', hen.name
1337
- end
1338
-
1339
- def test_first_or_create
1340
- parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
1341
- assert_kind_of Bird, parrot
1342
- assert parrot.persisted?
1343
- assert_equal 'parrot', parrot.name
1344
- assert_equal 'green', parrot.color
1345
-
1346
- same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
1347
- assert_kind_of Bird, same_parrot
1348
- assert same_parrot.persisted?
1349
- assert_equal parrot, same_parrot
1350
- end
1351
-
1352
- def test_first_or_create_with_no_parameters
1353
- parrot = Bird.where(:color => 'green').first_or_create
1354
- assert_kind_of Bird, parrot
1355
- assert !parrot.persisted?
1356
- assert_equal 'green', parrot.color
1357
- end
1358
-
1359
- def test_first_or_create_with_block
1360
- parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
1361
- assert_kind_of Bird, parrot
1362
- assert parrot.persisted?
1363
- assert_equal 'green', parrot.color
1364
- assert_equal 'parrot', parrot.name
1365
-
1366
- same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
1367
- assert_equal parrot, same_parrot
1368
- end
1369
-
1370
- def test_first_or_create_with_array
1371
- several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
1372
- assert_kind_of Array, several_green_birds
1373
- several_green_birds.each { |bird| assert bird.persisted? }
1374
-
1375
- same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
1376
- assert_kind_of Bird, same_parrot
1377
- assert_equal several_green_birds.first, same_parrot
1378
- end
1379
-
1380
- def test_first_or_create_bang_with_valid_options
1381
- parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
1382
- assert_kind_of Bird, parrot
1383
- assert parrot.persisted?
1384
- assert_equal 'parrot', parrot.name
1385
- assert_equal 'green', parrot.color
1386
-
1387
- same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
1388
- assert_kind_of Bird, same_parrot
1389
- assert same_parrot.persisted?
1390
- assert_equal parrot, same_parrot
1391
- end
1392
-
1393
- def test_first_or_create_bang_with_invalid_options
1394
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
1395
- end
1396
-
1397
- def test_first_or_create_bang_with_no_parameters
1398
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
1399
- end
1400
-
1401
- def test_first_or_create_bang_with_valid_block
1402
- parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
1403
- assert_kind_of Bird, parrot
1404
- assert parrot.persisted?
1405
- assert_equal 'green', parrot.color
1406
- assert_equal 'parrot', parrot.name
1407
-
1408
- same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
1409
- assert_equal parrot, same_parrot
1410
- end
1411
-
1412
- def test_first_or_create_bang_with_invalid_block
1413
- assert_raise(ActiveRecord::RecordInvalid) do
1414
- Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
1415
- end
1416
- end
1417
-
1418
- def test_first_or_create_with_valid_array
1419
- several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
1420
- assert_kind_of Array, several_green_birds
1421
- several_green_birds.each { |bird| assert bird.persisted? }
1422
-
1423
- same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
1424
- assert_kind_of Bird, same_parrot
1425
- assert_equal several_green_birds.first, same_parrot
1426
- end
1427
-
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} ]) }
1430
- end
1431
-
1432
- def test_first_or_initialize
1433
- parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
1434
- 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
1440
- end
1441
-
1442
- def test_first_or_initialize_with_no_parameters
1443
- parrot = Bird.where(:color => 'green').first_or_initialize
1444
- assert_kind_of Bird, parrot
1445
- assert !parrot.persisted?
1446
- assert !parrot.valid?
1447
- assert parrot.new_record?
1448
- assert_equal 'green', parrot.color
1449
- end
1450
-
1451
- def test_first_or_initialize_with_block
1452
- parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
1453
- 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
1459
- end
1460
-
1461
- def test_find_or_create_by
1462
- assert_nil Bird.find_by(name: 'bob')
1463
-
1464
- bird = Bird.find_or_create_by(name: 'bob')
1465
- assert bird.persisted?
1466
-
1467
- assert_equal bird, Bird.find_or_create_by(name: 'bob')
1468
- end
1469
-
1470
- def test_find_or_create_by_with_create_with
1471
- assert_nil Bird.find_by(name: 'bob')
1472
-
1473
- bird = Bird.create_with(color: 'green').find_or_create_by(name: 'bob')
1474
- assert bird.persisted?
1475
- assert_equal 'green', bird.color
1476
-
1477
- assert_equal bird, Bird.create_with(color: 'blue').find_or_create_by(name: 'bob')
1478
- end
1479
-
1480
- def test_find_or_create_by!
1481
- assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: 'green') }
1482
- end
1483
-
1484
- def test_find_or_initialize_by
1485
- assert_nil Bird.find_by(name: 'bob')
1486
-
1487
- bird = Bird.find_or_initialize_by(name: 'bob')
1488
- assert bird.new_record?
1489
- bird.save!
1490
-
1491
- assert_equal bird, Bird.find_or_initialize_by(name: 'bob')
1492
- end
1493
-
1494
- def test_explicit_create_scope
1495
- hens = Bird.where(:name => 'hen')
1496
- assert_equal 'hen', hens.new.name
1497
-
1498
- hens = hens.create_with(:name => 'cock')
1499
- assert_equal 'cock', hens.new.name
1500
- end
1501
-
1502
- def test_except
1503
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1504
- assert_equal [posts(:welcome)], relation.to_a
1505
-
1506
- author_posts = relation.except(:order, :limit)
1507
- assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1508
-
1509
- all_posts = relation.except(:where, :order, :limit)
1510
- assert_equal Post.all, all_posts
1511
- end
1512
-
1513
- def test_only
1514
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1515
- assert_equal [posts(:welcome)], relation.to_a
1516
-
1517
- author_posts = relation.only(:where)
1518
- assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1519
-
1520
- all_posts = relation.only(:limit)
1521
- assert_equal Post.limit(1).to_a.first, all_posts.first
1522
- end
1523
-
1524
- def test_anonymous_extension
1525
- relation = Post.where(:author_id => 1).order('id ASC').extending do
1526
- def author
1527
- 'lifo'
1528
- end
1529
- end
1530
-
1531
- assert_equal "lifo", relation.author
1532
- assert_equal "lifo", relation.limit(1).author
1533
- end
1534
-
1535
- def test_named_extension
1536
- relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
1537
- assert_equal "lifo", relation.author
1538
- assert_equal "lifo", relation.limit(1).author
1539
- end
1540
-
1541
- def test_order_by_relation_attribute
1542
- assert_equal Post.order(Post.arel_table[:title]).to_a, Post.order("title").to_a
1543
- end
1544
-
1545
- 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
1548
- end
1549
-
1550
- def test_order_using_scoping
1551
- car1 = CoolCar.order('id DESC').scoping do
1552
- CoolCar.all.merge!(order: 'id asc').first
1553
- end
1554
- assert_equal 'zyke', car1.name
1555
-
1556
- car2 = FastCar.order('id DESC').scoping do
1557
- FastCar.all.merge!(order: 'id asc').first
1558
- end
1559
- assert_equal 'zyke', car2.name
1560
- end
1561
-
1562
- 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}
1565
- end
1566
-
1567
- def test_intersection_with_array
1568
- relation = Author.where(:name => "David")
1569
- rails_author = relation.first
1570
-
1571
- assert_equal [rails_author], [rails_author] & relation
1572
- assert_equal [rails_author], relation & [rails_author]
1573
- end
1574
-
1575
- def test_primary_key
1576
- assert_equal "id", Post.all.primary_key
1577
- end
1578
-
1579
- 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
1643
- end
1644
-
1645
- def test_distinct
1646
- tag1 = Tag.create(:name => 'Foo')
1647
- tag2 = Tag.create(:name => 'Foo')
1648
-
1649
- query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
1650
-
1651
- assert_equal ['Foo', 'Foo'], query.map(&:name)
1652
- assert_sql(/DISTINCT/) do
1653
- assert_equal ['Foo'], query.distinct.map(&:name)
1654
- assert_deprecated { assert_equal ['Foo'], query.uniq.map(&:name) }
1655
- end
1656
- 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)
1664
- end
1665
- end
1666
-
1667
- def test_doesnt_add_having_values_if_options_are_blank
1668
- scope = Post.having('')
1669
- assert scope.having_clause.empty?
1670
-
1671
- scope = Post.having([])
1672
- assert scope.having_clause.empty?
1673
- end
1674
-
1675
- def test_having_with_binds_for_both_where_and_having
1676
- 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)
1679
-
1680
- assert_equal [post], having_then_where
1681
- assert_equal [post], where_then_having
1682
- end
1683
-
1684
- def test_multiple_where_and_having_clauses
1685
- post = Post.first
1686
- having_then_where = Post.having(id: post.id).where(title: post.title)
1687
- .having(id: post.id).where(title: post.title).group(:id)
1688
-
1689
- assert_equal [post], having_then_where
1690
- end
1691
-
1692
- def test_grouping_by_column_with_reserved_name
1693
- assert_equal [], Possession.select(:where).group(:where).to_a
1694
- end
1695
-
1696
- def test_references_triggers_eager_loading
1697
- scope = Post.includes(:comments)
1698
- assert !scope.eager_loading?
1699
- assert scope.references(:comments).eager_loading?
1700
- end
1701
-
1702
- def test_references_doesnt_trigger_eager_loading_if_reference_not_included
1703
- scope = Post.references(:comments)
1704
- assert !scope.eager_loading?
1705
- end
1706
-
1707
- def test_automatically_added_where_references
1708
- scope = Post.where(:comments => { :body => "Bla" })
1709
- assert_equal ['comments'], scope.references_values
1710
-
1711
- scope = Post.where('comments.body' => 'Bla')
1712
- assert_equal ['comments'], scope.references_values
1713
- end
1714
-
1715
- def test_automatically_added_where_not_references
1716
- scope = Post.where.not(comments: { body: "Bla" })
1717
- assert_equal ['comments'], scope.references_values
1718
-
1719
- scope = Post.where.not('comments.body' => 'Bla')
1720
- assert_equal ['comments'], scope.references_values
1721
- end
1722
-
1723
- def test_automatically_added_having_references
1724
- scope = Post.having(:comments => { :body => "Bla" })
1725
- assert_equal ['comments'], scope.references_values
1726
-
1727
- scope = Post.having('comments.body' => 'Bla')
1728
- assert_equal ['comments'], scope.references_values
1729
- end
1730
-
1731
- def test_automatically_added_order_references
1732
- scope = Post.order('comments.body')
1733
- assert_equal ['comments'], scope.references_values
1734
-
1735
- scope = Post.order('comments.body', 'yaks.body')
1736
- assert_equal ['comments', 'yaks'], scope.references_values
1737
-
1738
- # 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
1741
-
1742
- scope = Post.order('comments.body asc')
1743
- assert_equal ['comments'], scope.references_values
1744
-
1745
- scope = Post.order('foo(comments.body)')
1746
- assert_equal [], scope.references_values
1747
- end
1748
-
1749
- def test_automatically_added_reorder_references
1750
- scope = Post.reorder('comments.body')
1751
- assert_equal %w(comments), scope.references_values
1752
-
1753
- scope = Post.reorder('comments.body', 'yaks.body')
1754
- assert_equal %w(comments yaks), scope.references_values
1755
-
1756
- # Don't infer yaks, let's not go down that road again...
1757
- scope = Post.reorder('comments.body, yaks.body')
1758
- assert_equal %w(comments), scope.references_values
1759
-
1760
- scope = Post.reorder('comments.body asc')
1761
- assert_equal %w(comments), scope.references_values
1762
-
1763
- scope = Post.reorder('foo(comments.body)')
1764
- assert_equal [], scope.references_values
1765
- end
1766
-
1767
- def test_order_with_reorder_nil_removes_the_order
1768
- relation = Post.order(:title).reorder(nil)
1769
-
1770
- assert_nil relation.order_values.first
1771
- end
1772
-
1773
- def test_reverse_order_with_reorder_nil_removes_the_order
1774
- relation = Post.order(:title).reverse_order.reorder(nil)
1775
-
1776
- assert_nil relation.order_values.first
1777
- end
1778
-
1779
- def test_presence
1780
- topics = Topic.all
1781
-
1782
- # the first query is triggered because there are no topics yet.
1783
- assert_queries(1) { assert topics.present? }
1784
-
1785
- # checking if there are topics is used before you actually display them,
1786
- # thus it shouldn't invoke an extra count query.
1787
- assert_no_queries { assert topics.present? }
1788
- assert_no_queries { assert !topics.blank? }
1789
-
1790
- # shows count of topics and loops after loading the query should not trigger extra queries either.
1791
- assert_no_queries { topics.size }
1792
- assert_no_queries { topics.length }
1793
- assert_no_queries { topics.each }
1794
-
1795
- # count always trigger the COUNT query.
1796
- assert_queries(1) { topics.count }
1797
-
1798
- assert topics.loaded?
1799
- end
1800
-
1801
- test "find_by with hash conditions returns the first matching record" do
1802
- assert_equal posts(:eager_other), Post.order(:id).find_by(author_id: 2)
1803
- end
1804
-
1805
- test "find_by with non-hash conditions returns the first matching record" do
1806
- assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = 2")
1807
- end
1808
-
1809
- 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)
1811
- end
1812
-
1813
- test "find_by returns nil if the record is missing" do
1814
- assert_equal nil, Post.all.find_by("1 = 0")
1815
- end
1816
-
1817
- test "find_by doesn't have implicit ordering" do
1818
- assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
1819
- end
1820
-
1821
- test "find_by requires at least one argument" do
1822
- assert_raises(ArgumentError) { Post.all.find_by }
1823
- end
1824
-
1825
- test "find_by! with hash conditions returns the first matching record" do
1826
- assert_equal posts(:eager_other), Post.order(:id).find_by!(author_id: 2)
1827
- end
1828
-
1829
- test "find_by! with non-hash conditions returns the first matching record" do
1830
- assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = 2")
1831
- end
1832
-
1833
- 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)
1835
- end
1836
-
1837
- test "find_by! doesn't have implicit ordering" do
1838
- assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
1839
- end
1840
-
1841
- test "find_by! raises RecordNotFound if the record is missing" do
1842
- assert_raises(ActiveRecord::RecordNotFound) do
1843
- Post.all.find_by!("1 = 0")
1844
- end
1845
- end
1846
-
1847
- test "find_by! requires at least one argument" do
1848
- assert_raises(ArgumentError) { Post.all.find_by! }
1849
- end
1850
-
1851
- test "loaded relations cannot be mutated by multi value methods" do
1852
- relation = Post.all
1853
- relation.to_a
1854
-
1855
- assert_raises(ActiveRecord::ImmutableRelation) do
1856
- relation.where! 'foo'
1857
- end
1858
- end
1859
-
1860
- test "loaded relations cannot be mutated by single value methods" do
1861
- relation = Post.all
1862
- relation.to_a
1863
-
1864
- assert_raises(ActiveRecord::ImmutableRelation) do
1865
- relation.limit! 5
1866
- end
1867
- end
1868
-
1869
- test "loaded relations cannot be mutated by merge!" do
1870
- relation = Post.all
1871
- relation.to_a
1872
-
1873
- assert_raises(ActiveRecord::ImmutableRelation) do
1874
- relation.merge! where: 'foo'
1875
- end
1876
- end
1877
-
1878
- test "loaded relations cannot be mutated by extending!" do
1879
- relation = Post.all
1880
- relation.to_a
1881
-
1882
- assert_raises(ActiveRecord::ImmutableRelation) do
1883
- relation.extending! Module.new
1884
- end
1885
- end
1886
-
1887
- test "relations with cached arel can't be mutated [internal API]" do
1888
- relation = Post.all
1889
- relation.count
1890
-
1891
- assert_raises(ActiveRecord::ImmutableRelation) { relation.limit!(5) }
1892
- assert_raises(ActiveRecord::ImmutableRelation) { relation.where!("1 = 2") }
1893
- end
1894
-
1895
- test "relations show the records in #inspect" do
1896
- relation = Post.limit(2)
1897
- assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
1898
- end
1899
-
1900
- test "relations limit the records in #inspect at 10" do
1901
- relation = Post.limit(11)
1902
- assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
1903
- end
1904
-
1905
- test "already-loaded relations don't perform a new query in #inspect" do
1906
- relation = Post.limit(2)
1907
- relation.to_a
1908
-
1909
- expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>"
1910
-
1911
- assert_no_queries do
1912
- assert_equal expected, relation.inspect
1913
- end
1914
- end
1915
-
1916
- test 'using a custom table affects the wheres' do
1917
- table_alias = Post.arel_table.alias('omg_posts')
1918
-
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")
1923
-
1924
- node = relation.arel.constraints.first.grep(Arel::Attributes::Attribute).first
1925
- assert_equal table_alias, node.relation
1926
- end
1927
-
1928
- test '#load' do
1929
- relation = Post.all
1930
- assert_queries(1) do
1931
- assert_equal relation, relation.load
1932
- end
1933
- assert_no_queries { relation.to_a }
1934
- end
1935
-
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
1939
-
1940
- assert_no_queries do
1941
- result = authors_count.map do |post|
1942
- [post.num_posts, post.author.try(:name)]
1943
- end
1944
-
1945
- expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
1946
- assert_equal expected, result
1947
- end
1948
- end
1949
-
1950
- test "joins with select" do
1951
- posts = Post.joins(:author).select("id", "authors.author_address_id").order("posts.id").limit(3)
1952
- assert_equal [1, 2, 4], posts.map(&:id)
1953
- assert_equal [1, 1, 1], posts.map(&:author_address_id)
1954
- end
1955
-
1956
- test "delegations do not leak to other classes" do
1957
- Topic.all.by_lifo
1958
- assert Topic.all.class.method_defined?(:by_lifo)
1959
- assert !Post.all.respond_to?(:by_lifo)
1960
- end
1961
-
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]]
1966
-
1967
- relation = left.unscope(where: :id)
1968
- assert_equal [], relation.bind_values
1969
- end
1970
-
1971
- def test_merging_removes_rhs_bind_parameters
1972
- left = Post.where(id: 20)
1973
- right = Post.where(id: [1,2,3,4])
1974
-
1975
- merged = left.merge(right)
1976
- assert_equal [], merged.bind_values
1977
- end
1978
-
1979
- def test_merging_keeps_lhs_bind_parameters
1980
- binds = [ActiveRecord::Relation::QueryAttribute.new("id", 20, Post.type_for_attribute("id"))]
1981
-
1982
- right = Post.where(id: 20)
1983
- left = Post.where(id: 10)
1984
-
1985
- merged = left.merge(right)
1986
- assert_equal binds, merged.bound_attributes
1987
- end
1988
-
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)
1993
-
1994
- merged = left.merge(right)
1995
- assert_equal post, merged.first
1996
- end
1997
-
1998
- def test_relation_join_method
1999
- assert_equal 'Thank you for the welcome,Thank you again for the welcome', Post.first.comments.join(",")
2000
- end
2001
-
2002
- def test_connection_adapters_can_reorder_binds
2003
- posts = Post.limit(1).offset(2)
2004
-
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)
2011
- end
2012
-
2013
- posts.define_singleton_method(:connection) do
2014
- stubbed_connection
2015
- end
2016
-
2017
- assert_equal 2, posts.to_a.length
2018
- end
2019
-
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 })
2024
- end
2025
- end
2026
- end
1
+ 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'
19
+ require "models/possession"
20
+ require "models/reader"
21
+ require "models/categorization"
22
+ require "models/edge"
23
+
24
+ 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
32
+
33
+ def test_do_not_double_quote_string_id
34
+ van = Minivan.last
35
+ assert van
36
+ assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id
37
+ end
38
+
39
+ def test_do_not_double_quote_string_id_with_array
40
+ van = Minivan.last
41
+ assert van
42
+ assert_equal van, Minivan.where(:minivan_id => [van]).to_a.first
43
+ end
44
+
45
+ def test_two_scopes_with_includes_should_not_drop_any_include
46
+ # heat habtm cache
47
+ car = Car.incl_engines.incl_tyres.first
48
+ car.tyres.length
49
+ car.engines.length
50
+
51
+ car = Car.incl_engines.incl_tyres.first
52
+ assert_no_queries { car.tyres.length }
53
+ assert_no_queries { car.engines.length }
54
+ end
55
+
56
+ def test_dynamic_finder
57
+ x = Post.where('author_id = ?', 1)
58
+ assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders'
59
+ end
60
+
61
+ def test_multivalue_where
62
+ posts = Post.where('author_id = ? AND id = ?', 1, 1)
63
+ assert_equal 1, posts.to_a.size
64
+ end
65
+
66
+ def test_scoped
67
+ topics = Topic.all
68
+ assert_kind_of ActiveRecord::Relation, topics
69
+ assert_equal 5, topics.size
70
+ end
71
+
72
+ def test_to_json
73
+ assert_nothing_raised { Bird.all.to_json }
74
+ assert_nothing_raised { Bird.all.to_a.to_json }
75
+ end
76
+
77
+ def test_to_yaml
78
+ assert_nothing_raised { Bird.all.to_yaml }
79
+ assert_nothing_raised { Bird.all.to_a.to_yaml }
80
+ end
81
+
82
+ def test_to_xml
83
+ assert_nothing_raised { Bird.all.to_xml }
84
+ assert_nothing_raised { Bird.all.to_a.to_xml }
85
+ end
86
+
87
+ def test_scoped_all
88
+ topics = Topic.all.to_a
89
+ assert_kind_of Array, topics
90
+ assert_no_queries { assert_equal 5, topics.size }
91
+ end
92
+
93
+ def test_loaded_all
94
+ topics = Topic.all
95
+
96
+ assert_queries(1) do
97
+ 2.times { assert_equal 5, topics.to_a.size }
98
+ end
99
+
100
+ assert topics.loaded?
101
+ end
102
+
103
+ def test_scoped_first
104
+ topics = Topic.all.order('id ASC')
105
+
106
+ assert_queries(1) do
107
+ 2.times { assert_equal "The First Topic", topics.first.title }
108
+ end
109
+
110
+ assert ! topics.loaded?
111
+ end
112
+
113
+ def test_loaded_first
114
+ topics = Topic.all.order('id ASC')
115
+ topics.to_a # force load
116
+
117
+ assert_no_queries do
118
+ assert_equal "The First Topic", topics.first.title
119
+ end
120
+
121
+ assert topics.loaded?
122
+ end
123
+
124
+ def test_loaded_first_with_limit
125
+ topics = Topic.all.order('id ASC')
126
+ topics.to_a # force load
127
+
128
+ assert_no_queries do
129
+ assert_equal ["The First Topic",
130
+ "The Second Topic of the day"], topics.first(2).map(&:title)
131
+ end
132
+
133
+ assert topics.loaded?
134
+ end
135
+
136
+ def test_first_get_more_than_available
137
+ topics = Topic.all.order('id ASC')
138
+ unloaded_first = topics.first(10)
139
+ topics.to_a # force load
140
+
141
+ assert_no_queries do
142
+ loaded_first = topics.first(10)
143
+ assert_equal unloaded_first, loaded_first
144
+ end
145
+ end
146
+
147
+ def test_reload
148
+ topics = Topic.all
149
+
150
+ assert_queries(1) do
151
+ 2.times { topics.to_a }
152
+ end
153
+
154
+ assert topics.loaded?
155
+
156
+ original_size = topics.to_a.size
157
+ Topic.create! :title => 'fake'
158
+
159
+ assert_queries(1) { topics.reload }
160
+ assert_equal original_size + 1, topics.size
161
+ assert topics.loaded?
162
+ end
163
+
164
+ 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
+ end
170
+
171
+ def test_finding_with_subquery_with_binds
172
+ 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
176
+ end
177
+
178
+ def test_finding_with_subquery_without_select_does_not_change_the_select
179
+ relation = Topic.where(approved: true)
180
+ assert_raises(ActiveRecord::StatementInvalid) do
181
+ Topic.from(relation).to_a
182
+ end
183
+ end
184
+
185
+ 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)
189
+ end
190
+
191
+ 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)
195
+ end
196
+
197
+ 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)
201
+ end
202
+
203
+ def test_finding_with_order
204
+ topics = Topic.order('id')
205
+ assert_equal 5, topics.to_a.size
206
+ assert_equal topics(:first).title, topics.first.title
207
+ end
208
+
209
+ def test_finding_with_arel_order
210
+ topics = Topic.order(Topic.arel_table[:id].asc)
211
+ assert_equal 5, topics.to_a.size
212
+ assert_equal topics(:first).title, topics.first.title
213
+ end
214
+
215
+ def test_finding_with_assoc_order
216
+ topics = Topic.order(:id => :desc)
217
+ assert_equal 5, topics.to_a.size
218
+ assert_equal topics(:fifth).title, topics.first.title
219
+ end
220
+
221
+ def test_finding_with_reverted_assoc_order
222
+ topics = Topic.order(:id => :asc).reverse_order
223
+ assert_equal 5, topics.to_a.size
224
+ assert_equal topics(:fifth).title, topics.first.title
225
+ end
226
+
227
+ def test_reverse_order_with_function
228
+ topics = Topic.order("length(title)").reverse_order
229
+ assert_equal topics(:second).title, topics.first.title
230
+ end
231
+
232
+ def test_reverse_order_with_function_other_predicates
233
+ topics = Topic.order("author_name, length(title), id").reverse_order
234
+ assert_equal topics(:second).title, topics.first.title
235
+ topics = Topic.order("length(author_name), id, length(title)").reverse_order
236
+ assert_equal topics(:fifth).title, topics.first.title
237
+ end
238
+
239
+ def test_reverse_order_with_multiargument_function
240
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
241
+ Topic.order("concat(author_name, title)").reverse_order
242
+ end
243
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
244
+ Topic.order("concat(lower(author_name), title)").reverse_order
245
+ end
246
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
247
+ Topic.order("concat(author_name, lower(title))").reverse_order
248
+ end
249
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
250
+ Topic.order("concat(lower(author_name), title, length(title)").reverse_order
251
+ end
252
+ end
253
+
254
+ def test_reverse_order_with_nulls_first_or_last
255
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
256
+ Topic.order("title NULLS FIRST").reverse_order
257
+ end
258
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
259
+ Topic.order("title nulls last").reverse_order
260
+ end
261
+ end
262
+
263
+ def test_default_reverse_order_on_table_without_primary_key
264
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
265
+ Edge.all.reverse_order
266
+ end
267
+ end
268
+
269
+ 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
271
+ end
272
+
273
+ def test_finding_with_desc_order_with_string
274
+ topics = Topic.order(id: "desc")
275
+ assert_equal 5, topics.to_a.size
276
+ assert_equal [topics(:fifth), topics(:fourth), topics(:third), topics(:second), topics(:first)], topics.to_a
277
+ end
278
+
279
+ def test_finding_with_asc_order_with_string
280
+ topics = Topic.order(id: 'asc')
281
+ assert_equal 5, topics.to_a.size
282
+ assert_equal [topics(:first), topics(:second), topics(:third), topics(:fourth), topics(:fifth)], topics.to_a
283
+ end
284
+
285
+ def test_support_upper_and_lower_case_directions
286
+ assert_includes Topic.order(id: "ASC").to_sql, "ASC"
287
+ assert_includes Topic.order(id: "asc").to_sql, "ASC"
288
+ assert_includes Topic.order(id: :ASC).to_sql, "ASC"
289
+ assert_includes Topic.order(id: :asc).to_sql, "ASC"
290
+
291
+ assert_includes Topic.order(id: "DESC").to_sql, "DESC"
292
+ assert_includes Topic.order(id: "desc").to_sql, "DESC"
293
+ assert_includes Topic.order(id: :DESC).to_sql, "DESC"
294
+ assert_includes Topic.order(id: :desc).to_sql,"DESC"
295
+ end
296
+
297
+ def test_raising_exception_on_invalid_hash_params
298
+ e = assert_raise(ArgumentError) { Topic.order(:name, "id DESC", id: :asfsdf) }
299
+ assert_equal 'Direction "asfsdf" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]', e.message
300
+ end
301
+
302
+ def test_finding_last_with_arel_order
303
+ topics = Topic.order(Topic.arel_table[:id].asc)
304
+ assert_equal topics(:fifth).title, topics.last.title
305
+ end
306
+
307
+ def test_finding_with_order_concatenated
308
+ topics = Topic.order('author_name').order('title')
309
+ assert_equal 5, topics.to_a.size
310
+ assert_equal topics(:fourth).title, topics.first.title
311
+ end
312
+
313
+ def test_finding_with_order_by_aliased_attributes
314
+ topics = Topic.order(:heading)
315
+ assert_equal 5, topics.to_a.size
316
+ assert_equal topics(:fifth).title, topics.first.title
317
+ end
318
+
319
+ def test_finding_with_assoc_order_by_aliased_attributes
320
+ topics = Topic.order(heading: :desc)
321
+ assert_equal 5, topics.to_a.size
322
+ assert_equal topics(:third).title, topics.first.title
323
+ end
324
+
325
+ def test_finding_with_reorder
326
+ topics = Topic.order('author_name').order('title').reorder('id').to_a
327
+ 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
329
+ end
330
+
331
+ def test_finding_with_reorder_by_aliased_attributes
332
+ topics = Topic.order('author_name').reorder(:heading)
333
+ assert_equal 5, topics.to_a.size
334
+ assert_equal topics(:fifth).title, topics.first.title
335
+ end
336
+
337
+ def test_finding_with_assoc_reorder_by_aliased_attributes
338
+ topics = Topic.order('author_name').reorder(heading: :desc)
339
+ assert_equal 5, topics.to_a.size
340
+ assert_equal topics(:third).title, topics.first.title
341
+ end
342
+
343
+ def test_finding_with_order_and_take
344
+ entrants = Entrant.order("id ASC").limit(2).to_a
345
+
346
+ assert_equal 2, entrants.size
347
+ assert_equal entrants(:first).name, entrants.first.name
348
+ end
349
+
350
+ def test_finding_with_cross_table_order_and_limit
351
+ tags = Tag.includes(:taggings).
352
+ order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
353
+ limit(1).to_a
354
+ assert_equal 1, tags.length
355
+ end
356
+
357
+ 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
359
+ assert_equal 1, tags.length
360
+ end
361
+
362
+ def test_finding_with_complex_order
363
+ tags = Tag.includes(:taggings).references(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
364
+ assert_equal 3, tags.length
365
+ end
366
+
367
+ def test_finding_with_sanitized_order
368
+ query = Tag.order(["field(id, ?)", [1,3,2]]).to_sql
369
+ assert_match(/field\(id, 1,3,2\)/, query)
370
+
371
+ query = Tag.order(["field(id, ?)", []]).to_sql
372
+ assert_match(/field\(id, NULL\)/, query)
373
+
374
+ query = Tag.order(["field(id, ?)", nil]).to_sql
375
+ assert_match(/field\(id, NULL\)/, query)
376
+ end
377
+
378
+ def test_finding_with_order_limit_and_offset
379
+ entrants = Entrant.order("id ASC").limit(2).offset(1)
380
+
381
+ assert_equal 2, entrants.to_a.size
382
+ assert_equal entrants(:second).name, entrants.first.name
383
+
384
+ entrants = Entrant.order("id ASC").limit(2).offset(2)
385
+ assert_equal 1, entrants.to_a.size
386
+ assert_equal entrants(:third).name, entrants.first.name
387
+ end
388
+
389
+ def test_finding_with_group
390
+ developers = Developer.group("salary").select("salary").to_a
391
+ assert_equal 4, developers.size
392
+ assert_equal 4, developers.map(&:salary).uniq.size
393
+ end
394
+
395
+ def test_select_with_block
396
+ even_ids = Developer.all.select {|d| d.id % 2 == 0 }.map(&:id)
397
+ assert_equal [2, 4, 6, 8, 10], even_ids.sort
398
+ end
399
+
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
+ def test_joins_with_nil_argument
518
+ assert_nothing_raised { DependentFirm.joins(nil).first }
519
+ end
520
+
521
+ def test_finding_with_hash_conditions_on_joined_table
522
+ firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
523
+ assert_equal 1, firms.size
524
+ assert_equal companies(:rails_core), firms.first
525
+ end
526
+
527
+ 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
530
+
531
+ assert_equal 3, developers_on_project_one.length
532
+ developer_names = developers_on_project_one.map(&:name)
533
+ assert developer_names.include?('David')
534
+ assert developer_names.include?('Jamis')
535
+ end
536
+
537
+ def test_find_on_hash_conditions
538
+ assert_equal Topic.all.merge!(:where => {:approved => false}).to_a, Topic.where({ :approved => false }).to_a
539
+ end
540
+
541
+ def test_joins_with_string_array
542
+ person_with_reader_and_post = Post.joins([
543
+ "INNER JOIN categorizations ON categorizations.post_id = posts.id",
544
+ "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
545
+ ]
546
+ ).to_a
547
+ assert_equal 1, person_with_reader_and_post.size
548
+ end
549
+
550
+ def test_no_arguments_to_query_methods_raise_errors
551
+ assert_raises(ArgumentError) { Topic.references() }
552
+ assert_raises(ArgumentError) { Topic.includes() }
553
+ assert_raises(ArgumentError) { Topic.preload() }
554
+ assert_raises(ArgumentError) { Topic.group() }
555
+ assert_raises(ArgumentError) { Topic.reorder() }
556
+ end
557
+
558
+ def test_blank_like_arguments_to_query_methods_dont_raise_errors
559
+ assert_nothing_raised { Topic.references([]) }
560
+ assert_nothing_raised { Topic.includes([]) }
561
+ assert_nothing_raised { Topic.preload([]) }
562
+ assert_nothing_raised { Topic.group([]) }
563
+ 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
591
+ end
592
+
593
+ def test_respond_to_dynamic_finders
594
+ relation = Topic.all
595
+
596
+ ["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}"
598
+ end
599
+ end
600
+
601
+ def test_respond_to_class_methods_and_scopes
602
+ assert Topic.all.respond_to?(:by_lifo)
603
+ end
604
+
605
+ def test_find_with_readonly_option
606
+ Developer.all.each { |d| assert !d.readonly? }
607
+ Developer.all.readonly.each { |d| assert d.readonly? }
608
+ end
609
+
610
+ 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
613
+
614
+ assert_equal [authors(:david)], authors
615
+ assert_no_queries do
616
+ authors.first.posts.first.special_comments.first.post.special_comments
617
+ authors.first.posts.first.special_comments.first.post.very_special_comment
618
+ end
619
+ end
620
+
621
+ def test_find_with_preloaded_associations
622
+ assert_queries(2) do
623
+ posts = Post.preload(:comments).order('posts.id')
624
+ assert posts.first.comments.first
625
+ end
626
+
627
+ assert_queries(2) do
628
+ posts = Post.preload(:comments).order('posts.id')
629
+ assert posts.first.comments.first
630
+ end
631
+
632
+ assert_queries(2) do
633
+ posts = Post.preload(:author).order('posts.id')
634
+ assert posts.first.author
635
+ end
636
+
637
+ assert_queries(2) do
638
+ posts = Post.preload(:author).order('posts.id')
639
+ assert posts.first.author
640
+ end
641
+
642
+ assert_queries(3) do
643
+ posts = Post.preload(:author, :comments).order('posts.id')
644
+ assert posts.first.author
645
+ assert posts.first.comments.first
646
+ end
647
+ end
648
+
649
+ def test_preload_applies_to_all_chained_preloaded_scopes
650
+ assert_queries(3) do
651
+ post = Post.with_comments.with_tags.first
652
+ assert post
653
+ end
654
+ end
655
+
656
+ def test_find_with_included_associations
657
+ assert_queries(2) do
658
+ posts = Post.includes(:comments).order('posts.id')
659
+ assert posts.first.comments.first
660
+ end
661
+
662
+ assert_queries(2) do
663
+ posts = Post.all.includes(:comments).order('posts.id')
664
+ assert posts.first.comments.first
665
+ end
666
+
667
+ assert_queries(2) do
668
+ posts = Post.includes(:author).order('posts.id')
669
+ assert posts.first.author
670
+ end
671
+
672
+ assert_queries(3) do
673
+ posts = Post.includes(:author, :comments).order('posts.id')
674
+ assert posts.first.author
675
+ assert posts.first.comments.first
676
+ end
677
+ end
678
+
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
+ 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
692
+ end
693
+
694
+ def test_includes_with_select
695
+ query = Post.select('comments_count AS ranking').order('ranking').includes(:comments)
696
+ .where(comments: { id: 1 })
697
+
698
+ assert_equal ['comments_count AS ranking'], query.select_values
699
+ assert_equal 1, query.to_a.size
700
+ end
701
+
702
+ def test_preloading_with_associations_and_merges
703
+ post = Post.create! title: 'Uhuu', body: 'body'
704
+ reader = Reader.create! post_id: post.id, person_id: 1
705
+ comment = Comment.create! post_id: post.id, body: 'body'
706
+
707
+ assert !comment.respond_to?(:readers)
708
+
709
+ post_rel = Post.preload(:readers).joins(:readers).where(title: 'Uhuu')
710
+ result_comment = Comment.joins(:post).merge(post_rel).to_a.first
711
+ assert_equal comment, result_comment
712
+
713
+ assert_no_queries do
714
+ assert_equal post, result_comment.post
715
+ assert_equal [reader], result_comment.post.readers.to_a
716
+ end
717
+
718
+ post_rel = Post.includes(:readers).where(title: 'Uhuu')
719
+ result_comment = Comment.joins(:post).merge(post_rel).first
720
+ assert_equal comment, result_comment
721
+
722
+ assert_no_queries do
723
+ assert_equal post, result_comment.post
724
+ assert_equal [reader], result_comment.post.readers.to_a
725
+ end
726
+ end
727
+
728
+ def test_preloading_with_associations_default_scopes_and_merges
729
+ post = Post.create! title: 'Uhuu', body: 'body'
730
+ reader = Reader.create! post_id: post.id, person_id: 1
731
+
732
+ post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: 'Uhuu')
733
+ result_post = PostWithPreloadDefaultScope.all.merge(post_rel).to_a.first
734
+
735
+ assert_no_queries do
736
+ assert_equal [reader], result_post.readers.to_a
737
+ end
738
+
739
+ post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: 'Uhuu')
740
+ result_post = PostWithIncludesDefaultScope.all.merge(post_rel).to_a.first
741
+
742
+ assert_no_queries do
743
+ assert_equal [reader], result_post.readers.to_a
744
+ end
745
+ end
746
+
747
+ def test_loading_with_one_association
748
+ posts = Post.preload(:comments)
749
+ post = posts.find { |p| p.id == 1 }
750
+ assert_equal 2, post.comments.size
751
+ assert post.comments.include?(comments(:greetings))
752
+
753
+ post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
754
+ assert_equal 2, post.comments.size
755
+ assert post.comments.include?(comments(:greetings))
756
+
757
+ posts = Post.preload(:last_comment)
758
+ post = posts.find { |p| p.id == 1 }
759
+ assert_equal Post.find(1).last_comment, post.last_comment
760
+ end
761
+
762
+ def test_to_sql_on_eager_join
763
+ expected = assert_sql {
764
+ Post.eager_load(:last_comment).order('comments.id DESC').to_a
765
+ }.first
766
+ actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
767
+ assert_equal expected, actual
768
+ end
769
+
770
+ def test_to_sql_on_scoped_proxy
771
+ auth = Author.first
772
+ Post.where("1=1").written_by(auth)
773
+ assert_not auth.posts.to_sql.include?("1=1")
774
+ end
775
+
776
+ def test_loading_with_one_association_with_non_preload
777
+ posts = Post.eager_load(:last_comment).order('comments.id DESC')
778
+ post = posts.find { |p| p.id == 1 }
779
+ assert_equal Post.find(1).last_comment, post.last_comment
780
+ end
781
+
782
+ def test_dynamic_find_by_attributes
783
+ david = authors(:david)
784
+ author = Author.preload(:taggings).find_by_id(david.id)
785
+ expected_taggings = taggings(:welcome_general, :thinking_general)
786
+
787
+ assert_no_queries do
788
+ assert_equal expected_taggings, author.taggings.distinct.sort_by(&:id)
789
+ assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id)
790
+ end
791
+
792
+ authors = Author.all
793
+ assert_equal david, authors.find_by_id_and_name(david.id, david.name)
794
+ assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
795
+ end
796
+
797
+ def test_dynamic_find_by_attributes_bang
798
+ author = Author.all.find_by_id!(authors(:david).id)
799
+ assert_equal "David", author.name
800
+
801
+ assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, 'invalid') }
802
+ end
803
+
804
+ def test_find_id
805
+ authors = Author.all
806
+
807
+ david = authors.find(authors(:david).id)
808
+ assert_equal 'David', david.name
809
+
810
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
811
+ end
812
+
813
+ def test_find_ids
814
+ authors = Author.order('id ASC')
815
+
816
+ results = authors.find(authors(:david).id, authors(:mary).id)
817
+ assert_kind_of Array, results
818
+ assert_equal 2, results.size
819
+ assert_equal 'David', results[0].name
820
+ assert_equal 'Mary', results[1].name
821
+ assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
822
+
823
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
824
+ assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
825
+ end
826
+
827
+ def test_find_in_empty_array
828
+ authors = Author.all.where(:id => [])
829
+ assert authors.to_a.blank?
830
+ end
831
+
832
+ def test_where_with_ar_object
833
+ author = Author.first
834
+ authors = Author.all.where(:id => author)
835
+ assert_equal 1, authors.to_a.length
836
+ end
837
+
838
+ def test_find_with_list_of_ar
839
+ author = Author.first
840
+ authors = Author.find([author.id])
841
+ assert_equal author, authors.first
842
+ end
843
+
844
+ class Mary < Author; end
845
+
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
851
+ end
852
+
853
+ def test_find_by_id_with_list_of_ar
854
+ author = Author.first
855
+ authors = Author.find_by_id([author])
856
+ assert_equal author, authors
857
+ end
858
+
859
+ def test_find_all_using_where_twice_should_or_the_relation
860
+ david = authors(:david)
861
+ relation = Author.unscoped
862
+ relation = relation.where(:name => david.name)
863
+ relation = relation.where(:name => 'Santiago')
864
+ relation = relation.where(:id => david.id)
865
+ assert_equal [], relation.to_a
866
+ end
867
+
868
+ def test_multi_where_ands_queries
869
+ relation = Author.unscoped
870
+ david = authors(:david)
871
+ sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
872
+ assert_match('AND', sql)
873
+ end
874
+
875
+ def test_find_all_with_multiple_should_use_and
876
+ david = authors(:david)
877
+ relation = [
878
+ { :name => david.name },
879
+ { :name => 'Santiago' },
880
+ { :name => 'tenderlove' },
881
+ ].inject(Author.unscoped) do |memo, param|
882
+ memo.where(param)
883
+ end
884
+ assert_equal [], relation.to_a
885
+ end
886
+
887
+ def test_typecasting_where_with_array
888
+ ids = Author.pluck(:id)
889
+ slugs = ids.map { |id| "#{id}-as-a-slug" }
890
+
891
+ assert_equal Author.all.to_a, Author.where(id: slugs).to_a
892
+ end
893
+
894
+ def test_find_all_using_where_with_relation
895
+ david = authors(:david)
896
+ # switching the lines below would succeed in current rails
897
+ # assert_queries(2) {
898
+ assert_queries(1) {
899
+ relation = Author.where(:id => Author.where(:id => david.id))
900
+ assert_equal [david], relation.to_a
901
+ }
902
+
903
+ assert_queries(1) {
904
+ relation = Author.where('id in (?)', Author.where(id: david).select(:id))
905
+ assert_equal [david], relation.to_a
906
+ }
907
+
908
+ assert_queries(1) do
909
+ relation = Author.where('id in (:author_ids)', author_ids: Author.where(id: david).select(:id))
910
+ assert_equal [david], relation.to_a
911
+ end
912
+ end
913
+
914
+ def test_find_all_using_where_with_relation_with_bound_values
915
+ david = authors(:david)
916
+ davids_posts = david.posts.order(:id).to_a
917
+
918
+ assert_queries(1) do
919
+ relation = Post.where(id: david.posts.select(:id))
920
+ assert_equal davids_posts, relation.order(:id).to_a
921
+ end
922
+
923
+ 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'
926
+ end
927
+
928
+ 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'
931
+ end
932
+ end
933
+
934
+ def test_find_all_using_where_with_relation_and_alternate_primary_key
935
+ cool_first = minivans(:cool_first)
936
+ # switching the lines below would succeed in current rails
937
+ # assert_queries(2) {
938
+ assert_queries(1) {
939
+ relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
940
+ assert_equal [cool_first], relation.to_a
941
+ }
942
+ end
943
+
944
+ def test_find_all_using_where_with_relation_does_not_alter_select_values
945
+ david = authors(:david)
946
+
947
+ subquery = Author.where(:id => david.id)
948
+
949
+ assert_queries(1) {
950
+ relation = Author.where(:id => subquery)
951
+ assert_equal [david], relation.to_a
952
+ }
953
+
954
+ assert_equal 0, subquery.select_values.size
955
+ end
956
+
957
+ def test_find_all_using_where_with_relation_with_joins
958
+ david = authors(:david)
959
+ assert_queries(1) {
960
+ relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
961
+ assert_equal [david], relation.to_a
962
+ }
963
+ end
964
+
965
+
966
+ def test_find_all_using_where_with_relation_with_select_to_build_subquery
967
+ david = authors(:david)
968
+ assert_queries(1) {
969
+ relation = Author.where(:name => Author.where(:id => david.id).select(:name))
970
+ assert_equal [david], relation.to_a
971
+ }
972
+ end
973
+
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
+ def test_last
1001
+ authors = Author.all
1002
+ assert_equal authors(:bob), authors.last
1003
+ end
1004
+
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
+ def test_select_with_aggregates
1059
+ posts = Post.select(:title, :body)
1060
+
1061
+ assert_equal 11, posts.count(:all)
1062
+ assert_equal 11, posts.size
1063
+ assert posts.any?
1064
+ assert posts.many?
1065
+ assert_not posts.empty?
1066
+ end
1067
+
1068
+ def test_select_takes_a_variable_list_of_args
1069
+ david = developers(:david)
1070
+
1071
+ developer = Developer.where(id: david.id).select(:name, :salary).first
1072
+ assert_equal david.name, developer.name
1073
+ assert_equal david.salary, developer.salary
1074
+ end
1075
+
1076
+ def test_select_takes_an_aliased_attribute
1077
+ first = topics(:first)
1078
+
1079
+ topic = Topic.where(id: first.id).select(:heading).first
1080
+ assert_equal first.heading, topic.heading
1081
+ end
1082
+
1083
+ def test_select_argument_error
1084
+ assert_raises(ArgumentError) { Developer.select }
1085
+ end
1086
+
1087
+ def test_count
1088
+ posts = Post.all
1089
+
1090
+ assert_equal 11, posts.count
1091
+ assert_equal 11, posts.count(:all)
1092
+ assert_equal 11, posts.count(:id)
1093
+
1094
+ assert_equal 1, posts.where('comments_count > 1').count
1095
+ assert_equal 9, posts.where(:comments_count => 0).count
1096
+ end
1097
+
1098
+ def test_count_on_association_relation
1099
+ author = Author.last
1100
+ another_author = Author.first
1101
+ posts = Post.where(author_id: author.id)
1102
+
1103
+ assert_equal author.posts.where(author_id: author.id).size, posts.count
1104
+
1105
+ assert_equal 0, author.posts.where(author_id: another_author.id).size
1106
+ assert author.posts.where(author_id: another_author.id).empty?
1107
+ end
1108
+
1109
+ def test_count_with_distinct
1110
+ posts = Post.all
1111
+
1112
+ assert_equal 3, posts.distinct(true).count(:comments_count)
1113
+ assert_equal 11, posts.distinct(false).count(:comments_count)
1114
+
1115
+ assert_equal 3, posts.distinct(true).select(:comments_count).count
1116
+ assert_equal 11, posts.distinct(false).select(:comments_count).count
1117
+ end
1118
+
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 }
1125
+ end
1126
+
1127
+ def test_count_explicit_columns
1128
+ Post.update_all(:comments_count => nil)
1129
+ posts = Post.all
1130
+
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
1133
+
1134
+ assert_equal 11, posts.select('comments_count').count('id')
1135
+ assert_equal 0, posts.select('comments_count').count
1136
+ assert_equal 0, posts.count(:comments_count)
1137
+ assert_equal 0, posts.count('comments_count')
1138
+ end
1139
+
1140
+ def test_multiple_selects
1141
+ post = Post.all.select('comments_count').select('title').order("id ASC").first
1142
+ assert_equal "Welcome to the weblog", post.title
1143
+ assert_equal 2, post.comments_count
1144
+ end
1145
+
1146
+ def test_size
1147
+ posts = Post.all
1148
+
1149
+ assert_queries(1) { assert_equal 11, posts.size }
1150
+ assert ! posts.loaded?
1151
+
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 }
1155
+ end
1156
+
1157
+ def test_size_with_limit
1158
+ posts = Post.limit(10)
1159
+
1160
+ assert_queries(1) { assert_equal 10, posts.size }
1161
+ assert ! posts.loaded?
1162
+
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 }
1166
+ end
1167
+
1168
+ def test_size_with_zero_limit
1169
+ posts = Post.limit(0)
1170
+
1171
+ assert_no_queries { assert_equal 0, posts.size }
1172
+ assert ! posts.loaded?
1173
+
1174
+ posts.to_a # force load
1175
+ assert_no_queries { assert_equal 0, posts.size }
1176
+ end
1177
+
1178
+ def test_empty_with_zero_limit
1179
+ posts = Post.limit(0)
1180
+
1181
+ assert_no_queries { assert_equal true, posts.empty? }
1182
+ assert ! posts.loaded?
1183
+ end
1184
+
1185
+ def test_count_complex_chained_relations
1186
+ posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
1187
+
1188
+ expected = { 1 => 2 }
1189
+ assert_equal expected, posts.count
1190
+ end
1191
+
1192
+ def test_empty
1193
+ posts = Post.all
1194
+
1195
+ assert_queries(1) { assert_equal false, posts.empty? }
1196
+ assert ! posts.loaded?
1197
+
1198
+ no_posts = posts.where(:title => "")
1199
+ assert_queries(1) { assert_equal true, no_posts.empty? }
1200
+ assert ! no_posts.loaded?
1201
+
1202
+ best_posts = posts.where(:comments_count => 0)
1203
+ best_posts.to_a # force load
1204
+ assert_no_queries { assert_equal false, best_posts.empty? }
1205
+ end
1206
+
1207
+ def test_empty_complex_chained_relations
1208
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
1209
+
1210
+ assert_queries(1) { assert_equal false, posts.empty? }
1211
+ assert ! posts.loaded?
1212
+
1213
+ no_posts = posts.where(:title => "")
1214
+ assert_queries(1) { assert_equal true, no_posts.empty? }
1215
+ assert ! no_posts.loaded?
1216
+ end
1217
+
1218
+ def test_any
1219
+ posts = Post.all
1220
+
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
+ assert_queries(3) do
1230
+ assert posts.any? # Uses COUNT()
1231
+ assert ! posts.where(:id => nil).any?
1232
+
1233
+ assert posts.any? {|p| p.id > 0 }
1234
+ assert ! posts.any? {|p| p.id <= 0 }
1235
+ end
1236
+
1237
+ assert posts.loaded?
1238
+ end
1239
+
1240
+ def test_many
1241
+ posts = Post.all
1242
+
1243
+ assert_queries(2) do
1244
+ assert posts.many? # Uses COUNT()
1245
+ assert posts.many? {|p| p.id > 0 }
1246
+ assert ! posts.many? {|p| p.id < 2 }
1247
+ end
1248
+
1249
+ assert posts.loaded?
1250
+ end
1251
+
1252
+ def test_many_with_limits
1253
+ posts = Post.all
1254
+
1255
+ assert posts.many?
1256
+ assert ! posts.limit(1).many?
1257
+ end
1258
+
1259
+ def test_none?
1260
+ posts = Post.all
1261
+ assert_queries(1) do
1262
+ assert ! posts.none? # Uses COUNT()
1263
+ end
1264
+
1265
+ assert ! posts.loaded?
1266
+
1267
+ assert_queries(1) do
1268
+ assert posts.none? {|p| p.id < 0 }
1269
+ assert ! posts.none? {|p| p.id == 1 }
1270
+ end
1271
+
1272
+ assert posts.loaded?
1273
+ end
1274
+
1275
+ def test_one
1276
+ posts = Post.all
1277
+ assert_queries(1) do
1278
+ assert ! posts.one? # Uses COUNT()
1279
+ end
1280
+
1281
+ assert ! posts.loaded?
1282
+
1283
+ assert_queries(1) do
1284
+ assert ! posts.one? {|p| p.id < 3 }
1285
+ assert posts.one? {|p| p.id == 1 }
1286
+ end
1287
+
1288
+ assert posts.loaded?
1289
+ end
1290
+
1291
+ def test_to_a_should_dup_target
1292
+ posts = Post.all
1293
+
1294
+ original_size = posts.size
1295
+ removed = posts.to_a.pop
1296
+
1297
+ assert_equal original_size, posts.size
1298
+ assert_includes posts.to_a, removed
1299
+ end
1300
+
1301
+ def test_build
1302
+ posts = Post.all
1303
+
1304
+ post = posts.new
1305
+ assert_kind_of Post, post
1306
+ end
1307
+
1308
+ def test_scoped_build
1309
+ posts = Post.where(:title => 'You told a lie')
1310
+
1311
+ post = posts.new
1312
+ assert_kind_of Post, post
1313
+ assert_equal 'You told a lie', post.title
1314
+ end
1315
+
1316
+ def test_create
1317
+ birds = Bird.all
1318
+
1319
+ sparrow = birds.create
1320
+ assert_kind_of Bird, sparrow
1321
+ assert !sparrow.persisted?
1322
+
1323
+ hen = birds.where(:name => 'hen').create
1324
+ assert hen.persisted?
1325
+ assert_equal 'hen', hen.name
1326
+ end
1327
+
1328
+ def test_create_bang
1329
+ birds = Bird.all
1330
+
1331
+ assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
1332
+
1333
+ hen = birds.where(:name => 'hen').create!
1334
+ assert_kind_of Bird, hen
1335
+ assert hen.persisted?
1336
+ assert_equal 'hen', hen.name
1337
+ end
1338
+
1339
+ def test_first_or_create
1340
+ parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
1341
+ assert_kind_of Bird, parrot
1342
+ assert parrot.persisted?
1343
+ assert_equal 'parrot', parrot.name
1344
+ assert_equal 'green', parrot.color
1345
+
1346
+ same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
1347
+ assert_kind_of Bird, same_parrot
1348
+ assert same_parrot.persisted?
1349
+ assert_equal parrot, same_parrot
1350
+ end
1351
+
1352
+ def test_first_or_create_with_no_parameters
1353
+ parrot = Bird.where(:color => 'green').first_or_create
1354
+ assert_kind_of Bird, parrot
1355
+ assert !parrot.persisted?
1356
+ assert_equal 'green', parrot.color
1357
+ end
1358
+
1359
+ def test_first_or_create_with_block
1360
+ parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
1361
+ assert_kind_of Bird, parrot
1362
+ assert parrot.persisted?
1363
+ assert_equal 'green', parrot.color
1364
+ assert_equal 'parrot', parrot.name
1365
+
1366
+ same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
1367
+ assert_equal parrot, same_parrot
1368
+ end
1369
+
1370
+ def test_first_or_create_with_array
1371
+ several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
1372
+ assert_kind_of Array, several_green_birds
1373
+ several_green_birds.each { |bird| assert bird.persisted? }
1374
+
1375
+ same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
1376
+ assert_kind_of Bird, same_parrot
1377
+ assert_equal several_green_birds.first, same_parrot
1378
+ end
1379
+
1380
+ def test_first_or_create_bang_with_valid_options
1381
+ parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
1382
+ assert_kind_of Bird, parrot
1383
+ assert parrot.persisted?
1384
+ assert_equal 'parrot', parrot.name
1385
+ assert_equal 'green', parrot.color
1386
+
1387
+ same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
1388
+ assert_kind_of Bird, same_parrot
1389
+ assert same_parrot.persisted?
1390
+ assert_equal parrot, same_parrot
1391
+ end
1392
+
1393
+ def test_first_or_create_bang_with_invalid_options
1394
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
1395
+ end
1396
+
1397
+ def test_first_or_create_bang_with_no_parameters
1398
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
1399
+ end
1400
+
1401
+ def test_first_or_create_bang_with_valid_block
1402
+ parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
1403
+ assert_kind_of Bird, parrot
1404
+ assert parrot.persisted?
1405
+ assert_equal 'green', parrot.color
1406
+ assert_equal 'parrot', parrot.name
1407
+
1408
+ same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
1409
+ assert_equal parrot, same_parrot
1410
+ end
1411
+
1412
+ def test_first_or_create_bang_with_invalid_block
1413
+ assert_raise(ActiveRecord::RecordInvalid) do
1414
+ Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
1415
+ end
1416
+ end
1417
+
1418
+ def test_first_or_create_with_valid_array
1419
+ several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
1420
+ assert_kind_of Array, several_green_birds
1421
+ several_green_birds.each { |bird| assert bird.persisted? }
1422
+
1423
+ same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
1424
+ assert_kind_of Bird, same_parrot
1425
+ assert_equal several_green_birds.first, same_parrot
1426
+ end
1427
+
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} ]) }
1430
+ end
1431
+
1432
+ def test_first_or_initialize
1433
+ parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
1434
+ 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
1440
+ end
1441
+
1442
+ def test_first_or_initialize_with_no_parameters
1443
+ parrot = Bird.where(:color => 'green').first_or_initialize
1444
+ assert_kind_of Bird, parrot
1445
+ assert !parrot.persisted?
1446
+ assert !parrot.valid?
1447
+ assert parrot.new_record?
1448
+ assert_equal 'green', parrot.color
1449
+ end
1450
+
1451
+ def test_first_or_initialize_with_block
1452
+ parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
1453
+ 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
1459
+ end
1460
+
1461
+ def test_find_or_create_by
1462
+ assert_nil Bird.find_by(name: 'bob')
1463
+
1464
+ bird = Bird.find_or_create_by(name: 'bob')
1465
+ assert bird.persisted?
1466
+
1467
+ assert_equal bird, Bird.find_or_create_by(name: 'bob')
1468
+ end
1469
+
1470
+ def test_find_or_create_by_with_create_with
1471
+ assert_nil Bird.find_by(name: 'bob')
1472
+
1473
+ bird = Bird.create_with(color: 'green').find_or_create_by(name: 'bob')
1474
+ assert bird.persisted?
1475
+ assert_equal 'green', bird.color
1476
+
1477
+ assert_equal bird, Bird.create_with(color: 'blue').find_or_create_by(name: 'bob')
1478
+ end
1479
+
1480
+ def test_find_or_create_by!
1481
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: 'green') }
1482
+ end
1483
+
1484
+ def test_find_or_initialize_by
1485
+ assert_nil Bird.find_by(name: 'bob')
1486
+
1487
+ bird = Bird.find_or_initialize_by(name: 'bob')
1488
+ assert bird.new_record?
1489
+ bird.save!
1490
+
1491
+ assert_equal bird, Bird.find_or_initialize_by(name: 'bob')
1492
+ end
1493
+
1494
+ def test_explicit_create_scope
1495
+ hens = Bird.where(:name => 'hen')
1496
+ assert_equal 'hen', hens.new.name
1497
+
1498
+ hens = hens.create_with(:name => 'cock')
1499
+ assert_equal 'cock', hens.new.name
1500
+ end
1501
+
1502
+ def test_except
1503
+ relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1504
+ assert_equal [posts(:welcome)], relation.to_a
1505
+
1506
+ author_posts = relation.except(:order, :limit)
1507
+ assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1508
+
1509
+ all_posts = relation.except(:where, :order, :limit)
1510
+ assert_equal Post.all, all_posts
1511
+ end
1512
+
1513
+ def test_only
1514
+ relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1515
+ assert_equal [posts(:welcome)], relation.to_a
1516
+
1517
+ author_posts = relation.only(:where)
1518
+ assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1519
+
1520
+ all_posts = relation.only(:limit)
1521
+ assert_equal Post.limit(1).to_a.first, all_posts.first
1522
+ end
1523
+
1524
+ def test_anonymous_extension
1525
+ relation = Post.where(:author_id => 1).order('id ASC').extending do
1526
+ def author
1527
+ 'lifo'
1528
+ end
1529
+ end
1530
+
1531
+ assert_equal "lifo", relation.author
1532
+ assert_equal "lifo", relation.limit(1).author
1533
+ end
1534
+
1535
+ def test_named_extension
1536
+ relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
1537
+ assert_equal "lifo", relation.author
1538
+ assert_equal "lifo", relation.limit(1).author
1539
+ end
1540
+
1541
+ def test_order_by_relation_attribute
1542
+ assert_equal Post.order(Post.arel_table[:title]).to_a, Post.order("title").to_a
1543
+ end
1544
+
1545
+ 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
1548
+ end
1549
+
1550
+ def test_order_using_scoping
1551
+ car1 = CoolCar.order('id DESC').scoping do
1552
+ CoolCar.all.merge!(order: 'id asc').first
1553
+ end
1554
+ assert_equal 'zyke', car1.name
1555
+
1556
+ car2 = FastCar.order('id DESC').scoping do
1557
+ FastCar.all.merge!(order: 'id asc').first
1558
+ end
1559
+ assert_equal 'zyke', car2.name
1560
+ end
1561
+
1562
+ 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}
1565
+ end
1566
+
1567
+ def test_intersection_with_array
1568
+ relation = Author.where(:name => "David")
1569
+ rails_author = relation.first
1570
+
1571
+ assert_equal [rails_author], [rails_author] & relation
1572
+ assert_equal [rails_author], relation & [rails_author]
1573
+ end
1574
+
1575
+ def test_primary_key
1576
+ assert_equal "id", Post.all.primary_key
1577
+ end
1578
+
1579
+ 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
1643
+ end
1644
+
1645
+ def test_distinct
1646
+ tag1 = Tag.create(:name => 'Foo')
1647
+ tag2 = Tag.create(:name => 'Foo')
1648
+
1649
+ query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
1650
+
1651
+ assert_equal ['Foo', 'Foo'], query.map(&:name)
1652
+ assert_sql(/DISTINCT/) do
1653
+ assert_equal ['Foo'], query.distinct.map(&:name)
1654
+ assert_deprecated { assert_equal ['Foo'], query.uniq.map(&:name) }
1655
+ end
1656
+ 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)
1664
+ end
1665
+ end
1666
+
1667
+ def test_doesnt_add_having_values_if_options_are_blank
1668
+ scope = Post.having('')
1669
+ assert scope.having_clause.empty?
1670
+
1671
+ scope = Post.having([])
1672
+ assert scope.having_clause.empty?
1673
+ end
1674
+
1675
+ def test_having_with_binds_for_both_where_and_having
1676
+ 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)
1679
+
1680
+ assert_equal [post], having_then_where
1681
+ assert_equal [post], where_then_having
1682
+ end
1683
+
1684
+ def test_multiple_where_and_having_clauses
1685
+ post = Post.first
1686
+ having_then_where = Post.having(id: post.id).where(title: post.title)
1687
+ .having(id: post.id).where(title: post.title).group(:id)
1688
+
1689
+ assert_equal [post], having_then_where
1690
+ end
1691
+
1692
+ def test_grouping_by_column_with_reserved_name
1693
+ assert_equal [], Possession.select(:where).group(:where).to_a
1694
+ end
1695
+
1696
+ def test_references_triggers_eager_loading
1697
+ scope = Post.includes(:comments)
1698
+ assert !scope.eager_loading?
1699
+ assert scope.references(:comments).eager_loading?
1700
+ end
1701
+
1702
+ def test_references_doesnt_trigger_eager_loading_if_reference_not_included
1703
+ scope = Post.references(:comments)
1704
+ assert !scope.eager_loading?
1705
+ end
1706
+
1707
+ def test_automatically_added_where_references
1708
+ scope = Post.where(:comments => { :body => "Bla" })
1709
+ assert_equal ['comments'], scope.references_values
1710
+
1711
+ scope = Post.where('comments.body' => 'Bla')
1712
+ assert_equal ['comments'], scope.references_values
1713
+ end
1714
+
1715
+ def test_automatically_added_where_not_references
1716
+ scope = Post.where.not(comments: { body: "Bla" })
1717
+ assert_equal ['comments'], scope.references_values
1718
+
1719
+ scope = Post.where.not('comments.body' => 'Bla')
1720
+ assert_equal ['comments'], scope.references_values
1721
+ end
1722
+
1723
+ def test_automatically_added_having_references
1724
+ scope = Post.having(:comments => { :body => "Bla" })
1725
+ assert_equal ['comments'], scope.references_values
1726
+
1727
+ scope = Post.having('comments.body' => 'Bla')
1728
+ assert_equal ['comments'], scope.references_values
1729
+ end
1730
+
1731
+ def test_automatically_added_order_references
1732
+ scope = Post.order('comments.body')
1733
+ assert_equal ['comments'], scope.references_values
1734
+
1735
+ scope = Post.order('comments.body', 'yaks.body')
1736
+ assert_equal ['comments', 'yaks'], scope.references_values
1737
+
1738
+ # 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
1741
+
1742
+ scope = Post.order('comments.body asc')
1743
+ assert_equal ['comments'], scope.references_values
1744
+
1745
+ scope = Post.order('foo(comments.body)')
1746
+ assert_equal [], scope.references_values
1747
+ end
1748
+
1749
+ def test_automatically_added_reorder_references
1750
+ scope = Post.reorder('comments.body')
1751
+ assert_equal %w(comments), scope.references_values
1752
+
1753
+ scope = Post.reorder('comments.body', 'yaks.body')
1754
+ assert_equal %w(comments yaks), scope.references_values
1755
+
1756
+ # Don't infer yaks, let's not go down that road again...
1757
+ scope = Post.reorder('comments.body, yaks.body')
1758
+ assert_equal %w(comments), scope.references_values
1759
+
1760
+ scope = Post.reorder('comments.body asc')
1761
+ assert_equal %w(comments), scope.references_values
1762
+
1763
+ scope = Post.reorder('foo(comments.body)')
1764
+ assert_equal [], scope.references_values
1765
+ end
1766
+
1767
+ def test_order_with_reorder_nil_removes_the_order
1768
+ relation = Post.order(:title).reorder(nil)
1769
+
1770
+ assert_nil relation.order_values.first
1771
+ end
1772
+
1773
+ def test_reverse_order_with_reorder_nil_removes_the_order
1774
+ relation = Post.order(:title).reverse_order.reorder(nil)
1775
+
1776
+ assert_nil relation.order_values.first
1777
+ end
1778
+
1779
+ def test_presence
1780
+ topics = Topic.all
1781
+
1782
+ # the first query is triggered because there are no topics yet.
1783
+ assert_queries(1) { assert topics.present? }
1784
+
1785
+ # checking if there are topics is used before you actually display them,
1786
+ # thus it shouldn't invoke an extra count query.
1787
+ assert_no_queries { assert topics.present? }
1788
+ assert_no_queries { assert !topics.blank? }
1789
+
1790
+ # shows count of topics and loops after loading the query should not trigger extra queries either.
1791
+ assert_no_queries { topics.size }
1792
+ assert_no_queries { topics.length }
1793
+ assert_no_queries { topics.each }
1794
+
1795
+ # count always trigger the COUNT query.
1796
+ assert_queries(1) { topics.count }
1797
+
1798
+ assert topics.loaded?
1799
+ end
1800
+
1801
+ test "find_by with hash conditions returns the first matching record" do
1802
+ assert_equal posts(:eager_other), Post.order(:id).find_by(author_id: 2)
1803
+ end
1804
+
1805
+ test "find_by with non-hash conditions returns the first matching record" do
1806
+ assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = 2")
1807
+ end
1808
+
1809
+ 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)
1811
+ end
1812
+
1813
+ test "find_by returns nil if the record is missing" do
1814
+ assert_equal nil, Post.all.find_by("1 = 0")
1815
+ end
1816
+
1817
+ test "find_by doesn't have implicit ordering" do
1818
+ assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
1819
+ end
1820
+
1821
+ test "find_by requires at least one argument" do
1822
+ assert_raises(ArgumentError) { Post.all.find_by }
1823
+ end
1824
+
1825
+ test "find_by! with hash conditions returns the first matching record" do
1826
+ assert_equal posts(:eager_other), Post.order(:id).find_by!(author_id: 2)
1827
+ end
1828
+
1829
+ test "find_by! with non-hash conditions returns the first matching record" do
1830
+ assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = 2")
1831
+ end
1832
+
1833
+ 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)
1835
+ end
1836
+
1837
+ test "find_by! doesn't have implicit ordering" do
1838
+ assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
1839
+ end
1840
+
1841
+ test "find_by! raises RecordNotFound if the record is missing" do
1842
+ assert_raises(ActiveRecord::RecordNotFound) do
1843
+ Post.all.find_by!("1 = 0")
1844
+ end
1845
+ end
1846
+
1847
+ test "find_by! requires at least one argument" do
1848
+ assert_raises(ArgumentError) { Post.all.find_by! }
1849
+ end
1850
+
1851
+ test "loaded relations cannot be mutated by multi value methods" do
1852
+ relation = Post.all
1853
+ relation.to_a
1854
+
1855
+ assert_raises(ActiveRecord::ImmutableRelation) do
1856
+ relation.where! 'foo'
1857
+ end
1858
+ end
1859
+
1860
+ test "loaded relations cannot be mutated by single value methods" do
1861
+ relation = Post.all
1862
+ relation.to_a
1863
+
1864
+ assert_raises(ActiveRecord::ImmutableRelation) do
1865
+ relation.limit! 5
1866
+ end
1867
+ end
1868
+
1869
+ test "loaded relations cannot be mutated by merge!" do
1870
+ relation = Post.all
1871
+ relation.to_a
1872
+
1873
+ assert_raises(ActiveRecord::ImmutableRelation) do
1874
+ relation.merge! where: 'foo'
1875
+ end
1876
+ end
1877
+
1878
+ test "loaded relations cannot be mutated by extending!" do
1879
+ relation = Post.all
1880
+ relation.to_a
1881
+
1882
+ assert_raises(ActiveRecord::ImmutableRelation) do
1883
+ relation.extending! Module.new
1884
+ end
1885
+ end
1886
+
1887
+ test "relations with cached arel can't be mutated [internal API]" do
1888
+ relation = Post.all
1889
+ relation.count
1890
+
1891
+ assert_raises(ActiveRecord::ImmutableRelation) { relation.limit!(5) }
1892
+ assert_raises(ActiveRecord::ImmutableRelation) { relation.where!("1 = 2") }
1893
+ end
1894
+
1895
+ test "relations show the records in #inspect" do
1896
+ relation = Post.limit(2)
1897
+ assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
1898
+ end
1899
+
1900
+ test "relations limit the records in #inspect at 10" do
1901
+ relation = Post.limit(11)
1902
+ assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
1903
+ end
1904
+
1905
+ test "already-loaded relations don't perform a new query in #inspect" do
1906
+ relation = Post.limit(2)
1907
+ relation.to_a
1908
+
1909
+ expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>"
1910
+
1911
+ assert_no_queries do
1912
+ assert_equal expected, relation.inspect
1913
+ end
1914
+ end
1915
+
1916
+ test 'using a custom table affects the wheres' do
1917
+ table_alias = Post.arel_table.alias('omg_posts')
1918
+
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")
1923
+
1924
+ node = relation.arel.constraints.first.grep(Arel::Attributes::Attribute).first
1925
+ assert_equal table_alias, node.relation
1926
+ end
1927
+
1928
+ test '#load' do
1929
+ relation = Post.all
1930
+ assert_queries(1) do
1931
+ assert_equal relation, relation.load
1932
+ end
1933
+ assert_no_queries { relation.to_a }
1934
+ end
1935
+
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
1939
+
1940
+ assert_no_queries do
1941
+ result = authors_count.map do |post|
1942
+ [post.num_posts, post.author.try(:name)]
1943
+ end
1944
+
1945
+ expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
1946
+ assert_equal expected, result
1947
+ end
1948
+ end
1949
+
1950
+ test "joins with select" do
1951
+ posts = Post.joins(:author).select("id", "authors.author_address_id").order("posts.id").limit(3)
1952
+ assert_equal [1, 2, 4], posts.map(&:id)
1953
+ assert_equal [1, 1, 1], posts.map(&:author_address_id)
1954
+ end
1955
+
1956
+ test "delegations do not leak to other classes" do
1957
+ Topic.all.by_lifo
1958
+ assert Topic.all.class.method_defined?(:by_lifo)
1959
+ assert !Post.all.respond_to?(:by_lifo)
1960
+ end
1961
+
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]]
1966
+
1967
+ relation = left.unscope(where: :id)
1968
+ assert_equal [], relation.bind_values
1969
+ end
1970
+
1971
+ def test_merging_removes_rhs_bind_parameters
1972
+ left = Post.where(id: 20)
1973
+ right = Post.where(id: [1,2,3,4])
1974
+
1975
+ merged = left.merge(right)
1976
+ assert_equal [], merged.bind_values
1977
+ end
1978
+
1979
+ def test_merging_keeps_lhs_bind_parameters
1980
+ binds = [ActiveRecord::Relation::QueryAttribute.new("id", 20, Post.type_for_attribute("id"))]
1981
+
1982
+ right = Post.where(id: 20)
1983
+ left = Post.where(id: 10)
1984
+
1985
+ merged = left.merge(right)
1986
+ assert_equal binds, merged.bound_attributes
1987
+ end
1988
+
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)
1993
+
1994
+ merged = left.merge(right)
1995
+ assert_equal post, merged.first
1996
+ end
1997
+
1998
+ def test_relation_join_method
1999
+ assert_equal 'Thank you for the welcome,Thank you again for the welcome', Post.first.comments.join(",")
2000
+ end
2001
+
2002
+ def test_connection_adapters_can_reorder_binds
2003
+ posts = Post.limit(1).offset(2)
2004
+
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)
2011
+ end
2012
+
2013
+ posts.define_singleton_method(:connection) do
2014
+ stubbed_connection
2015
+ end
2016
+
2017
+ assert_equal 2, posts.to_a.length
2018
+ end
2019
+
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 })
2024
+ end
2025
+ end
2026
+ end