ibm_db 3.0.5-x86-mingw32 → 4.0.0-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 (586) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/ParameterizedQueries README +6 -6
  6. data/README +208 -225
  7. data/ext/Makefile.nt32 +181 -181
  8. data/ext/Makefile.nt32.191 +212 -212
  9. data/ext/extconf.rb +291 -291
  10. data/ext/ibm_db.c +11887 -11887
  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/init.rb +41 -41
  15. data/lib/IBM_DB.rb +27 -27
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
  17. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  18. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  19. data/lib/mswin32/ibm_db.rb +91 -123
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  22. data/test/assets/example.log +1 -1
  23. data/test/assets/test.txt +1 -1
  24. data/test/cases/adapter_test.rb +351 -276
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  27. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  30. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  32. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  33. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  34. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  35. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  36. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  38. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  39. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  40. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  41. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  43. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  44. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  45. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  46. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  47. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  48. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  49. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  50. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  51. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  52. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  53. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  54. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  55. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  56. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  57. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  58. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  59. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  60. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  61. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  62. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  63. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  64. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  65. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  66. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  67. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  68. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  69. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  70. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  71. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  72. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  73. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  74. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  75. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  76. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  77. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  78. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  79. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  80. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  81. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  82. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  83. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  84. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  85. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  86. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  87. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  88. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  89. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  90. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  91. data/test/cases/aggregations_test.rb +168 -158
  92. data/test/cases/ar_schema_test.rb +146 -161
  93. data/test/cases/associations/association_scope_test.rb +16 -21
  94. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  95. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  96. data/test/cases/associations/callbacks_test.rb +190 -192
  97. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  98. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  99. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  100. data/test/cases/associations/eager_singularization_test.rb +148 -148
  101. data/test/cases/associations/eager_test.rb +1514 -1429
  102. data/test/cases/associations/extension_test.rb +87 -82
  103. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
  104. data/test/cases/associations/has_many_associations_test.rb +2501 -2182
  105. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  106. data/test/cases/associations/has_one_associations_test.rb +707 -610
  107. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  108. data/test/cases/associations/inner_join_association_test.rb +139 -139
  109. data/test/cases/associations/inverse_associations_test.rb +733 -706
  110. data/test/cases/associations/join_model_test.rb +777 -754
  111. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  112. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  113. data/test/cases/associations/required_test.rb +102 -82
  114. data/test/cases/associations_test.rb +385 -380
  115. data/test/cases/attribute_decorators_test.rb +125 -125
  116. data/test/cases/attribute_methods/read_test.rb +60 -60
  117. data/test/cases/attribute_methods_test.rb +1009 -952
  118. data/test/cases/attribute_set_test.rb +270 -210
  119. data/test/cases/attribute_test.rb +246 -180
  120. data/test/cases/attributes_test.rb +253 -136
  121. data/test/cases/autosave_association_test.rb +1708 -1595
  122. data/test/cases/base_test.rb +1713 -1664
  123. data/test/cases/batches_test.rb +489 -212
  124. data/test/cases/binary_test.rb +44 -52
  125. data/test/cases/bind_parameter_test.rb +110 -100
  126. data/test/cases/cache_key_test.rb +25 -0
  127. data/test/cases/calculations_test.rb +798 -646
  128. data/test/cases/callbacks_test.rb +636 -543
  129. data/test/cases/clone_test.rb +40 -40
  130. data/test/cases/coders/json_test.rb +15 -0
  131. data/test/cases/coders/yaml_column_test.rb +63 -63
  132. data/test/cases/collection_cache_key_test.rb +115 -0
  133. data/test/cases/column_alias_test.rb +17 -17
  134. data/test/cases/column_definition_test.rb +92 -123
  135. data/test/cases/comment_test.rb +143 -0
  136. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  137. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  138. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  139. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  140. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  141. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  142. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  143. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  144. data/test/cases/connection_management_test.rb +112 -122
  145. data/test/cases/connection_pool_test.rb +521 -346
  146. data/test/cases/connection_specification/resolver_test.rb +131 -116
  147. data/test/cases/core_test.rb +112 -112
  148. data/test/cases/counter_cache_test.rb +214 -209
  149. data/test/cases/custom_locking_test.rb +17 -17
  150. data/test/cases/database_statements_test.rb +34 -19
  151. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  152. data/test/cases/date_time_precision_test.rb +106 -0
  153. data/test/cases/date_time_test.rb +61 -61
  154. data/test/cases/defaults_test.rb +218 -223
  155. data/test/cases/dirty_test.rb +763 -785
  156. data/test/cases/disconnected_test.rb +30 -28
  157. data/test/cases/dup_test.rb +157 -157
  158. data/test/cases/enum_test.rb +444 -290
  159. data/test/cases/errors_test.rb +16 -0
  160. data/test/cases/explain_subscriber_test.rb +64 -64
  161. data/test/cases/explain_test.rb +87 -76
  162. data/test/cases/finder_respond_to_test.rb +60 -60
  163. data/test/cases/finder_test.rb +1294 -1169
  164. data/test/cases/fixture_set/file_test.rb +156 -138
  165. data/test/cases/fixtures_test.rb +988 -908
  166. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  167. data/test/cases/habtm_destroy_order_test.rb +61 -61
  168. data/test/cases/helper.rb +204 -210
  169. data/test/cases/hot_compatibility_test.rb +142 -54
  170. data/test/cases/i18n_test.rb +45 -45
  171. data/test/cases/inheritance_test.rb +606 -375
  172. data/test/cases/integration_test.rb +155 -139
  173. data/test/cases/invalid_connection_test.rb +24 -22
  174. data/test/cases/invertible_migration_test.rb +387 -295
  175. data/test/cases/json_serialization_test.rb +311 -302
  176. data/test/cases/locking_test.rb +493 -477
  177. data/test/cases/log_subscriber_test.rb +225 -136
  178. data/test/cases/migration/change_schema_test.rb +458 -512
  179. data/test/cases/migration/change_table_test.rb +256 -224
  180. data/test/cases/migration/column_attributes_test.rb +176 -192
  181. data/test/cases/migration/column_positioning_test.rb +56 -56
  182. data/test/cases/migration/columns_test.rb +310 -304
  183. data/test/cases/migration/command_recorder_test.rb +350 -305
  184. data/test/cases/migration/compatibility_test.rb +118 -0
  185. data/test/cases/migration/create_join_table_test.rb +157 -148
  186. data/test/cases/migration/foreign_key_test.rb +360 -328
  187. data/test/cases/migration/helper.rb +39 -39
  188. data/test/cases/migration/index_test.rb +218 -216
  189. data/test/cases/migration/logger_test.rb +36 -36
  190. data/test/cases/migration/pending_migrations_test.rb +52 -53
  191. data/test/cases/migration/references_foreign_key_test.rb +216 -169
  192. data/test/cases/migration/references_index_test.rb +101 -101
  193. data/test/cases/migration/references_statements_test.rb +136 -116
  194. data/test/cases/migration/rename_table_test.rb +93 -93
  195. data/test/cases/migration_test.rb +1157 -959
  196. data/test/cases/migrator_test.rb +470 -388
  197. data/test/cases/mixin_test.rb +68 -70
  198. data/test/cases/modules_test.rb +172 -173
  199. data/test/cases/multiparameter_attributes_test.rb +372 -350
  200. data/test/cases/multiple_db_test.rb +122 -115
  201. data/test/cases/nested_attributes_test.rb +1098 -1070
  202. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  203. data/test/cases/persistence_test.rb +1001 -909
  204. data/test/cases/pooled_connections_test.rb +81 -81
  205. data/test/cases/primary_keys_test.rb +376 -237
  206. data/test/cases/query_cache_test.rb +446 -326
  207. data/test/cases/quoting_test.rb +202 -156
  208. data/test/cases/readonly_test.rb +119 -118
  209. data/test/cases/reaper_test.rb +85 -85
  210. data/test/cases/reflection_test.rb +509 -463
  211. data/test/cases/relation/delegation_test.rb +63 -68
  212. data/test/cases/relation/merging_test.rb +157 -161
  213. data/test/cases/relation/mutation_test.rb +183 -165
  214. data/test/cases/relation/or_test.rb +92 -0
  215. data/test/cases/relation/predicate_builder_test.rb +16 -14
  216. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  217. data/test/cases/relation/where_chain_test.rb +105 -181
  218. data/test/cases/relation/where_clause_test.rb +182 -0
  219. data/test/cases/relation/where_test.rb +322 -300
  220. data/test/cases/relation_test.rb +328 -319
  221. data/test/cases/relations_test.rb +2026 -1815
  222. data/test/cases/reload_models_test.rb +22 -22
  223. data/test/cases/result_test.rb +90 -80
  224. data/test/cases/sanitize_test.rb +176 -83
  225. data/test/cases/schema_dumper_test.rb +457 -463
  226. data/test/cases/schema_loading_test.rb +52 -0
  227. data/test/cases/scoping/default_scoping_test.rb +528 -454
  228. data/test/cases/scoping/named_scoping_test.rb +561 -524
  229. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  230. data/test/cases/secure_token_test.rb +32 -0
  231. data/test/cases/serialization_test.rb +104 -104
  232. data/test/cases/serialized_attribute_test.rb +364 -277
  233. data/test/cases/statement_cache_test.rb +136 -98
  234. data/test/cases/store_test.rb +195 -194
  235. data/test/cases/suppressor_test.rb +63 -0
  236. data/test/cases/tasks/database_tasks_test.rb +462 -398
  237. data/test/cases/tasks/mysql_rake_test.rb +345 -324
  238. data/test/cases/tasks/postgresql_rake_test.rb +304 -250
  239. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  240. data/test/cases/test_case.rb +131 -123
  241. data/test/cases/test_fixtures_test.rb +36 -0
  242. data/test/cases/time_precision_test.rb +102 -0
  243. data/test/cases/timestamp_test.rb +501 -467
  244. data/test/cases/touch_later_test.rb +121 -0
  245. data/test/cases/transaction_callbacks_test.rb +518 -452
  246. data/test/cases/transaction_isolation_test.rb +106 -106
  247. data/test/cases/transactions_test.rb +834 -817
  248. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  249. data/test/cases/type/date_time_test.rb +14 -0
  250. data/test/cases/type/integer_test.rb +27 -121
  251. data/test/cases/type/string_test.rb +22 -36
  252. data/test/cases/type/type_map_test.rb +177 -177
  253. data/test/cases/type_test.rb +39 -0
  254. data/test/cases/types_test.rb +24 -141
  255. data/test/cases/unconnected_test.rb +33 -33
  256. data/test/cases/validations/absence_validation_test.rb +73 -0
  257. data/test/cases/validations/association_validation_test.rb +97 -86
  258. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  259. data/test/cases/validations/i18n_validation_test.rb +86 -90
  260. data/test/cases/validations/length_validation_test.rb +79 -47
  261. data/test/cases/validations/presence_validation_test.rb +103 -68
  262. data/test/cases/validations/uniqueness_validation_test.rb +548 -457
  263. data/test/cases/validations_repair_helper.rb +19 -23
  264. data/test/cases/validations_test.rb +194 -165
  265. data/test/cases/view_test.rb +216 -119
  266. data/test/cases/yaml_serialization_test.rb +121 -126
  267. data/test/config.example.yml +97 -0
  268. data/test/config.rb +5 -5
  269. data/test/fixtures/accounts.yml +29 -29
  270. data/test/fixtures/admin/accounts.yml +2 -2
  271. data/test/fixtures/admin/users.yml +10 -10
  272. data/test/fixtures/author_addresses.original +11 -0
  273. data/test/fixtures/author_addresses.yml +17 -17
  274. data/test/fixtures/author_favorites.yml +3 -3
  275. data/test/fixtures/authors.original +17 -0
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -0
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -11
  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 -0
  295. data/test/fixtures/content_positions.yml +3 -0
  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 -0
  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 -0
  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 -0
  333. data/test/fixtures/naked/yml/trees.yml +3 -0
  334. data/test/fixtures/nodes.yml +29 -0
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -0
  337. data/test/fixtures/other_dogs.yml +2 -0
  338. data/test/fixtures/other_posts.yml +7 -0
  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 +15 -12
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -7
  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 -0
  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/randomly_named_c1.rb +6 -2
  414. data/test/models/admin/user.rb +40 -40
  415. data/test/models/aircraft.rb +5 -4
  416. data/test/models/arunit2_model.rb +3 -3
  417. data/test/models/author.rb +209 -212
  418. data/test/models/auto_id.rb +4 -4
  419. data/test/models/autoloadable/extra_firm.rb +2 -2
  420. data/test/models/binary.rb +2 -2
  421. data/test/models/bird.rb +12 -12
  422. data/test/models/book.rb +23 -18
  423. data/test/models/boolean.rb +2 -2
  424. data/test/models/bulb.rb +52 -51
  425. data/test/models/cake_designer.rb +3 -3
  426. data/test/models/car.rb +29 -26
  427. data/test/models/carrier.rb +2 -2
  428. data/test/models/cat.rb +10 -0
  429. data/test/models/categorization.rb +19 -19
  430. data/test/models/category.rb +35 -35
  431. data/test/models/chef.rb +8 -7
  432. data/test/models/citation.rb +3 -3
  433. data/test/models/club.rb +25 -23
  434. data/test/models/college.rb +10 -10
  435. data/test/models/column.rb +3 -3
  436. data/test/models/column_name.rb +3 -3
  437. data/test/models/comment.rb +76 -64
  438. data/test/models/company.rb +230 -228
  439. data/test/models/company_in_module.rb +98 -98
  440. data/test/models/computer.rb +3 -3
  441. data/test/models/contact.rb +41 -41
  442. data/test/models/content.rb +40 -0
  443. data/test/models/contract.rb +20 -20
  444. data/test/models/country.rb +7 -7
  445. data/test/models/course.rb +6 -6
  446. data/test/models/customer.rb +83 -77
  447. data/test/models/customer_carrier.rb +14 -14
  448. data/test/models/dashboard.rb +3 -3
  449. data/test/models/default.rb +2 -2
  450. data/test/models/department.rb +4 -4
  451. data/test/models/developer.rb +274 -255
  452. data/test/models/dog.rb +5 -5
  453. data/test/models/dog_lover.rb +5 -5
  454. data/test/models/doubloon.rb +12 -12
  455. data/test/models/drink_designer.rb +3 -3
  456. data/test/models/edge.rb +5 -5
  457. data/test/models/electron.rb +5 -5
  458. data/test/models/engine.rb +4 -4
  459. data/test/models/entrant.rb +3 -3
  460. data/test/models/essay.rb +5 -5
  461. data/test/models/event.rb +3 -3
  462. data/test/models/eye.rb +37 -37
  463. data/test/models/face.rb +9 -9
  464. data/test/models/friendship.rb +6 -6
  465. data/test/models/guid.rb +2 -2
  466. data/test/models/guitar.rb +4 -0
  467. data/test/models/hotel.rb +11 -9
  468. data/test/models/image.rb +3 -3
  469. data/test/models/interest.rb +5 -5
  470. data/test/models/invoice.rb +4 -4
  471. data/test/models/item.rb +7 -7
  472. data/test/models/job.rb +7 -7
  473. data/test/models/joke.rb +7 -7
  474. data/test/models/keyboard.rb +3 -3
  475. data/test/models/legacy_thing.rb +3 -3
  476. data/test/models/lesson.rb +11 -11
  477. data/test/models/line_item.rb +3 -3
  478. data/test/models/liquid.rb +4 -4
  479. data/test/models/man.rb +11 -11
  480. data/test/models/matey.rb +4 -4
  481. data/test/models/member.rb +42 -41
  482. data/test/models/member_detail.rb +8 -7
  483. data/test/models/member_type.rb +3 -3
  484. data/test/models/membership.rb +35 -35
  485. data/test/models/mentor.rb +3 -0
  486. data/test/models/minimalistic.rb +2 -2
  487. data/test/models/minivan.rb +9 -9
  488. data/test/models/mixed_case_monkey.rb +3 -3
  489. data/test/models/mocktail_designer.rb +2 -0
  490. data/test/models/molecule.rb +6 -6
  491. data/test/models/movie.rb +5 -5
  492. data/test/models/node.rb +5 -0
  493. data/test/models/non_primary_key.rb +2 -0
  494. data/test/models/notification.rb +3 -0
  495. data/test/models/order.rb +4 -4
  496. data/test/models/organization.rb +14 -14
  497. data/test/models/other_dog.rb +5 -0
  498. data/test/models/owner.rb +37 -34
  499. data/test/models/parrot.rb +28 -29
  500. data/test/models/person.rb +142 -143
  501. data/test/models/personal_legacy_thing.rb +4 -4
  502. data/test/models/pet.rb +18 -15
  503. data/test/models/pet_treasure.rb +6 -0
  504. data/test/models/pirate.rb +92 -92
  505. data/test/models/possession.rb +3 -3
  506. data/test/models/post.rb +273 -264
  507. data/test/models/price_estimate.rb +4 -4
  508. data/test/models/professor.rb +5 -5
  509. data/test/models/project.rb +40 -31
  510. data/test/models/publisher.rb +2 -2
  511. data/test/models/publisher/article.rb +4 -4
  512. data/test/models/publisher/magazine.rb +3 -3
  513. data/test/models/randomly_named_c1.rb +1 -1
  514. data/test/models/rating.rb +4 -4
  515. data/test/models/reader.rb +23 -23
  516. data/test/models/recipe.rb +3 -0
  517. data/test/models/record.rb +2 -2
  518. data/test/models/reference.rb +22 -22
  519. data/test/models/reply.rb +61 -61
  520. data/test/models/ship.rb +39 -33
  521. data/test/models/ship_part.rb +8 -8
  522. data/test/models/shop.rb +17 -17
  523. data/test/models/shop_account.rb +6 -6
  524. data/test/models/speedometer.rb +6 -6
  525. data/test/models/sponsor.rb +7 -7
  526. data/test/models/string_key_object.rb +3 -3
  527. data/test/models/student.rb +4 -4
  528. data/test/models/subject.rb +16 -16
  529. data/test/models/subscriber.rb +8 -8
  530. data/test/models/subscription.rb +4 -4
  531. data/test/models/tag.rb +13 -7
  532. data/test/models/tagging.rb +13 -13
  533. data/test/models/task.rb +5 -5
  534. data/test/models/topic.rb +118 -124
  535. data/test/models/toy.rb +6 -6
  536. data/test/models/traffic_light.rb +4 -4
  537. data/test/models/treasure.rb +14 -14
  538. data/test/models/treaty.rb +7 -7
  539. data/test/models/tree.rb +3 -0
  540. data/test/models/tuning_peg.rb +4 -0
  541. data/test/models/tyre.rb +11 -11
  542. data/test/models/user.rb +14 -0
  543. data/test/models/uuid_child.rb +3 -3
  544. data/test/models/uuid_item.rb +6 -0
  545. data/test/models/uuid_parent.rb +3 -3
  546. data/test/models/vegetables.rb +24 -24
  547. data/test/models/vehicle.rb +6 -6
  548. data/test/models/vertex.rb +9 -9
  549. data/test/models/warehouse_thing.rb +5 -5
  550. data/test/models/wheel.rb +3 -3
  551. data/test/models/without_table.rb +3 -3
  552. data/test/models/zine.rb +3 -3
  553. data/test/schema/mysql2_specific_schema.rb +68 -58
  554. data/test/schema/oracle_specific_schema.rb +40 -43
  555. data/test/schema/postgresql_specific_schema.rb +114 -202
  556. data/test/schema/schema.rb +1057 -952
  557. data/test/schema/schema.rb.original +1057 -0
  558. data/test/schema/sqlite_specific_schema.rb +18 -22
  559. data/test/support/config.rb +43 -43
  560. data/test/support/connection.rb +23 -22
  561. data/test/support/connection_helper.rb +14 -14
  562. data/test/support/ddl_helper.rb +8 -8
  563. data/test/support/schema_dumping_helper.rb +20 -20
  564. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  565. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  566. metadata +129 -28
  567. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  568. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  569. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  570. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  571. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  572. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  573. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  574. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  575. data/test/cases/migration/table_and_index_test.rb +0 -24
  576. data/test/cases/relation/where_test2.rb +0 -36
  577. data/test/cases/type/decimal_test.rb +0 -56
  578. data/test/cases/type/unsigned_integer_test.rb +0 -18
  579. data/test/cases/xml_serialization_test.rb +0 -457
  580. data/test/connections/native_ibm_db/connection.rb +0 -44
  581. data/test/fixtures/naked/csv/accounts.csv +0 -1
  582. data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
  583. data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
  584. data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
  585. data/test/schema/mysql_specific_schema.rb +0 -70
  586. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,1815 +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
