ibm_db 3.0.4-x86-mingw32 → 3.0.5-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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -1
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/README +225 -225
  6. data/ext/Makefile.nt32 +181 -181
  7. data/ext/Makefile.nt32.191 +212 -212
  8. data/ext/extconf.rb +291 -291
  9. data/ext/ibm_db.c +11887 -11884
  10. data/ext/ruby_ibm_db.h +241 -241
  11. data/ext/ruby_ibm_db_cli.c +866 -866
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3177 -3177
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +122 -122
  19. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  20. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  21. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +46 -46
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +276 -261
  26. data/test/cases/aggregations_test.rb +158 -158
  27. data/test/cases/ar_schema_test.rb +161 -161
  28. data/test/cases/associations/association_scope_test.rb +21 -21
  29. data/test/cases/associations/belongs_to_associations_test.rb +1029 -1029
  30. data/test/cases/associations/callbacks_test.rb +192 -192
  31. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  32. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -26
  33. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  34. data/test/cases/associations/eager_load_nested_include_test.rb +128 -128
  35. data/test/cases/associations/eager_singularization_test.rb +148 -148
  36. data/test/cases/associations/eager_test.rb +1429 -1411
  37. data/test/cases/associations/extension_test.rb +82 -82
  38. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +972 -932
  39. data/test/cases/associations/has_many_associations_test.rb +2182 -2162
  40. data/test/cases/associations/has_many_through_associations_test.rb +1204 -1204
  41. data/test/cases/associations/has_one_associations_test.rb +610 -610
  42. data/test/cases/associations/has_one_through_associations_test.rb +380 -380
  43. data/test/cases/associations/inner_join_association_test.rb +139 -139
  44. data/test/cases/associations/inverse_associations_test.rb +706 -693
  45. data/test/cases/associations/join_model_test.rb +754 -754
  46. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  47. data/test/cases/associations/required_test.rb +82 -82
  48. data/test/cases/associations_test.rb +380 -380
  49. data/test/cases/attribute_decorators_test.rb +125 -125
  50. data/test/cases/attribute_methods/read_test.rb +60 -60
  51. data/test/cases/attribute_methods/serialization_test.rb +29 -29
  52. data/test/cases/attribute_methods_test.rb +952 -952
  53. data/test/cases/attribute_set_test.rb +210 -200
  54. data/test/cases/attribute_test.rb +180 -180
  55. data/test/cases/attributes_test.rb +136 -136
  56. data/test/cases/autosave_association_test.rb +1595 -1595
  57. data/test/cases/base_test.rb +1664 -1638
  58. data/test/cases/batches_test.rb +212 -212
  59. data/test/cases/binary_test.rb +52 -52
  60. data/test/cases/bind_parameter_test.rb +100 -100
  61. data/test/cases/calculations_test.rb +646 -646
  62. data/test/cases/callbacks_test.rb +543 -543
  63. data/test/cases/clone_test.rb +40 -40
  64. data/test/cases/coders/yaml_column_test.rb +63 -63
  65. data/test/cases/column_alias_test.rb +17 -17
  66. data/test/cases/column_definition_test.rb +123 -123
  67. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -54
  68. data/test/cases/connection_adapters/connection_handler_test.rb +53 -53
  69. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  70. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -293
  71. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -65
  72. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  73. data/test/cases/connection_adapters/schema_cache_test.rb +56 -56
  74. data/test/cases/connection_adapters/type_lookup_test.rb +110 -110
  75. data/test/cases/connection_management_test.rb +122 -122
  76. data/test/cases/connection_pool_test.rb +346 -346
  77. data/test/cases/connection_specification/resolver_test.rb +116 -116
  78. data/test/cases/core_test.rb +112 -112
  79. data/test/cases/counter_cache_test.rb +209 -209
  80. data/test/cases/custom_locking_test.rb +17 -17
  81. data/test/cases/database_statements_test.rb +19 -19
  82. data/test/cases/date_time_test.rb +61 -61
  83. data/test/cases/defaults_test.rb +223 -223
  84. data/test/cases/dirty_test.rb +785 -775
  85. data/test/cases/disconnected_test.rb +28 -28
  86. data/test/cases/dup_test.rb +157 -157
  87. data/test/cases/enum_test.rb +290 -290
  88. data/test/cases/explain_subscriber_test.rb +64 -64
  89. data/test/cases/explain_test.rb +76 -76
  90. data/test/cases/finder_respond_to_test.rb +60 -60
  91. data/test/cases/finder_test.rb +1169 -1166
  92. data/test/cases/fixture_set/file_test.rb +138 -138
  93. data/test/cases/fixtures_test.rb +908 -897
  94. data/test/cases/forbidden_attributes_protection_test.rb +99 -99
  95. data/test/cases/habtm_destroy_order_test.rb +61 -61
  96. data/test/cases/helper.rb +210 -210
  97. data/test/cases/hot_compatibility_test.rb +54 -54
  98. data/test/cases/i18n_test.rb +45 -45
  99. data/test/cases/inheritance_test.rb +375 -375
  100. data/test/cases/integration_test.rb +139 -139
  101. data/test/cases/invalid_connection_test.rb +22 -22
  102. data/test/cases/invalid_date_test.rb +32 -32
  103. data/test/cases/invertible_migration_test.rb +295 -295
  104. data/test/cases/json_serialization_test.rb +302 -302
  105. data/test/cases/locking_test.rb +477 -477
  106. data/test/cases/log_subscriber_test.rb +136 -136
  107. data/test/cases/migration/change_schema_test - Copy.rb +448 -448
  108. data/test/cases/migration/change_schema_test.rb +512 -472
  109. data/test/cases/migration/change_table_test.rb +224 -224
  110. data/test/cases/migration/column_attributes_test.rb +192 -192
  111. data/test/cases/migration/column_positioning_test.rb +56 -56
  112. data/test/cases/migration/columns_test.rb +304 -304
  113. data/test/cases/migration/command_recorder_test.rb +305 -305
  114. data/test/cases/migration/create_join_table_test.rb +148 -148
  115. data/test/cases/migration/foreign_key_test - Changed.rb +325 -325
  116. data/test/cases/migration/foreign_key_test.rb +328 -360
  117. data/test/cases/migration/helper.rb +39 -39
  118. data/test/cases/migration/index_test.rb +216 -216
  119. data/test/cases/migration/logger_test.rb +36 -36
  120. data/test/cases/migration/pending_migrations_test.rb +53 -53
  121. data/test/cases/migration/references_foreign_key_test.rb +169 -214
  122. data/test/cases/migration/references_index_test.rb +101 -101
  123. data/test/cases/migration/references_statements_test.rb +116 -116
  124. data/test/cases/migration/rename_table_test.rb +93 -93
  125. data/test/cases/migration/table_and_index_test.rb +24 -24
  126. data/test/cases/migration_test.rb +959 -959
  127. data/test/cases/migrator_test.rb +388 -388
  128. data/test/cases/mixin_test.rb +70 -70
  129. data/test/cases/modules_test.rb +173 -173
  130. data/test/cases/multiparameter_attributes_test.rb +350 -350
  131. data/test/cases/multiple_db_test.rb +115 -115
  132. data/test/cases/nested_attributes_test.rb +1070 -1057
  133. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  134. data/test/cases/persistence_test.rb +909 -909
  135. data/test/cases/pooled_connections_test.rb +81 -81
  136. data/test/cases/primary_keys_test.rb +237 -237
  137. data/test/cases/query_cache_test.rb +326 -326
  138. data/test/cases/quoting_test.rb +156 -156
  139. data/test/cases/readonly_test.rb +118 -118
  140. data/test/cases/reaper_test.rb +85 -85
  141. data/test/cases/reflection_test.rb +463 -454
  142. data/test/cases/relation/delegation_test.rb +68 -68
  143. data/test/cases/relation/merging_test.rb +161 -161
  144. data/test/cases/relation/mutation_test.rb +165 -165
  145. data/test/cases/relation/predicate_builder_test.rb +14 -14
  146. data/test/cases/relation/where_chain_test.rb +181 -181
  147. data/test/cases/relation/where_test.rb +300 -300
  148. data/test/cases/relation/where_test2.rb +36 -36
  149. data/test/cases/relation_test.rb +319 -297
  150. data/test/cases/relations_test.rb +1815 -1815
  151. data/test/cases/reload_models_test.rb +22 -22
  152. data/test/cases/result_test.rb +80 -80
  153. data/test/cases/sanitize_test.rb +83 -83
  154. data/test/cases/schema_dumper_test.rb +463 -463
  155. data/test/cases/scoping/default_scoping_test.rb +454 -454
  156. data/test/cases/scoping/named_scoping_test.rb +524 -524
  157. data/test/cases/scoping/relation_scoping_test.rb +357 -357
  158. data/test/cases/serialization_test.rb +104 -104
  159. data/test/cases/serialized_attribute_test.rb +277 -277
  160. data/test/cases/statement_cache_test.rb +98 -98
  161. data/test/cases/store_test.rb +194 -194
  162. data/test/cases/tasks/database_tasks_test.rb +398 -396
  163. data/test/cases/tasks/mysql_rake_test.rb +324 -311
  164. data/test/cases/tasks/postgresql_rake_test.rb +250 -245
  165. data/test/cases/tasks/sqlite_rake_test.rb +193 -193
  166. data/test/cases/test_case.rb +123 -123
  167. data/test/cases/timestamp_test.rb +467 -468
  168. data/test/cases/transaction_callbacks_test.rb +452 -452
  169. data/test/cases/transaction_isolation_test.rb +106 -106
  170. data/test/cases/transactions_test.rb +817 -817
  171. data/test/cases/type/decimal_test.rb +56 -51
  172. data/test/cases/type/integer_test.rb +121 -121
  173. data/test/cases/type/string_test.rb +36 -36
  174. data/test/cases/type/type_map_test.rb +177 -177
  175. data/test/cases/type/unsigned_integer_test.rb +18 -18
  176. data/test/cases/types_test.rb +141 -141
  177. data/test/cases/unconnected_test.rb +33 -33
  178. data/test/cases/validations/association_validation_test.rb +86 -86
  179. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  180. data/test/cases/validations/i18n_validation_test.rb +90 -90
  181. data/test/cases/validations/length_validation_test.rb +47 -47
  182. data/test/cases/validations/presence_validation_test.rb +68 -68
  183. data/test/cases/validations/uniqueness_validation_test.rb +457 -434
  184. data/test/cases/validations_repair_helper.rb +23 -23
  185. data/test/cases/validations_test.rb +165 -165
  186. data/test/cases/view_test.rb +119 -113
  187. data/test/cases/xml_serialization_test.rb +457 -457
  188. data/test/cases/yaml_serialization_test.rb +126 -86
  189. data/test/config.rb +5 -5
  190. data/test/config.yml +154 -154
  191. data/test/connections/native_ibm_db/connection.rb +43 -43
  192. data/test/fixtures/accounts.yml +29 -29
  193. data/test/fixtures/admin/accounts.yml +2 -2
  194. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  195. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  196. data/test/fixtures/admin/users.yml +10 -10
  197. data/test/fixtures/author_addresses.yml +17 -17
  198. data/test/fixtures/author_favorites.yml +3 -3
  199. data/test/fixtures/authors.yml +23 -23
  200. data/test/fixtures/binaries.yml +133 -133
  201. data/test/fixtures/books.yml +11 -11
  202. data/test/fixtures/bulbs.yml +5 -5
  203. data/test/fixtures/cars.yml +9 -9
  204. data/test/fixtures/categories.yml +19 -19
  205. data/test/fixtures/categories/special_categories.yml +9 -9
  206. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  207. data/test/fixtures/categories_ordered.yml +7 -7
  208. data/test/fixtures/categories_posts.yml +31 -31
  209. data/test/fixtures/categorizations.yml +23 -23
  210. data/test/fixtures/clubs.yml +8 -8
  211. data/test/fixtures/collections.yml +3 -3
  212. data/test/fixtures/colleges.yml +3 -3
  213. data/test/fixtures/comments.yml +65 -65
  214. data/test/fixtures/companies.yml +67 -67
  215. data/test/fixtures/computers.yml +10 -10
  216. data/test/fixtures/courses.yml +8 -8
  217. data/test/fixtures/customers.yml +25 -25
  218. data/test/fixtures/dashboards.yml +6 -6
  219. data/test/fixtures/developers.yml +21 -21
  220. data/test/fixtures/developers_projects.yml +16 -16
  221. data/test/fixtures/dog_lovers.yml +7 -7
  222. data/test/fixtures/dogs.yml +4 -4
  223. data/test/fixtures/doubloons.yml +3 -3
  224. data/test/fixtures/edges.yml +5 -5
  225. data/test/fixtures/entrants.yml +14 -14
  226. data/test/fixtures/essays.yml +6 -6
  227. data/test/fixtures/faces.yml +11 -11
  228. data/test/fixtures/fk_test_has_fk.yml +3 -3
  229. data/test/fixtures/fk_test_has_pk.yml +1 -1
  230. data/test/fixtures/friendships.yml +4 -4
  231. data/test/fixtures/funny_jokes.yml +10 -10
  232. data/test/fixtures/interests.yml +33 -33
  233. data/test/fixtures/items.yml +3 -3
  234. data/test/fixtures/jobs.yml +7 -7
  235. data/test/fixtures/legacy_things.yml +3 -3
  236. data/test/fixtures/mateys.yml +4 -4
  237. data/test/fixtures/member_details.yml +8 -8
  238. data/test/fixtures/member_types.yml +6 -6
  239. data/test/fixtures/members.yml +11 -11
  240. data/test/fixtures/memberships.yml +34 -34
  241. data/test/fixtures/men.yml +5 -5
  242. data/test/fixtures/minimalistics.yml +2 -2
  243. data/test/fixtures/minivans.yml +5 -5
  244. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  245. data/test/fixtures/mixins.yml +29 -29
  246. data/test/fixtures/movies.yml +7 -7
  247. data/test/fixtures/naked/csv/accounts.csv +1 -1
  248. data/test/fixtures/naked/yml/accounts.yml +1 -1
  249. data/test/fixtures/naked/yml/companies.yml +1 -1
  250. data/test/fixtures/naked/yml/courses.yml +1 -1
  251. data/test/fixtures/organizations.yml +5 -5
  252. data/test/fixtures/other_topics.yml +42 -42
  253. data/test/fixtures/owners.yml +9 -9
  254. data/test/fixtures/parrots.yml +27 -27
  255. data/test/fixtures/parrots_pirates.yml +7 -7
  256. data/test/fixtures/people.yml +24 -24
  257. data/test/fixtures/peoples_treasures.yml +3 -3
  258. data/test/fixtures/pets.yml +19 -19
  259. data/test/fixtures/pirates.yml +12 -12
  260. data/test/fixtures/posts.yml +80 -80
  261. data/test/fixtures/price_estimates.yml +7 -7
  262. data/test/fixtures/products.yml +4 -4
  263. data/test/fixtures/projects.yml +7 -7
  264. data/test/fixtures/randomly_named_a9.yml +7 -7
  265. data/test/fixtures/ratings.yml +14 -14
  266. data/test/fixtures/readers.yml +11 -11
  267. data/test/fixtures/references.yml +17 -17
  268. data/test/fixtures/reserved_words/distinct.yml +5 -5
  269. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  270. data/test/fixtures/reserved_words/group.yml +14 -14
  271. data/test/fixtures/reserved_words/select.yml +8 -8
  272. data/test/fixtures/reserved_words/values.yml +7 -7
  273. data/test/fixtures/ships.yml +6 -6
  274. data/test/fixtures/speedometers.yml +8 -8
  275. data/test/fixtures/sponsors.yml +12 -12
  276. data/test/fixtures/string_key_objects.yml +7 -7
  277. data/test/fixtures/subscribers.yml +10 -10
  278. data/test/fixtures/subscriptions.yml +12 -12
  279. data/test/fixtures/taggings.yml +78 -78
  280. data/test/fixtures/tags.yml +11 -11
  281. data/test/fixtures/tasks.yml +7 -7
  282. data/test/fixtures/teapots.yml +3 -3
  283. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  284. data/test/fixtures/to_be_linked/users.yml +10 -10
  285. data/test/fixtures/topics.yml +49 -49
  286. data/test/fixtures/toys.yml +14 -14
  287. data/test/fixtures/traffic_lights.yml +9 -9
  288. data/test/fixtures/treasures.yml +10 -10
  289. data/test/fixtures/uuid_children.yml +3 -3
  290. data/test/fixtures/uuid_parents.yml +2 -2
  291. data/test/fixtures/variants.yml +4 -4
  292. data/test/fixtures/vegetables.yml +19 -19
  293. data/test/fixtures/vertices.yml +3 -3
  294. data/test/fixtures/warehouse_things.yml +2 -2
  295. data/test/fixtures/zines.yml +5 -5
  296. data/test/ibm_db_test.rb +24 -24
  297. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  298. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  299. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  300. data/test/migrations/missing/1000_people_have_middle_names.rb +8 -8
  301. data/test/migrations/missing/1_people_have_last_names.rb +8 -8
  302. data/test/migrations/missing/3_we_need_reminders.rb +11 -11
  303. data/test/migrations/missing/4_innocent_jointable.rb +11 -11
  304. data/test/migrations/rename/1_we_need_things.rb +10 -10
  305. data/test/migrations/rename/2_rename_things.rb +8 -8
  306. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  307. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  308. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  309. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  310. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  311. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  312. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  313. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  314. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  315. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  316. data/test/migrations/valid/2_we_need_reminders.rb +11 -11
  317. data/test/migrations/valid/3_innocent_jointable.rb +11 -11
  318. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  319. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +11 -11
  320. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +11 -11
  321. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  322. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  323. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  324. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  325. data/test/models/admin.rb +4 -4
  326. data/test/models/admin/account.rb +2 -2
  327. data/test/models/admin/randomly_named_c1.rb +3 -3
  328. data/test/models/admin/user.rb +40 -40
  329. data/test/models/aircraft.rb +4 -4
  330. data/test/models/arunit2_model.rb +3 -3
  331. data/test/models/author.rb +212 -212
  332. data/test/models/auto_id.rb +4 -4
  333. data/test/models/autoloadable/extra_firm.rb +2 -2
  334. data/test/models/binary.rb +1 -1
  335. data/test/models/bird.rb +12 -12
  336. data/test/models/book.rb +18 -18
  337. data/test/models/boolean.rb +2 -2
  338. data/test/models/bulb.rb +51 -51
  339. data/test/models/cake_designer.rb +3 -3
  340. data/test/models/car.rb +26 -26
  341. data/test/models/carrier.rb +2 -2
  342. data/test/models/categorization.rb +19 -19
  343. data/test/models/category.rb +35 -35
  344. data/test/models/chef.rb +7 -3
  345. data/test/models/citation.rb +3 -3
  346. data/test/models/club.rb +23 -23
  347. data/test/models/college.rb +10 -10
  348. data/test/models/column.rb +3 -3
  349. data/test/models/column_name.rb +3 -3
  350. data/test/models/comment.rb +64 -64
  351. data/test/models/company.rb +228 -225
  352. data/test/models/company_in_module.rb +98 -98
  353. data/test/models/computer.rb +3 -3
  354. data/test/models/contact.rb +41 -41
  355. data/test/models/contract.rb +20 -20
  356. data/test/models/country.rb +7 -7
  357. data/test/models/course.rb +6 -6
  358. data/test/models/customer.rb +77 -77
  359. data/test/models/customer_carrier.rb +14 -14
  360. data/test/models/dashboard.rb +3 -3
  361. data/test/models/default.rb +2 -2
  362. data/test/models/department.rb +4 -4
  363. data/test/models/developer.rb +255 -252
  364. data/test/models/dog.rb +5 -5
  365. data/test/models/dog_lover.rb +5 -5
  366. data/test/models/doubloon.rb +12 -12
  367. data/test/models/drink_designer.rb +3 -3
  368. data/test/models/edge.rb +5 -5
  369. data/test/models/electron.rb +5 -5
  370. data/test/models/engine.rb +4 -4
  371. data/test/models/entrant.rb +3 -3
  372. data/test/models/essay.rb +5 -5
  373. data/test/models/event.rb +2 -2
  374. data/test/models/eye.rb +37 -37
  375. data/test/models/face.rb +9 -9
  376. data/test/models/friendship.rb +6 -6
  377. data/test/models/guid.rb +1 -1
  378. data/test/models/hotel.rb +9 -6
  379. data/test/models/image.rb +3 -3
  380. data/test/models/interest.rb +5 -5
  381. data/test/models/invoice.rb +4 -4
  382. data/test/models/item.rb +7 -7
  383. data/test/models/job.rb +7 -7
  384. data/test/models/joke.rb +7 -7
  385. data/test/models/keyboard.rb +3 -3
  386. data/test/models/legacy_thing.rb +3 -3
  387. data/test/models/lesson.rb +11 -11
  388. data/test/models/line_item.rb +3 -3
  389. data/test/models/liquid.rb +4 -4
  390. data/test/models/man.rb +11 -11
  391. data/test/models/matey.rb +4 -4
  392. data/test/models/member.rb +41 -41
  393. data/test/models/member_detail.rb +7 -7
  394. data/test/models/member_type.rb +3 -3
  395. data/test/models/membership.rb +35 -35
  396. data/test/models/minimalistic.rb +2 -2
  397. data/test/models/minivan.rb +9 -9
  398. data/test/models/mixed_case_monkey.rb +3 -3
  399. data/test/models/molecule.rb +6 -6
  400. data/test/models/movie.rb +5 -5
  401. data/test/models/order.rb +4 -4
  402. data/test/models/organization.rb +14 -14
  403. data/test/models/owner.rb +34 -34
  404. data/test/models/parrot.rb +29 -29
  405. data/test/models/person.rb +143 -143
  406. data/test/models/personal_legacy_thing.rb +4 -4
  407. data/test/models/pet.rb +15 -15
  408. data/test/models/pirate.rb +92 -92
  409. data/test/models/possession.rb +3 -3
  410. data/test/models/post.rb +264 -264
  411. data/test/models/price_estimate.rb +4 -4
  412. data/test/models/professor.rb +5 -5
  413. data/test/models/project.rb +31 -29
  414. data/test/models/publisher.rb +2 -2
  415. data/test/models/publisher/article.rb +4 -4
  416. data/test/models/publisher/magazine.rb +3 -3
  417. data/test/models/randomly_named_c1.rb +3 -3
  418. data/test/models/rating.rb +4 -4
  419. data/test/models/reader.rb +23 -23
  420. data/test/models/record.rb +2 -2
  421. data/test/models/reference.rb +22 -22
  422. data/test/models/reply.rb +61 -61
  423. data/test/models/ship.rb +33 -33
  424. data/test/models/ship_part.rb +7 -7
  425. data/test/models/shop.rb +17 -17
  426. data/test/models/shop_account.rb +6 -6
  427. data/test/models/speedometer.rb +6 -6
  428. data/test/models/sponsor.rb +7 -7
  429. data/test/models/string_key_object.rb +3 -3
  430. data/test/models/student.rb +4 -4
  431. data/test/models/subject.rb +16 -16
  432. data/test/models/subscriber.rb +8 -8
  433. data/test/models/subscription.rb +4 -4
  434. data/test/models/tag.rb +7 -7
  435. data/test/models/tagging.rb +13 -13
  436. data/test/models/task.rb +5 -5
  437. data/test/models/topic.rb +124 -124
  438. data/test/models/toy.rb +6 -6
  439. data/test/models/traffic_light.rb +4 -4
  440. data/test/models/treasure.rb +14 -14
  441. data/test/models/treaty.rb +7 -7
  442. data/test/models/tyre.rb +11 -11
  443. data/test/models/uuid_child.rb +3 -3
  444. data/test/models/uuid_parent.rb +3 -3
  445. data/test/models/vegetables.rb +24 -24
  446. data/test/models/vehicle.rb +6 -6
  447. data/test/models/vertex.rb +9 -9
  448. data/test/models/warehouse_thing.rb +5 -5
  449. data/test/models/wheel.rb +3 -3
  450. data/test/models/without_table.rb +3 -3
  451. data/test/models/zine.rb +3 -3
  452. data/test/schema/mysql2_specific_schema.rb +58 -58
  453. data/test/schema/mysql_specific_schema.rb +70 -70
  454. data/test/schema/oracle_specific_schema.rb +43 -43
  455. data/test/schema/postgresql_specific_schema.rb +202 -202
  456. data/test/schema/schema.rb +952 -938
  457. data/test/schema/sqlite_specific_schema.rb +21 -21
  458. data/test/support/config.rb +43 -43
  459. data/test/support/connection.rb +22 -22
  460. data/test/support/connection_helper.rb +14 -14
  461. data/test/support/ddl_helper.rb +8 -8
  462. data/test/support/schema_dumping_helper.rb +20 -20
  463. metadata +2 -2
@@ -1,1815 +1,1815 @@
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
+
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