-
22
- class RelationTest < ActiveRecord::TestCase
23
- fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
24
- :tags, :taggings, :cars, :minivans, :author_addresses
25
-
26
- def test_do_not_double_quote_string_id
27
- van = Minivan.last
28
- assert van
29
- assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id
30
- end
31
-
32
- def test_do_not_double_quote_string_id_with_array
33
- van = Minivan.last
34
- assert van
35
- assert_equal van, Minivan.where(:minivan_id => [van]).to_a.first
36
- end
37
-
38
- def test_bind_values
39
- relation = Post.all
40
- assert_equal [], relation.bind_values
41
-
42
- relation2 = relation.bind 'foo'
43
- assert_equal %w{ foo }, relation2.bind_values
44
- assert_equal [], relation.bind_values
45
- end
46
-
47
- def test_two_scopes_with_includes_should_not_drop_any_include
48
- # heat habtm cache
49
- car = Car.incl_engines.incl_tyres.first
50
- car.tyres.length
51
- car.engines.length
52
-
53
- car = Car.incl_engines.incl_tyres.first
54
- assert_no_queries { car.tyres.length }
55
- assert_no_queries { car.engines.length }
56
- end
57
-
58
- def test_dynamic_finder
59
- x = Post.where('author_id = ?', 1)
60
- assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders'
61
- end
62
-
63
- def test_multivalue_where
64
- posts = Post.where('author_id = ? AND id = ?', 1, 1)
65
- assert_equal 1, posts.to_a.size
66
- end
67
-
68
- def test_scoped
69
- topics = Topic.all
70
- assert_kind_of ActiveRecord::Relation, topics
71
- assert_equal 5, topics.size
72
- end
73
-
74
- def test_to_json
75
- assert_nothing_raised { Bird.all.to_json }
76
- assert_nothing_raised { Bird.all.to_a.to_json }
77
- end
78
-
79
- def test_to_yaml
80
- assert_nothing_raised { Bird.all.to_yaml }
81
- assert_nothing_raised { Bird.all.to_a.to_yaml }
82
- end
83
-
84
- def test_to_xml
85
- assert_nothing_raised { Bird.all.to_xml }
86
- assert_nothing_raised { Bird.all.to_a.to_xml }
87
- end
88
-
89
- def test_scoped_all
90
- topics = Topic.all.to_a
91
- assert_kind_of Array, topics
92
- assert_no_queries { assert_equal 5, topics.size }
93
- end
94
-
95
- def test_loaded_all
96
- topics = Topic.all
97
-
98
- assert_queries(1) do
99
- 2.times { assert_equal 5, topics.to_a.size }
100
- end
101
-
102
- assert topics.loaded?
103
- end
104
-
105
- def test_scoped_first
106
- topics = Topic.all.order('id ASC')
107
-
108
- assert_queries(1) do
109
- 2.times { assert_equal "The First Topic", topics.first.title }
110
- end
111
-
112
- assert ! topics.loaded?
113
- end
114
-
115
- def test_loaded_first
116
- topics = Topic.all.order('id ASC')
117
-
118
- assert_queries(1) do
119
- topics.to_a # force load
120
- 2.times { assert_equal "The First Topic", topics.first.title }
121
- end
122
-
123
- assert topics.loaded?
124
- end
125
-
126
- def test_reload
127
- topics = Topic.all
128
-
129
- assert_queries(1) do
130
- 2.times { topics.to_a }
131
- end
132
-
133
- assert topics.loaded?
134
-
135
- original_size = topics.to_a.size
136
- Topic.create! :title => 'fake'
137
-
138
- assert_queries(1) { topics.reload }
139
- assert_equal original_size + 1, topics.size
140
- assert topics.loaded?
141
- end
142
-
143
- def test_finding_with_subquery
144
- relation = Topic.where(:approved => true)
145
- assert_equal relation.to_a, Topic.select('*').from(relation).to_a
146
- assert_equal relation.to_a, Topic.select('subquery.*').from(relation).to_a
147
- assert_equal relation.to_a, Topic.select('a.*').from(relation, :a).to_a
148
- end
149
-
150
- def test_finding_with_subquery_with_binds
151
- relation = Post.first.comments
152
- assert_equal relation.to_a, Comment.select('*').from(relation).to_a
153
- assert_equal relation.to_a, Comment.select('subquery.*').from(relation).to_a
154
- assert_equal relation.to_a, Comment.select('a.*').from(relation, :a).to_a
155
- end
156
-
157
- def test_finding_with_subquery_without_select_does_not_change_the_select
158
- relation = Topic.where(approved: true)
159
- assert_raises(ActiveRecord::StatementInvalid) do
160
- Topic.from(relation).to_a
161
- end
162
- end
163
-
164
- def test_select_with_subquery_in_from_does_not_use_original_table_name
165
- relation = Comment.group(:type).select('COUNT(post_id) AS post_count, type')
166
- subquery = Comment.from(relation).select('type','post_count')
167
- assert_equal(relation.map(&:post_count).sort,subquery.map(&:post_count).sort)
168
- end
169
-
170
- def test_group_with_subquery_in_from_does_not_use_original_table_name
171
- relation = Comment.group(:type).select('COUNT(post_id) AS post_count,type')
172
- subquery = Comment.from(relation).group('type').average("post_count")
173
- assert_equal(relation.map(&:post_count).sort,subquery.values.sort)
174
- end
175
-
176
- def test_finding_with_conditions
177
- assert_equal ["David"], Author.where(:name => 'David').map(&:name)
178
- assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name)
179
- assert_equal ['Mary'], Author.where("name = ?", 'Mary').map(&:name)
180
- end
181
-
182
- def test_finding_with_order
183
- topics = Topic.order('id')
184
- assert_equal 5, topics.to_a.size
185
- assert_equal topics(:first).title, topics.first.title
186
- end
187
-
188
- def test_finding_with_arel_order
189
- topics = Topic.order(Topic.arel_table[:id].asc)
190
- assert_equal 5, topics.to_a.size
191
- assert_equal topics(:first).title, topics.first.title
192
- end
193
-
194
- def test_finding_with_assoc_order
195
- topics = Topic.order(:id => :desc)
196
- assert_equal 5, topics.to_a.size
197
- assert_equal topics(:fifth).title, topics.first.title
198
- end
199
-
200
- def test_finding_with_reverted_assoc_order
201
- topics = Topic.order(:id => :asc).reverse_order
202
- assert_equal 5, topics.to_a.size
203
- assert_equal topics(:fifth).title, topics.first.title
204
- end
205
-
206
- def test_order_with_hash_and_symbol_generates_the_same_sql
207
- assert_equal Topic.order(:id).to_sql, Topic.order(:id => :asc).to_sql
208
- end
209
-
210
- def test_finding_with_desc_order_with_string
211
- topics = Topic.order(id: "desc")
212
- assert_equal 5, topics.to_a.size
213
- assert_equal [topics(:fifth), topics(:fourth), topics(:third), topics(:second), topics(:first)], topics.to_a
214
- end
215
-
216
- def test_finding_with_asc_order_with_string
217
- topics = Topic.order(id: 'asc')
218
- assert_equal 5, topics.to_a.size
219
- assert_equal [topics(:first), topics(:second), topics(:third), topics(:fourth), topics(:fifth)], topics.to_a
220
- end
221
-
222
- def test_support_upper_and_lower_case_directions
223
- assert_includes Topic.order(id: "ASC").to_sql, "ASC"
224
- assert_includes Topic.order(id: "asc").to_sql, "ASC"
225
- assert_includes Topic.order(id: :ASC).to_sql, "ASC"
226
- assert_includes Topic.order(id: :asc).to_sql, "ASC"
227
-
228
- assert_includes Topic.order(id: "DESC").to_sql, "DESC"
229
- assert_includes Topic.order(id: "desc").to_sql, "DESC"
230
- assert_includes Topic.order(id: :DESC).to_sql, "DESC"
231
- assert_includes Topic.order(id: :desc).to_sql,"DESC"
232
- end
233
-
234
- def test_raising_exception_on_invalid_hash_params
235
- e = assert_raise(ArgumentError) { Topic.order(:name, "id DESC", id: :asfsdf) }
236
- assert_equal 'Direction "asfsdf" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]', e.message
237
- end
238
-
239
- def test_finding_last_with_arel_order
240
- topics = Topic.order(Topic.arel_table[:id].asc)
241
- assert_equal topics(:fifth).title, topics.last.title
242
- end
243
-
244
- def test_finding_with_order_concatenated
245
- topics = Topic.order('author_name').order('title')
246
- assert_equal 5, topics.to_a.size
247
- assert_equal topics(:fourth).title, topics.first.title
248
- end
249
-
250
- def test_finding_with_order_by_aliased_attributes
251
- topics = Topic.order(:heading)
252
- assert_equal 5, topics.to_a.size
253
- assert_equal topics(:fifth).title, topics.first.title
254
- end
255
-
256
- def test_finding_with_assoc_order_by_aliased_attributes
257
- topics = Topic.order(heading: :desc)
258
- assert_equal 5, topics.to_a.size
259
- assert_equal topics(:third).title, topics.first.title
260
- end
261
-
262
- def test_finding_with_reorder
263
- topics = Topic.order('author_name').order('title').reorder('id').to_a
264
- topics_titles = topics.map{ |t| t.title }
265
- 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
266
- end
267
-
268
- def test_finding_with_reorder_by_aliased_attributes
269
- topics = Topic.order('author_name').reorder(:heading)
270
- assert_equal 5, topics.to_a.size
271
- assert_equal topics(:fifth).title, topics.first.title
272
- end
273
-
274
- def test_finding_with_assoc_reorder_by_aliased_attributes
275
- topics = Topic.order('author_name').reorder(heading: :desc)
276
- assert_equal 5, topics.to_a.size
277
- assert_equal topics(:third).title, topics.first.title
278
- end
279
-
280
- def test_finding_with_order_and_take
281
- entrants = Entrant.order("id ASC").limit(2).to_a
282
-
283
- assert_equal 2, entrants.size
284
- assert_equal entrants(:first).name, entrants.first.name
285
- end
286
-
287
- def test_finding_with_cross_table_order_and_limit
288
- tags = Tag.includes(:taggings).
289
- order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
290
- limit(1).to_a
291
- assert_equal 1, tags.length
292
- end
293
-
294
- def test_finding_with_complex_order_and_limit
295
- tags = Tag.includes(:taggings).references(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a
296
- assert_equal 1, tags.length
297
- end
298
-
299
- def test_finding_with_complex_order
300
- tags = Tag.includes(:taggings).references(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
301
- assert_equal 3, tags.length
302
- end
303
-
304
- def test_finding_with_order_limit_and_offset
305
- entrants = Entrant.order("id ASC").limit(2).offset(1)
306
-
307
- assert_equal 2, entrants.to_a.size
308
- assert_equal entrants(:second).name, entrants.first.name
309
-
310
- entrants = Entrant.order("id ASC").limit(2).offset(2)
311
- assert_equal 1, entrants.to_a.size
312
- assert_equal entrants(:third).name, entrants.first.name
313
- end
314
-
315
- def test_finding_with_group
316
- developers = Developer.group("salary").select("salary").to_a
317
- assert_equal 4, developers.size
318
- assert_equal 4, developers.map(&:salary).uniq.size
319
- end
320
-
321
- def test_select_with_block
322
- even_ids = Developer.all.select {|d| d.id % 2 == 0 }.map(&:id)
323
- assert_equal [2, 4, 6, 8, 10], even_ids.sort
324
- end
325
-
326
- def test_none
327
- assert_no_queries(ignore_none: false) do
328
- assert_equal [], Developer.none
329
- assert_equal [], Developer.all.none
330
- end
331
- end
332
-
333
- def test_none_chainable
334
- assert_no_queries(ignore_none: false) do
335
- assert_equal [], Developer.none.where(:name => 'David')
336
- end
337
- end
338
-
339
- def test_none_chainable_to_existing_scope_extension_method
340
- assert_no_queries(ignore_none: false) do
341
- assert_equal 1, Topic.anonymous_extension.none.one
342
- end
343
- end
344
-
345
- def test_none_chained_to_methods_firing_queries_straight_to_db
346
- assert_no_queries(ignore_none: false) do
347
- assert_equal [], Developer.none.pluck(:id, :name)
348
- assert_equal 0, Developer.none.delete_all
349
- assert_equal 0, Developer.none.update_all(:name => 'David')
350
- assert_equal 0, Developer.none.delete(1)
351
- assert_equal false, Developer.none.exists?(1)
352
- end
353
- end
354
-
355
- def test_null_relation_content_size_methods
356
- assert_no_queries(ignore_none: false) do
357
- assert_equal 0, Developer.none.size
358
- assert_equal 0, Developer.none.count
359
- assert_equal true, Developer.none.empty?
360
- assert_equal false, Developer.none.any?
361
- assert_equal false, Developer.none.many?
362
- end
363
- end
364
-
365
- def test_null_relation_calculations_methods
366
- assert_no_queries(ignore_none: false) do
367
- assert_equal 0, Developer.none.count
368
- assert_equal 0, Developer.none.calculate(:count, nil, {})
369
- assert_equal nil, Developer.none.calculate(:average, 'salary')
370
- end
371
- end
372
-
373
- def test_null_relation_metadata_methods
374
- assert_equal "", Developer.none.to_sql
375
- assert_equal({}, Developer.none.where_values_hash)
376
- end
377
-
378
- def test_null_relation_where_values_hash
379
- assert_equal({ 'salary' => 100_000 }, Developer.none.where(salary: 100_000).where_values_hash)
380
- end
381
-
382
- def test_null_relation_sum
383
- ac = Aircraft.new
384
- assert_equal Hash.new, ac.engines.group(:id).sum(:id)
385
- assert_equal 0, ac.engines.count
386
- ac.save
387
- assert_equal Hash.new, ac.engines.group(:id).sum(:id)
388
- assert_equal 0, ac.engines.count
389
- end
390
-
391
- def test_null_relation_count
392
- ac = Aircraft.new
393
- assert_equal Hash.new, ac.engines.group(:id).count
394
- assert_equal 0, ac.engines.count
395
- ac.save
396
- assert_equal Hash.new, ac.engines.group(:id).count
397
- assert_equal 0, ac.engines.count
398
- end
399
-
400
- def test_null_relation_size
401
- ac = Aircraft.new
402
- assert_equal Hash.new, ac.engines.group(:id).size
403
- assert_equal 0, ac.engines.size
404
- ac.save
405
- assert_equal Hash.new, ac.engines.group(:id).size
406
- assert_equal 0, ac.engines.size
407
- end
408
-
409
- def test_null_relation_average
410
- ac = Aircraft.new
411
- assert_equal Hash.new, ac.engines.group(:car_id).average(:id)
412
- assert_equal nil, ac.engines.average(:id)
413
- ac.save
414
- assert_equal Hash.new, ac.engines.group(:car_id).average(:id)
415
- assert_equal nil, ac.engines.average(:id)
416
- end
417
-
418
- def test_null_relation_minimum
419
- ac = Aircraft.new
420
- assert_equal Hash.new, ac.engines.group(:car_id).minimum(:id)
421
- assert_equal nil, ac.engines.minimum(:id)
422
- ac.save
423
- assert_equal Hash.new, ac.engines.group(:car_id).minimum(:id)
424
- assert_equal nil, ac.engines.minimum(:id)
425
- end
426
-
427
- def test_null_relation_maximum
428
- ac = Aircraft.new
429
- assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id)
430
- assert_equal nil, ac.engines.maximum(:id)
431
- ac.save
432
- assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id)
433
- assert_equal nil, ac.engines.maximum(:id)
434
- end
435
-
436
- def test_null_relation_in_where_condition
437
- assert_operator Comment.count, :>, 0 # precondition, make sure there are comments.
438
- assert_equal 0, Comment.where(post_id: Post.none).to_a.size
439
- end
440
-
441
- def test_joins_with_nil_argument
442
- assert_nothing_raised { DependentFirm.joins(nil).first }
443
- end
444
-
445
- def test_finding_with_hash_conditions_on_joined_table
446
- firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
447
- assert_equal 1, firms.size
448
- assert_equal companies(:rails_core), firms.first
449
- end
450
-
451
- def test_find_all_with_join
452
- developers_on_project_one = Developer.joins('LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id').
453
- where('project_id=1').to_a
454
-
455
- assert_equal 3, developers_on_project_one.length
456
- developer_names = developers_on_project_one.map { |d| d.name }
457
- assert developer_names.include?('David')
458
- assert developer_names.include?('Jamis')
459
- end
460
-
461
- def test_find_on_hash_conditions
462
- assert_equal Topic.all.merge!(:where => {:approved => false}).to_a, Topic.where({ :approved => false }).to_a
463
- end
464
-
465
- def test_joins_with_string_array
466
- person_with_reader_and_post = Post.joins([
467
- "INNER JOIN categorizations ON categorizations.post_id = posts.id",
468
- "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
469
- ]
470
- ).to_a
471
- assert_equal 1, person_with_reader_and_post.size
472
- end
473
-
474
- def test_no_arguments_to_query_methods_raise_errors
475
- assert_raises(ArgumentError) { Topic.references() }
476
- assert_raises(ArgumentError) { Topic.includes() }
477
- assert_raises(ArgumentError) { Topic.preload() }
478
- assert_raises(ArgumentError) { Topic.group() }
479
- assert_raises(ArgumentError) { Topic.reorder() }
480
- end
481
-
482
- def test_blank_like_arguments_to_query_methods_dont_raise_errors
483
- assert_nothing_raised { Topic.references([]) }
484
- assert_nothing_raised { Topic.includes([]) }
485
- assert_nothing_raised { Topic.preload([]) }
486
- assert_nothing_raised { Topic.group([]) }
487
- assert_nothing_raised { Topic.reorder([]) }
488
- end
489
-
490
- def test_scoped_responds_to_delegated_methods
491
- relation = Topic.all
492
-
493
- ["map", "uniq", "sort", "insert", "delete", "update"].each do |method|
494
- assert_respond_to relation, method, "Topic.all should respond to #{method.inspect}"
495
- end
496
- end
497
-
498
- def test_respond_to_delegates_to_relation
499
- relation = Topic.all
500
- fake_arel = Struct.new(:responds) {
501
- def respond_to? method, access = false
502
- responds << [method, access]
503
- end
504
- }.new []
505
-
506
- relation.extend(Module.new { attr_accessor :arel })
507
- relation.arel = fake_arel
508
-
509
- relation.respond_to?(:matching_attributes)
510
- assert_equal [:matching_attributes, false], fake_arel.responds.first
511
-
512
- fake_arel.responds = []
513
- relation.respond_to?(:matching_attributes, true)
514
- assert_equal [:matching_attributes, true], fake_arel.responds.first
515
- end
516
-
517
- def test_respond_to_dynamic_finders
518
- relation = Topic.all
519
-
520
- ["find_by_title", "find_by_title_and_author_name"].each do |method|
521
- assert_respond_to relation, method, "Topic.all should respond to #{method.inspect}"
522
- end
523
- end
524
-
525
- def test_respond_to_class_methods_and_scopes
526
- assert Topic.all.respond_to?(:by_lifo)
527
- end
528
-
529
- def test_find_with_readonly_option
530
- Developer.all.each { |d| assert !d.readonly? }
531
- Developer.all.readonly.each { |d| assert d.readonly? }
532
- end
533
-
534
- def test_eager_association_loading_of_stis_with_multiple_references
535
- authors = Author.eager_load(:posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } }).
536
- order('comments.body, very_special_comments_posts.body').where('posts.id = 4').to_a
537
-
538
- assert_equal [authors(:david)], authors
539
- assert_no_queries do
540
- authors.first.posts.first.special_comments.first.post.special_comments
541
- authors.first.posts.first.special_comments.first.post.very_special_comment
542
- end
543
- end
544
-
545
- def test_find_with_preloaded_associations
546
- assert_queries(2) do
547
- posts = Post.preload(:comments).order('posts.id')
548
- assert posts.first.comments.first
549
- end
550
-
551
- assert_queries(2) do
552
- posts = Post.preload(:comments).order('posts.id')
553
- assert posts.first.comments.first
554
- end
555
-
556
- assert_queries(2) do
557
- posts = Post.preload(:author).order('posts.id')
558
- assert posts.first.author
559
- end
560
-
561
- assert_queries(2) do
562
- posts = Post.preload(:author).order('posts.id')
563
- assert posts.first.author
564
- end
565
-
566
- assert_queries(3) do
567
- posts = Post.preload(:author, :comments).order('posts.id')
568
- assert posts.first.author
569
- assert posts.first.comments.first
570
- end
571
- end
572
-
573
- def test_preload_applies_to_all_chained_preloaded_scopes
574
- assert_queries(3) do
575
- post = Post.with_comments.with_tags.first
576
- assert post
577
- end
578
- end
579
-
580
- def test_find_with_included_associations
581
- assert_queries(2) do
582
- posts = Post.includes(:comments).order('posts.id')
583
- assert posts.first.comments.first
584
- end
585
-
586
- assert_queries(2) do
587
- posts = Post.all.includes(:comments).order('posts.id')
588
- assert posts.first.comments.first
589
- end
590
-
591
- assert_queries(2) do
592
- posts = Post.includes(:author).order('posts.id')
593
- assert posts.first.author
594
- end
595
-
596
- assert_queries(3) do
597
- posts = Post.includes(:author, :comments).order('posts.id')
598
- assert posts.first.author
599
- assert posts.first.comments.first
600
- end
601
- end
602
-
603
- def test_default_scope_with_conditions_string
604
- assert_equal Developer.where(name: 'David').map(&:id).sort, DeveloperCalledDavid.all.map(&:id).sort
605
- assert_nil DeveloperCalledDavid.create!.name
606
- end
607
-
608
- def test_default_scope_with_conditions_hash
609
- assert_equal Developer.where(name: 'Jamis').map(&:id).sort, DeveloperCalledJamis.all.map(&:id).sort
610
- assert_equal 'Jamis', DeveloperCalledJamis.create!.name
611
- end
612
-
613
- def test_default_scoping_finder_methods
614
- developers = DeveloperCalledDavid.order('id').map(&:id).sort
615
- assert_equal Developer.where(name: 'David').map(&:id).sort, developers
616
- end
617
-
618
- def test_includes_with_select
619
- query = Post.select('comments_count AS ranking').order('ranking').includes(:comments)
620
- .where(comments: { id: 1 })
621
-
622
- assert_equal ['comments_count AS ranking'], query.select_values
623
- assert_equal 1, query.to_a.size
624
- end
625
-
626
- def test_preloading_with_associations_and_merges
627
- post = Post.create! title: 'Uhuu', body: 'body'
628
- reader = Reader.create! post_id: post.id, person_id: 1
629
- comment = Comment.create! post_id: post.id, body: 'body'
630
-
631
- assert !comment.respond_to?(:readers)
632
-
633
- post_rel = Post.preload(:readers).joins(:readers).where(title: 'Uhuu')
634
- result_comment = Comment.joins(:post).merge(post_rel).to_a.first
635
- assert_equal comment, result_comment
636
-
637
- assert_no_queries do
638
- assert_equal post, result_comment.post
639
- assert_equal [reader], result_comment.post.readers.to_a
640
- end
641
-
642
- post_rel = Post.includes(:readers).where(title: 'Uhuu')
643
- result_comment = Comment.joins(:post).merge(post_rel).first
644
- assert_equal comment, result_comment
645
-
646
- assert_no_queries do
647
- assert_equal post, result_comment.post
648
- assert_equal [reader], result_comment.post.readers.to_a
649
- end
650
- end
651
-
652
- def test_preloading_with_associations_default_scopes_and_merges
653
- post = Post.create! title: 'Uhuu', body: 'body'
654
- reader = Reader.create! post_id: post.id, person_id: 1
655
-
656
- post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: 'Uhuu')
657
- result_post = PostWithPreloadDefaultScope.all.merge(post_rel).to_a.first
658
-
659
- assert_no_queries do
660
- assert_equal [reader], result_post.readers.to_a
661
- end
662
-
663
- post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: 'Uhuu')
664
- result_post = PostWithIncludesDefaultScope.all.merge(post_rel).to_a.first
665
-
666
- assert_no_queries do
667
- assert_equal [reader], result_post.readers.to_a
668
- end
669
- end
670
-
671
- def test_loading_with_one_association
672
- posts = Post.preload(:comments)
673
- post = posts.find { |p| p.id == 1 }
674
- assert_equal 2, post.comments.size
675
- assert post.comments.include?(comments(:greetings))
676
-
677
- post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
678
- assert_equal 2, post.comments.size
679
- assert post.comments.include?(comments(:greetings))
680
-
681
- posts = Post.preload(:last_comment)
682
- post = posts.find { |p| p.id == 1 }
683
- assert_equal Post.find(1).last_comment, post.last_comment
684
- end
685
-
686
- def test_to_sql_on_eager_join
687
- expected = assert_sql {
688
- Post.eager_load(:last_comment).order('comments.id DESC').to_a
689
- }.first
690
- actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
691
- assert_equal expected, actual
692
- end
693
-
694
- def test_to_sql_on_scoped_proxy
695
- auth = Author.first
696
- Post.where("1=1").written_by(auth)
697
- assert_not auth.posts.to_sql.include?("1=1")
698
- end
699
-
700
- def test_loading_with_one_association_with_non_preload
701
- posts = Post.eager_load(:last_comment).order('comments.id DESC')
702
- post = posts.find { |p| p.id == 1 }
703
- assert_equal Post.find(1).last_comment, post.last_comment
704
- end
705
-
706
- def test_dynamic_find_by_attributes
707
- david = authors(:david)
708
- author = Author.preload(:taggings).find_by_id(david.id)
709
- expected_taggings = taggings(:welcome_general, :thinking_general)
710
-
711
- assert_no_queries do
712
- assert_equal expected_taggings, author.taggings.distinct.sort_by { |t| t.id }
713
- assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
714
- end
715
-
716
- authors = Author.all
717
- assert_equal david, authors.find_by_id_and_name(david.id, david.name)
718
- assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
719
- end
720
-
721
- def test_dynamic_find_by_attributes_bang
722
- author = Author.all.find_by_id!(authors(:david).id)
723
- assert_equal "David", author.name
724
-
725
- assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, 'invalid') }
726
- end
727
-
728
- def test_find_id
729
- authors = Author.all
730
-
731
- david = authors.find(authors(:david).id)
732
- assert_equal 'David', david.name
733
-
734
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
735
- end
736
-
737
- def test_find_ids
738
- authors = Author.order('id ASC')
739
-
740
- results = authors.find(authors(:david).id, authors(:mary).id)
741
- assert_kind_of Array, results
742
- assert_equal 2, results.size
743
- assert_equal 'David', results[0].name
744
- assert_equal 'Mary', results[1].name
745
- assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
746
-
747
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
748
- assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
749
- end
750
-
751
- def test_find_in_empty_array
752
- authors = Author.all.where(:id => [])
753
- assert authors.to_a.blank?
754
- end
755
-
756
- def test_where_with_ar_object
757
- author = Author.first
758
- authors = Author.all.where(:id => author)
759
- assert_equal 1, authors.to_a.length
760
- end
761
-
762
- def test_find_with_list_of_ar
763
- author = Author.first
764
- authors = Author.find([author.id])
765
- assert_equal author, authors.first
766
- end
767
-
768
- class Mary < Author; end
769
-
770
- def test_find_by_classname
771
- Author.create!(:name => Mary.name)
772
- assert_equal 1, Author.where(:name => Mary).size
773
- end
774
-
775
- def test_find_by_id_with_list_of_ar
776
- author = Author.first
777
- authors = Author.find_by_id([author])
778
- assert_equal author, authors
779
- end
780
-
781
- def test_find_all_using_where_twice_should_or_the_relation
782
- david = authors(:david)
783
- relation = Author.unscoped
784
- relation = relation.where(:name => david.name)
785
- relation = relation.where(:name => 'Santiago')
786
- relation = relation.where(:id => david.id)
787
- assert_equal [], relation.to_a
788
- end
789
-
790
- def test_multi_where_ands_queries
791
- relation = Author.unscoped
792
- david = authors(:david)
793
- sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
794
- assert_match('AND', sql)
795
- end
796
-
797
- def test_find_all_with_multiple_should_use_and
798
- david = authors(:david)
799
- relation = [
800
- { :name => david.name },
801
- { :name => 'Santiago' },
802
- { :name => 'tenderlove' },
803
- ].inject(Author.unscoped) do |memo, param|
804
- memo.where(param)
805
- end
806
- assert_equal [], relation.to_a
807
- end
808
-
809
- def test_typecasting_where_with_array
810
- ids = Author.pluck(:id)
811
- slugs = ids.map { |id| "#{id}-as-a-slug" }
812
-
813
- assert_equal Author.all.to_a, Author.where(id: slugs).to_a
814
- end
815
-
816
- def test_find_all_using_where_with_relation
817
- david = authors(:david)
818
- # switching the lines below would succeed in current rails
819
- # assert_queries(2) {
820
- assert_queries(1) {
821
- relation = Author.where(:id => Author.where(:id => david.id))
822
- assert_equal [david], relation.to_a
823
- }
824
-
825
- assert_queries(1) {
826
- relation = Author.where('id in (?)', Author.where(id: david).select(:id))
827
- assert_equal [david], relation.to_a
828
- }
829
-
830
- assert_queries(1) do
831
- relation = Author.where('id in (:author_ids)', author_ids: Author.where(id: david).select(:id))
832
- assert_equal [david], relation.to_a
833
- end
834
- end
835
-
836
- def test_find_all_using_where_with_relation_with_bound_values
837
- david = authors(:david)
838
- davids_posts = david.posts.order(:id).to_a
839
-
840
- assert_queries(1) do
841
- relation = Post.where(id: david.posts.select(:id))
842
- assert_equal davids_posts, relation.order(:id).to_a
843
- end
844
-
845
- assert_queries(1) do
846
- relation = Post.where('id in (?)', david.posts.select(:id))
847
- assert_equal davids_posts, relation.order(:id).to_a, 'should process Relation as bind variables'
848
- end
849
-
850
- assert_queries(1) do
851
- relation = Post.where('id in (:post_ids)', post_ids: david.posts.select(:id))
852
- assert_equal davids_posts, relation.order(:id).to_a, 'should process Relation as named bind variables'
853
- end
854
- end
855
-
856
- def test_find_all_using_where_with_relation_and_alternate_primary_key
857
- cool_first = minivans(:cool_first)
858
- # switching the lines below would succeed in current rails
859
- # assert_queries(2) {
860
- assert_queries(1) {
861
- relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
862
- assert_equal [cool_first], relation.to_a
863
- }
864
- end
865
-
866
- def test_find_all_using_where_with_relation_does_not_alter_select_values
867
- david = authors(:david)
868
-
869
- subquery = Author.where(:id => david.id)
870
-
871
- assert_queries(1) {
872
- relation = Author.where(:id => subquery)
873
- assert_equal [david], relation.to_a
874
- }
875
-
876
- assert_equal 0, subquery.select_values.size
877
- end
878
-
879
- def test_find_all_using_where_with_relation_with_joins
880
- david = authors(:david)
881
- assert_queries(1) {
882
- relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
883
- assert_equal [david], relation.to_a
884
- }
885
- end
886
-
887
-
888
- def test_find_all_using_where_with_relation_with_select_to_build_subquery
889
- david = authors(:david)
890
- assert_queries(1) {
891
- relation = Author.where(:name => Author.where(:id => david.id).select(:name))
892
- assert_equal [david], relation.to_a
893
- }
894
- end
895
-
896
- def test_exists
897
- davids = Author.where(:name => 'David')
898
- assert davids.exists?
899
- assert davids.exists?(authors(:david).id)
900
- assert ! davids.exists?(authors(:mary).id)
901
- assert ! davids.exists?("42")
902
- assert ! davids.exists?(42)
903
- assert ! davids.exists?(davids.new.id)
904
-
905
- fake = Author.where(:name => 'fake author')
906
- assert ! fake.exists?
907
- assert ! fake.exists?(authors(:david).id)
908
- end
909
-
910
- def test_exists_uses_existing_scope
911
- post = authors(:david).posts.first
912
- authors = Author.includes(:posts).where(name: "David", posts: { id: post.id })
913
- assert authors.exists?(authors(:david).id)
914
- end
915
-
916
- def test_last
917
- authors = Author.all
918
- assert_equal authors(:bob), authors.last
919
- end
920
-
921
- def test_destroy_all
922
- davids = Author.where(:name => 'David')
923
-
924
- # Force load
925
- assert_equal [authors(:david)], davids.to_a
926
- assert davids.loaded?
927
-
928
- assert_difference('Author.count', -1) { davids.destroy_all }
929
-
930
- assert_equal [], davids.to_a
931
- assert davids.loaded?
932
- end
933
-
934
- def test_delete_all
935
- davids = Author.where(:name => 'David')
936
-
937
- assert_difference('Author.count', -1) { davids.delete_all }
938
- assert ! davids.loaded?
939
- end
940
-
941
- def test_delete_all_loaded
942
- davids = Author.where(:name => 'David')
943
-
944
- # Force load
945
- assert_equal [authors(:david)], davids.to_a
946
- assert davids.loaded?
947
-
948
- assert_difference('Author.count', -1) { davids.delete_all }
949
-
950
- assert_equal [], davids.to_a
951
- assert davids.loaded?
952
- end
953
-
954
- def test_delete_all_with_unpermitted_relation_raises_error
955
- assert_raises(ActiveRecord::ActiveRecordError) { Author.limit(10).delete_all }
956
- assert_raises(ActiveRecord::ActiveRecordError) { Author.uniq.delete_all }
957
- assert_raises(ActiveRecord::ActiveRecordError) { Author.group(:name).delete_all }
958
- assert_raises(ActiveRecord::ActiveRecordError) { Author.having('SUM(id) < 3').delete_all }
959
- assert_raises(ActiveRecord::ActiveRecordError) { Author.offset(10).delete_all }
960
- end
961
-
962
- def test_select_with_aggregates
963
- posts = Post.select(:title, :body)
964
-
965
- assert_equal 11, posts.count(:all)
966
- assert_equal 11, posts.size
967
- assert posts.any?
968
- assert posts.many?
969
- assert_not posts.empty?
970
- end
971
-
972
- def test_select_takes_a_variable_list_of_args
973
- david = developers(:david)
974
-
975
- developer = Developer.where(id: david.id).select(:name, :salary).first
976
- assert_equal david.name, developer.name
977
- assert_equal david.salary, developer.salary
978
- end
979
-
980
- def test_select_takes_an_aliased_attribute
981
- first = topics(:first)
982
-
983
- topic = Topic.where(id: first.id).select(:heading).first
984
- assert_equal first.heading, topic.heading
985
- end
986
-
987
- def test_select_argument_error
988
- assert_raises(ArgumentError) { Developer.select }
989
- end
990
-
991
- def test_count
992
- posts = Post.all
993
-
994
- assert_equal 11, posts.count
995
- assert_equal 11, posts.count(:all)
996
- assert_equal 11, posts.count(:id)
997
-
998
- assert_equal 1, posts.where('comments_count > 1').count
999
- assert_equal 9, posts.where(:comments_count => 0).count
1000
- end
1001
-
1002
- def test_count_on_association_relation
1003
- author = Author.last
1004
- another_author = Author.first
1005
- posts = Post.where(author_id: author.id)
1006
-
1007
- assert_equal author.posts.where(author_id: author.id).size, posts.count
1008
-
1009
- assert_equal 0, author.posts.where(author_id: another_author.id).size
1010
- assert author.posts.where(author_id: another_author.id).empty?
1011
- end
1012
-
1013
- def test_count_with_distinct
1014
- posts = Post.all
1015
-
1016
- assert_equal 3, posts.distinct(true).count(:comments_count)
1017
- assert_equal 11, posts.distinct(false).count(:comments_count)
1018
-
1019
- assert_equal 3, posts.distinct(true).select(:comments_count).count
1020
- assert_equal 11, posts.distinct(false).select(:comments_count).count
1021
- end
1022
-
1023
- def test_update_all_with_scope
1024
- tag = Tag.first
1025
- Post.tagged_with(tag.id).update_all title: "rofl"
1026
- list = Post.tagged_with(tag.id).all.to_a
1027
- assert_operator list.length, :>, 0
1028
- list.each { |post| assert_equal 'rofl', post.title }
1029
- end
1030
-
1031
- def test_count_explicit_columns
1032
- Post.update_all(:comments_count => nil)
1033
- posts = Post.all
1034
-
1035
- assert_equal [0], posts.select('comments_count').where('id is not null').group('id').order('id').count.values.uniq
1036
- assert_equal 0, posts.where('id is not null').select('comments_count').count
1037
-
1038
- assert_equal 11, posts.select('comments_count').count('id')
1039
- assert_equal 0, posts.select('comments_count').count
1040
- assert_equal 0, posts.count(:comments_count)
1041
- assert_equal 0, posts.count('comments_count')
1042
- end
1043
-
1044
- def test_multiple_selects
1045
- post = Post.all.select('comments_count').select('title').order("id ASC").first
1046
- assert_equal "Welcome to the weblog", post.title
1047
- assert_equal 2, post.comments_count
1048
- end
1049
-
1050
- def test_size
1051
- posts = Post.all
1052
-
1053
- assert_queries(1) { assert_equal 11, posts.size }
1054
- assert ! posts.loaded?
1055
-
1056
- best_posts = posts.where(:comments_count => 0)
1057
- best_posts.to_a # force load
1058
- assert_no_queries { assert_equal 9, best_posts.size }
1059
- end
1060
-
1061
- def test_size_with_limit
1062
- posts = Post.limit(10)
1063
-
1064
- assert_queries(1) { assert_equal 10, posts.size }
1065
- assert ! posts.loaded?
1066
-
1067
- best_posts = posts.where(:comments_count => 0)
1068
- best_posts.to_a # force load
1069
- assert_no_queries { assert_equal 9, best_posts.size }
1070
- end
1071
-
1072
- def test_size_with_zero_limit
1073
- posts = Post.limit(0)
1074
-
1075
- assert_no_queries { assert_equal 0, posts.size }
1076
- assert ! posts.loaded?
1077
-
1078
- posts.to_a # force load
1079
- assert_no_queries { assert_equal 0, posts.size }
1080
- end
1081
-
1082
- def test_empty_with_zero_limit
1083
- posts = Post.limit(0)
1084
-
1085
- assert_no_queries { assert_equal true, posts.empty? }
1086
- assert ! posts.loaded?
1087
- end
1088
-
1089
- def test_count_complex_chained_relations
1090
- posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
1091
-
1092
- expected = { 1 => 2 }
1093
- assert_equal expected, posts.count
1094
- end
1095
-
1096
- def test_empty
1097
- posts = Post.all
1098
-
1099
- assert_queries(1) { assert_equal false, posts.empty? }
1100
- assert ! posts.loaded?
1101
-
1102
- no_posts = posts.where(:title => "")
1103
- assert_queries(1) { assert_equal true, no_posts.empty? }
1104
- assert ! no_posts.loaded?
1105
-
1106
- best_posts = posts.where(:comments_count => 0)
1107
- best_posts.to_a # force load
1108
- assert_no_queries { assert_equal false, best_posts.empty? }
1109
- end
1110
-
1111
- def test_empty_complex_chained_relations
1112
- posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
1113
-
1114
- assert_queries(1) { assert_equal false, posts.empty? }
1115
- assert ! posts.loaded?
1116
-
1117
- no_posts = posts.where(:title => "")
1118
- assert_queries(1) { assert_equal true, no_posts.empty? }
1119
- assert ! no_posts.loaded?
1120
- end
1121
-
1122
- def test_any
1123
- posts = Post.all
1124
-
1125
- # This test was failing when run on its own (as opposed to running the entire suite).
1126
- # The second line in the assert_queries block was causing visit_Arel_Attributes_Attribute
1127
- # in Arel::Visitors::ToSql to trigger a SHOW TABLES query. Running that line here causes
1128
- # the SHOW TABLES result to be cached so we don't have to do it again in the block.
1129
- #
1130
- # This is obviously a rubbish fix but it's the best I can come up with for now...
1131
- posts.where(:id => nil).any?
1132
-
1133
- assert_queries(3) do
1134
- assert posts.any? # Uses COUNT()
1135
- assert ! posts.where(:id => nil).any?
1136
-
1137
- assert posts.any? {|p| p.id > 0 }
1138
- assert ! posts.any? {|p| p.id <= 0 }
1139
- end
1140
-
1141
- assert posts.loaded?
1142
- end
1143
-
1144
- def test_many
1145
- posts = Post.all
1146
-
1147
- assert_queries(2) do
1148
- assert posts.many? # Uses COUNT()
1149
- assert posts.many? {|p| p.id > 0 }
1150
- assert ! posts.many? {|p| p.id < 2 }
1151
- end
1152
-
1153
- assert posts.loaded?
1154
- end
1155
-
1156
- def test_many_with_limits
1157
- posts = Post.all
1158
-
1159
- assert posts.many?
1160
- assert ! posts.limit(1).many?
1161
- end
1162
-
1163
- def test_build
1164
- posts = Post.all
1165
-
1166
- post = posts.new
1167
- assert_kind_of Post, post
1168
- end
1169
-
1170
- def test_scoped_build
1171
- posts = Post.where(:title => 'You told a lie')
1172
-
1173
- post = posts.new
1174
- assert_kind_of Post, post
1175
- assert_equal 'You told a lie', post.title
1176
- end
1177
-
1178
- def test_create
1179
- birds = Bird.all
1180
-
1181
- sparrow = birds.create
1182
- assert_kind_of Bird, sparrow
1183
- assert !sparrow.persisted?
1184
-
1185
- hen = birds.where(:name => 'hen').create
1186
- assert hen.persisted?
1187
- assert_equal 'hen', hen.name
1188
- end
1189
-
1190
- def test_create_bang
1191
- birds = Bird.all
1192
-
1193
- assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
1194
-
1195
- hen = birds.where(:name => 'hen').create!
1196
- assert_kind_of Bird, hen
1197
- assert hen.persisted?
1198
- assert_equal 'hen', hen.name
1199
- end
1200
-
1201
- def test_first_or_create
1202
- parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
1203
- assert_kind_of Bird, parrot
1204
- assert parrot.persisted?
1205
- assert_equal 'parrot', parrot.name
1206
- assert_equal 'green', parrot.color
1207
-
1208
- same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
1209
- assert_kind_of Bird, same_parrot
1210
- assert same_parrot.persisted?
1211
- assert_equal parrot, same_parrot
1212
- end
1213
-
1214
- def test_first_or_create_with_no_parameters
1215
- parrot = Bird.where(:color => 'green').first_or_create
1216
- assert_kind_of Bird, parrot
1217
- assert !parrot.persisted?
1218
- assert_equal 'green', parrot.color
1219
- end
1220
-
1221
- def test_first_or_create_with_block
1222
- parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
1223
- assert_kind_of Bird, parrot
1224
- assert parrot.persisted?
1225
- assert_equal 'green', parrot.color
1226
- assert_equal 'parrot', parrot.name
1227
-
1228
- same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
1229
- assert_equal parrot, same_parrot
1230
- end
1231
-
1232
- def test_first_or_create_with_array
1233
- several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
1234
- assert_kind_of Array, several_green_birds
1235
- several_green_birds.each { |bird| assert bird.persisted? }
1236
-
1237
- same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
1238
- assert_kind_of Bird, same_parrot
1239
- assert_equal several_green_birds.first, same_parrot
1240
- end
1241
-
1242
- def test_first_or_create_bang_with_valid_options
1243
- parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
1244
- assert_kind_of Bird, parrot
1245
- assert parrot.persisted?
1246
- assert_equal 'parrot', parrot.name
1247
- assert_equal 'green', parrot.color
1248
-
1249
- same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
1250
- assert_kind_of Bird, same_parrot
1251
- assert same_parrot.persisted?
1252
- assert_equal parrot, same_parrot
1253
- end
1254
-
1255
- def test_first_or_create_bang_with_invalid_options
1256
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
1257
- end
1258
-
1259
- def test_first_or_create_bang_with_no_parameters
1260
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
1261
- end
1262
-
1263
- def test_first_or_create_bang_with_valid_block
1264
- parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
1265
- assert_kind_of Bird, parrot
1266
- assert parrot.persisted?
1267
- assert_equal 'green', parrot.color
1268
- assert_equal 'parrot', parrot.name
1269
-
1270
- same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
1271
- assert_equal parrot, same_parrot
1272
- end
1273
-
1274
- def test_first_or_create_bang_with_invalid_block
1275
- assert_raise(ActiveRecord::RecordInvalid) do
1276
- Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
1277
- end
1278
- end
1279
-
1280
- def test_first_or_create_with_valid_array
1281
- several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
1282
- assert_kind_of Array, several_green_birds
1283
- several_green_birds.each { |bird| assert bird.persisted? }
1284
-
1285
- same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
1286
- assert_kind_of Bird, same_parrot
1287
- assert_equal several_green_birds.first, same_parrot
1288
- end
1289
-
1290
- def test_first_or_create_with_invalid_array
1291
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) }
1292
- end
1293
-
1294
- def test_first_or_initialize
1295
- parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
1296
- assert_kind_of Bird, parrot
1297
- assert !parrot.persisted?
1298
- assert parrot.valid?
1299
- assert parrot.new_record?
1300
- assert_equal 'parrot', parrot.name
1301
- assert_equal 'green', parrot.color
1302
- end
1303
-
1304
- def test_first_or_initialize_with_no_parameters
1305
- parrot = Bird.where(:color => 'green').first_or_initialize
1306
- assert_kind_of Bird, parrot
1307
- assert !parrot.persisted?
1308
- assert !parrot.valid?
1309
- assert parrot.new_record?
1310
- assert_equal 'green', parrot.color
1311
- end
1312
-
1313
- def test_first_or_initialize_with_block
1314
- parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
1315
- assert_kind_of Bird, parrot
1316
- assert !parrot.persisted?
1317
- assert parrot.valid?
1318
- assert parrot.new_record?
1319
- assert_equal 'green', parrot.color
1320
- assert_equal 'parrot', parrot.name
1321
- end
1322
-
1323
- def test_find_or_create_by
1324
- assert_nil Bird.find_by(name: 'bob')
1325
-
1326
- bird = Bird.find_or_create_by(name: 'bob')
1327
- assert bird.persisted?
1328
-
1329
- assert_equal bird, Bird.find_or_create_by(name: 'bob')
1330
- end
1331
-
1332
- def test_find_or_create_by_with_create_with
1333
- assert_nil Bird.find_by(name: 'bob')
1334
-
1335
- bird = Bird.create_with(color: 'green').find_or_create_by(name: 'bob')
1336
- assert bird.persisted?
1337
- assert_equal 'green', bird.color
1338
-
1339
- assert_equal bird, Bird.create_with(color: 'blue').find_or_create_by(name: 'bob')
1340
- end
1341
-
1342
- def test_find_or_create_by!
1343
- assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: 'green') }
1344
- end
1345
-
1346
- def test_find_or_initialize_by
1347
- assert_nil Bird.find_by(name: 'bob')
1348
-
1349
- bird = Bird.find_or_initialize_by(name: 'bob')
1350
- assert bird.new_record?
1351
- bird.save!
1352
-
1353
- assert_equal bird, Bird.find_or_initialize_by(name: 'bob')
1354
- end
1355
-
1356
- def test_explicit_create_scope
1357
- hens = Bird.where(:name => 'hen')
1358
- assert_equal 'hen', hens.new.name
1359
-
1360
- hens = hens.create_with(:name => 'cock')
1361
- assert_equal 'cock', hens.new.name
1362
- end
1363
-
1364
- def test_except
1365
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1366
- assert_equal [posts(:welcome)], relation.to_a
1367
-
1368
- author_posts = relation.except(:order, :limit)
1369
- assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1370
-
1371
- all_posts = relation.except(:where, :order, :limit)
1372
- assert_equal Post.all, all_posts
1373
- end
1374
-
1375
- def test_only
1376
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1377
- assert_equal [posts(:welcome)], relation.to_a
1378
-
1379
- author_posts = relation.only(:where)
1380
- assert_equal Post.where(:author_id => 1).to_a, author_posts.to_a
1381
-
1382
- all_posts = relation.only(:limit)
1383
- assert_equal Post.limit(1).to_a.first, all_posts.first
1384
- end
1385
-
1386
- def test_anonymous_extension
1387
- relation = Post.where(:author_id => 1).order('id ASC').extending do
1388
- def author
1389
- 'lifo'
1390
- end
1391
- end
1392
-
1393
- assert_equal "lifo", relation.author
1394
- assert_equal "lifo", relation.limit(1).author
1395
- end
1396
-
1397
- def test_named_extension
1398
- relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
1399
- assert_equal "lifo", relation.author
1400
- assert_equal "lifo", relation.limit(1).author
1401
- end
1402
-
1403
- def test_order_by_relation_attribute
1404
- assert_equal Post.order(Post.arel_table[:title]).to_a, Post.order("title").to_a
1405
- end
1406
-
1407
- def test_default_scope_order_with_scope_order
1408
- assert_equal 'zyke', CoolCar.order_using_new_style.limit(1).first.name
1409
- assert_equal 'zyke', FastCar.order_using_new_style.limit(1).first.name
1410
- end
1411
-
1412
- def test_order_using_scoping
1413
- car1 = CoolCar.order('id DESC').scoping do
1414
- CoolCar.all.merge!(order: 'id asc').first
1415
- end
1416
- assert_equal 'zyke', car1.name
1417
-
1418
- car2 = FastCar.order('id DESC').scoping do
1419
- FastCar.all.merge!(order: 'id asc').first
1420
- end
1421
- assert_equal 'zyke', car2.name
1422
- end
1423
-
1424
- def test_unscoped_block_style
1425
- assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name}
1426
- assert_equal 'honda', FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name}
1427
- end
1428
-
1429
- def test_intersection_with_array
1430
- relation = Author.where(:name => "David")
1431
- rails_author = relation.first
1432
-
1433
- assert_equal [rails_author], [rails_author] & relation
1434
- assert_equal [rails_author], relation & [rails_author]
1435
- end
1436
-
1437
- def test_primary_key
1438
- assert_equal "id", Post.all.primary_key
1439
- end
1440
-
1441
- def test_disable_implicit_join_references_is_deprecated
1442
- assert_deprecated do
1443
- ActiveRecord::Base.disable_implicit_join_references = true
1444
- end
1445
- end
1446
-
1447
- def test_ordering_with_extra_spaces
1448
- assert_equal authors(:david), Author.order('id DESC , name DESC').last
1449
- end
1450
-
1451
- def test_update_all_with_blank_argument
1452
- assert_raises(ArgumentError) { Comment.update_all({}) }
1453
- end
1454
-
1455
- def test_update_all_with_joins
1456
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1457
- count = comments.count
1458
-
1459
- assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
1460
- assert_equal posts(:thinking), comments(:greetings).post
1461
- end
1462
-
1463
- def test_update_all_with_joins_and_limit
1464
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).limit(1)
1465
- assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1466
- end
1467
-
1468
- def test_update_all_with_joins_and_limit_and_order
1469
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('comments.id').limit(1)
1470
- assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1471
- assert_equal posts(:thinking), comments(:greetings).post
1472
- assert_equal posts(:welcome), comments(:more_greetings).post
1473
- end
1474
-
1475
- unless current_adapter?(:IBM_DBAdapter)
1476
- #IBM_DB does not support offset on subselect of the update statement
1477
- def test_update_all_with_joins_and_offset
1478
- all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1479
- count = all_comments.count
1480
- comments = all_comments.offset(1)
1481
-
1482
- assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1483
- end
1484
-
1485
- def test_update_all_with_joins_and_offset_and_order
1486
- all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id')
1487
- count = all_comments.count
1488
- comments = all_comments.offset(1)
1489
-
1490
- assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1491
- assert_equal posts(:thinking), comments(:more_greetings).post
1492
- assert_equal posts(:welcome), comments(:greetings).post
1493
- end
1494
- end
1495
-
1496
- def test_distinct
1497
- tag1 = Tag.create(:name => 'Foo')
1498
- tag2 = Tag.create(:name => 'Foo')
1499
-
1500
- query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
1501
-
1502
- assert_equal ['Foo', 'Foo'], query.map(&:name)
1503
- assert_sql(/DISTINCT/) do
1504
- assert_equal ['Foo'], query.distinct.map(&:name)
1505
- assert_equal ['Foo'], query.uniq.map(&:name)
1506
- end
1507
- assert_sql(/DISTINCT/) do
1508
- assert_equal ['Foo'], query.distinct(true).map(&:name)
1509
- assert_equal ['Foo'], query.uniq(true).map(&:name)
1510
- end
1511
- assert_equal ['Foo', 'Foo'], query.distinct(true).distinct(false).map(&:name)
1512
- assert_equal ['Foo', 'Foo'], query.uniq(true).uniq(false).map(&:name)
1513
- end
1514
-
1515
- def test_doesnt_add_having_values_if_options_are_blank
1516
- scope = Post.having('')
1517
- assert_equal [], scope.having_values
1518
-
1519
- scope = Post.having([])
1520
- assert_equal [], scope.having_values
1521
- end
1522
-
1523
- def test_grouping_by_column_with_reserved_name
1524
- assert_equal [], Possession.select(:where).group(:where).to_a
1525
- end
1526
-
1527
- def test_references_triggers_eager_loading
1528
- scope = Post.includes(:comments)
1529
- assert !scope.eager_loading?
1530
- assert scope.references(:comments).eager_loading?
1531
- end
1532
-
1533
- def test_references_doesnt_trigger_eager_loading_if_reference_not_included
1534
- scope = Post.references(:comments)
1535
- assert !scope.eager_loading?
1536
- end
1537
-
1538
- def test_automatically_added_where_references
1539
- scope = Post.where(:comments => { :body => "Bla" })
1540
- assert_equal ['comments'], scope.references_values
1541
-
1542
- scope = Post.where('comments.body' => 'Bla')
1543
- assert_equal ['comments'], scope.references_values
1544
- end
1545
-
1546
- def test_automatically_added_where_not_references
1547
- scope = Post.where.not(comments: { body: "Bla" })
1548
- assert_equal ['comments'], scope.references_values
1549
-
1550
- scope = Post.where.not('comments.body' => 'Bla')
1551
- assert_equal ['comments'], scope.references_values
1552
- end
1553
-
1554
- def test_automatically_added_having_references
1555
- scope = Post.having(:comments => { :body => "Bla" })
1556
- assert_equal ['comments'], scope.references_values
1557
-
1558
- scope = Post.having('comments.body' => 'Bla')
1559
- assert_equal ['comments'], scope.references_values
1560
- end
1561
-
1562
- def test_automatically_added_order_references
1563
- scope = Post.order('comments.body')
1564
- assert_equal ['comments'], scope.references_values
1565
-
1566
- scope = Post.order('comments.body', 'yaks.body')
1567
- assert_equal ['comments', 'yaks'], scope.references_values
1568
-
1569
- # Don't infer yaks, let's not go down that road again...
1570
- scope = Post.order('comments.body, yaks.body')
1571
- assert_equal ['comments'], scope.references_values
1572
-
1573
- scope = Post.order('comments.body asc')
1574
- assert_equal ['comments'], scope.references_values
1575
-
1576
- scope = Post.order('foo(comments.body)')
1577
- assert_equal [], scope.references_values
1578
- end
1579
-
1580
- def test_automatically_added_reorder_references
1581
- scope = Post.reorder('comments.body')
1582
- assert_equal %w(comments), scope.references_values
1583
-
1584
- scope = Post.reorder('comments.body', 'yaks.body')
1585
- assert_equal %w(comments yaks), scope.references_values
1586
-
1587
- # Don't infer yaks, let's not go down that road again...
1588
- scope = Post.reorder('comments.body, yaks.body')
1589
- assert_equal %w(comments), scope.references_values
1590
-
1591
- scope = Post.reorder('comments.body asc')
1592
- assert_equal %w(comments), scope.references_values
1593
-
1594
- scope = Post.reorder('foo(comments.body)')
1595
- assert_equal [], scope.references_values
1596
- end
1597
-
1598
- def test_order_with_reorder_nil_removes_the_order
1599
- relation = Post.order(:title).reorder(nil)
1600
-
1601
- assert_nil relation.order_values.first
1602
- end
1603
-
1604
- def test_reverse_order_with_reorder_nil_removes_the_order
1605
- relation = Post.order(:title).reverse_order.reorder(nil)
1606
-
1607
- assert_nil relation.order_values.first
1608
- end
1609
-
1610
- def test_presence
1611
- topics = Topic.all
1612
-
1613
- # the first query is triggered because there are no topics yet.
1614
- assert_queries(1) { assert topics.present? }
1615
-
1616
- # checking if there are topics is used before you actually display them,
1617
- # thus it shouldn't invoke an extra count query.
1618
- assert_no_queries { assert topics.present? }
1619
- assert_no_queries { assert !topics.blank? }
1620
-
1621
- # shows count of topics and loops after loading the query should not trigger extra queries either.
1622
- assert_no_queries { topics.size }
1623
- assert_no_queries { topics.length }
1624
- assert_no_queries { topics.each }
1625
-
1626
- # count always trigger the COUNT query.
1627
- assert_queries(1) { topics.count }
1628
-
1629
- assert topics.loaded?
1630
- end
1631
-
1632
- test "find_by with hash conditions returns the first matching record" do
1633
- assert_equal posts(:eager_other), Post.order(:id).find_by(author_id: 2)
1634
- end
1635
-
1636
- test "find_by with non-hash conditions returns the first matching record" do
1637
- assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = 2")
1638
- end
1639
-
1640
- test "find_by with multi-arg conditions returns the first matching record" do
1641
- assert_equal posts(:eager_other), Post.order(:id).find_by('author_id = ?', 2)
1642
- end
1643
-
1644
- test "find_by returns nil if the record is missing" do
1645
- assert_equal nil, Post.all.find_by("1 = 0")
1646
- end
1647
-
1648
- test "find_by doesn't have implicit ordering" do
1649
- assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
1650
- end
1651
-
1652
- test "find_by! with hash conditions returns the first matching record" do
1653
- assert_equal posts(:eager_other), Post.order(:id).find_by!(author_id: 2)
1654
- end
1655
-
1656
- test "find_by! with non-hash conditions returns the first matching record" do
1657
- assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = 2")
1658
- end
1659
-
1660
- test "find_by! with multi-arg conditions returns the first matching record" do
1661
- assert_equal posts(:eager_other), Post.order(:id).find_by!('author_id = ?', 2)
1662
- end
1663
-
1664
- test "find_by! doesn't have implicit ordering" do
1665
- assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
1666
- end
1667
-
1668
- test "find_by! raises RecordNotFound if the record is missing" do
1669
- assert_raises(ActiveRecord::RecordNotFound) do
1670
- Post.all.find_by!("1 = 0")
1671
- end
1672
- end
1673
-
1674
- test "loaded relations cannot be mutated by multi value methods" do
1675
- relation = Post.all
1676
- relation.to_a
1677
-
1678
- assert_raises(ActiveRecord::ImmutableRelation) do
1679
- relation.where! 'foo'
1680
- end
1681
- end
1682
-
1683
- test "loaded relations cannot be mutated by single value methods" do
1684
- relation = Post.all
1685
- relation.to_a
1686
-
1687
- assert_raises(ActiveRecord::ImmutableRelation) do
1688
- relation.limit! 5
1689
- end
1690
- end
1691
-
1692
- test "loaded relations cannot be mutated by merge!" do
1693
- relation = Post.all
1694
- relation.to_a
1695
-
1696
- assert_raises(ActiveRecord::ImmutableRelation) do
1697
- relation.merge! where: 'foo'
1698
- end
1699
- end
1700
-
1701
- test "loaded relations cannot be mutated by extending!" do
1702
- relation = Post.all
1703
- relation.to_a
1704
-
1705
- assert_raises(ActiveRecord::ImmutableRelation) do
1706
- relation.extending! Module.new
1707
- end
1708
- end
1709
-
1710
- test "relations show the records in #inspect" do
1711
- relation = Post.limit(2)
1712
- assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
1713
- end
1714
-
1715
- test "relations limit the records in #inspect at 10" do
1716
- relation = Post.limit(11)
1717
- assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
1718
- end
1719
-
1720
- test "already-loaded relations don't perform a new query in #inspect" do
1721
- relation = Post.limit(2)
1722
- relation.to_a
1723
-
1724
- expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>"
1725
-
1726
- assert_no_queries do
1727
- assert_equal expected, relation.inspect
1728
- end
1729
- end
1730
-
1731
- test 'using a custom table affects the wheres' do
1732
- table_alias = Post.arel_table.alias('omg_posts')
1733
-
1734
- relation = ActiveRecord::Relation.new Post, table_alias
1735
- relation.where!(:foo => "bar")
1736
-
1737
- node = relation.arel.constraints.first.grep(Arel::Attributes::Attribute).first
1738
- assert_equal table_alias, node.relation
1739
- end
1740
-
1741
- test '#load' do
1742
- relation = Post.all
1743
- assert_queries(1) do
1744
- assert_equal relation, relation.load
1745
- end
1746
- assert_no_queries { relation.to_a }
1747
- end
1748
-
1749
- test 'group with select and includes' do
1750
- authors_count = Post.select('author_id, COUNT(author_id) AS num_posts').
1751
- group('author_id').order('author_id').includes(:author).to_a
1752
-
1753
- assert_no_queries do
1754
- result = authors_count.map do |post|
1755
- [post.num_posts, post.author.try(:name)]
1756
- end
1757
-
1758
- expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
1759
- assert_equal expected, result
1760
- end
1761
- end
1762
-
1763
- test "joins with select" do
1764
- posts = Post.joins(:author).select("id", "authors.author_address_id").order("posts.id").limit(3)
1765
- assert_equal [1, 2, 4], posts.map(&:id)
1766
- assert_equal [1, 1, 1], posts.map(&:author_address_id)
1767
- end
1768
-
1769
- test "delegations do not leak to other classes" do
1770
- Topic.all.by_lifo
1771
- assert Topic.all.class.method_defined?(:by_lifo)
1772
- assert !Post.all.respond_to?(:by_lifo)
1773
- end
1774
-
1775
- def test_unscope_removes_binds
1776
- left = Post.where(id: Arel::Nodes::BindParam.new)
1777
- column = Post.columns_hash['id']
1778
- left.bind_values += [[column, 20]]
1779
-
1780
- relation = left.unscope(where: :id)
1781
- assert_equal [], relation.bind_values
1782
- end
1783
-
1784
- def test_merging_removes_rhs_bind_parameters
1785
- left = Post.where(id: 20)
1786
- right = Post.where(id: [1,2,3,4])
1787
-
1788
- merged = left.merge(right)
1789
- assert_equal [], merged.bind_values
1790
- end
1791
-
1792
- def test_merging_keeps_lhs_bind_parameters
1793
- column = Post.columns_hash['id']
1794
- binds = [[column, 20]]
1795
-
1796
- right = Post.where(id: 20)
1797
- left = Post.where(id: 10)
1798
-
1799
- merged = left.merge(right)
1800
- assert_equal binds, merged.bind_values
1801
- end
1802
-
1803
- def test_merging_reorders_bind_params
1804
- post = Post.first
1805
- right = Post.where(id: post.id)
1806
- left = Post.where(title: post.title)
1807
-
1808
- merged = left.merge(right)
1809
- assert_equal post, merged.first
1810
- end
1811
-
1812
- def test_relation_join_method
1813
- assert_equal 'Thank you for the welcome,Thank you again for the welcome', Post.first.comments.join(",")
1814
- end
1815
- 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