ibm_db 3.0.5-x86-mingw32 → 4.0.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (586) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/ParameterizedQueries README +6 -6
  6. data/README +208 -225
  7. data/ext/Makefile.nt32 +181 -181
  8. data/ext/Makefile.nt32.191 +212 -212
  9. data/ext/extconf.rb +291 -291
  10. data/ext/ibm_db.c +11887 -11887
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/init.rb +41 -41
  15. data/lib/IBM_DB.rb +27 -27
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
  17. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  18. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  19. data/lib/mswin32/ibm_db.rb +91 -123
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  22. data/test/assets/example.log +1 -1
  23. data/test/assets/test.txt +1 -1
  24. data/test/cases/adapter_test.rb +351 -276
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  27. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  30. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  32. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  33. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  34. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  35. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  36. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  38. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  39. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  40. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  41. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  43. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  44. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  45. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  46. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  47. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  48. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  49. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  50. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  51. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  52. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  53. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  54. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  55. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  56. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  57. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  58. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  59. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  60. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  61. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  62. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  63. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  64. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  65. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  66. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  67. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  68. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  69. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  70. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  71. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  72. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  73. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  74. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  75. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  76. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  77. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  78. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  79. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  80. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  81. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  82. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  83. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  84. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  85. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  86. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  87. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  88. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  89. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  90. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  91. data/test/cases/aggregations_test.rb +168 -158
  92. data/test/cases/ar_schema_test.rb +146 -161
  93. data/test/cases/associations/association_scope_test.rb +16 -21
  94. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  95. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  96. data/test/cases/associations/callbacks_test.rb +190 -192
  97. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  98. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  99. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  100. data/test/cases/associations/eager_singularization_test.rb +148 -148
  101. data/test/cases/associations/eager_test.rb +1514 -1429
  102. data/test/cases/associations/extension_test.rb +87 -82
  103. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
  104. data/test/cases/associations/has_many_associations_test.rb +2501 -2182
  105. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  106. data/test/cases/associations/has_one_associations_test.rb +707 -610
  107. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  108. data/test/cases/associations/inner_join_association_test.rb +139 -139
  109. data/test/cases/associations/inverse_associations_test.rb +733 -706
  110. data/test/cases/associations/join_model_test.rb +777 -754
  111. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  112. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  113. data/test/cases/associations/required_test.rb +102 -82
  114. data/test/cases/associations_test.rb +385 -380
  115. data/test/cases/attribute_decorators_test.rb +125 -125
  116. data/test/cases/attribute_methods/read_test.rb +60 -60
  117. data/test/cases/attribute_methods_test.rb +1009 -952
  118. data/test/cases/attribute_set_test.rb +270 -210
  119. data/test/cases/attribute_test.rb +246 -180
  120. data/test/cases/attributes_test.rb +253 -136
  121. data/test/cases/autosave_association_test.rb +1708 -1595
  122. data/test/cases/base_test.rb +1713 -1664
  123. data/test/cases/batches_test.rb +489 -212
  124. data/test/cases/binary_test.rb +44 -52
  125. data/test/cases/bind_parameter_test.rb +110 -100
  126. data/test/cases/cache_key_test.rb +25 -0
  127. data/test/cases/calculations_test.rb +798 -646
  128. data/test/cases/callbacks_test.rb +636 -543
  129. data/test/cases/clone_test.rb +40 -40
  130. data/test/cases/coders/json_test.rb +15 -0
  131. data/test/cases/coders/yaml_column_test.rb +63 -63
  132. data/test/cases/collection_cache_key_test.rb +115 -0
  133. data/test/cases/column_alias_test.rb +17 -17
  134. data/test/cases/column_definition_test.rb +92 -123
  135. data/test/cases/comment_test.rb +143 -0
  136. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  137. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  138. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  139. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  140. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  141. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  142. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  143. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  144. data/test/cases/connection_management_test.rb +112 -122
  145. data/test/cases/connection_pool_test.rb +521 -346
  146. data/test/cases/connection_specification/resolver_test.rb +131 -116
  147. data/test/cases/core_test.rb +112 -112
  148. data/test/cases/counter_cache_test.rb +214 -209
  149. data/test/cases/custom_locking_test.rb +17 -17
  150. data/test/cases/database_statements_test.rb +34 -19
  151. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  152. data/test/cases/date_time_precision_test.rb +106 -0
  153. data/test/cases/date_time_test.rb +61 -61
  154. data/test/cases/defaults_test.rb +218 -223
  155. data/test/cases/dirty_test.rb +763 -785
  156. data/test/cases/disconnected_test.rb +30 -28
  157. data/test/cases/dup_test.rb +157 -157
  158. data/test/cases/enum_test.rb +444 -290
  159. data/test/cases/errors_test.rb +16 -0
  160. data/test/cases/explain_subscriber_test.rb +64 -64
  161. data/test/cases/explain_test.rb +87 -76
  162. data/test/cases/finder_respond_to_test.rb +60 -60
  163. data/test/cases/finder_test.rb +1294 -1169
  164. data/test/cases/fixture_set/file_test.rb +156 -138
  165. data/test/cases/fixtures_test.rb +988 -908
  166. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  167. data/test/cases/habtm_destroy_order_test.rb +61 -61
  168. data/test/cases/helper.rb +204 -210
  169. data/test/cases/hot_compatibility_test.rb +142 -54
  170. data/test/cases/i18n_test.rb +45 -45
  171. data/test/cases/inheritance_test.rb +606 -375
  172. data/test/cases/integration_test.rb +155 -139
  173. data/test/cases/invalid_connection_test.rb +24 -22
  174. data/test/cases/invertible_migration_test.rb +387 -295
  175. data/test/cases/json_serialization_test.rb +311 -302
  176. data/test/cases/locking_test.rb +493 -477
  177. data/test/cases/log_subscriber_test.rb +225 -136
  178. data/test/cases/migration/change_schema_test.rb +458 -512
  179. data/test/cases/migration/change_table_test.rb +256 -224
  180. data/test/cases/migration/column_attributes_test.rb +176 -192
  181. data/test/cases/migration/column_positioning_test.rb +56 -56
  182. data/test/cases/migration/columns_test.rb +310 -304
  183. data/test/cases/migration/command_recorder_test.rb +350 -305
  184. data/test/cases/migration/compatibility_test.rb +118 -0
  185. data/test/cases/migration/create_join_table_test.rb +157 -148
  186. data/test/cases/migration/foreign_key_test.rb +360 -328
  187. data/test/cases/migration/helper.rb +39 -39
  188. data/test/cases/migration/index_test.rb +218 -216
  189. data/test/cases/migration/logger_test.rb +36 -36
  190. data/test/cases/migration/pending_migrations_test.rb +52 -53
  191. data/test/cases/migration/references_foreign_key_test.rb +216 -169
  192. data/test/cases/migration/references_index_test.rb +101 -101
  193. data/test/cases/migration/references_statements_test.rb +136 -116
  194. data/test/cases/migration/rename_table_test.rb +93 -93
  195. data/test/cases/migration_test.rb +1157 -959
  196. data/test/cases/migrator_test.rb +470 -388
  197. data/test/cases/mixin_test.rb +68 -70
  198. data/test/cases/modules_test.rb +172 -173
  199. data/test/cases/multiparameter_attributes_test.rb +372 -350
  200. data/test/cases/multiple_db_test.rb +122 -115
  201. data/test/cases/nested_attributes_test.rb +1098 -1070
  202. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  203. data/test/cases/persistence_test.rb +1001 -909
  204. data/test/cases/pooled_connections_test.rb +81 -81
  205. data/test/cases/primary_keys_test.rb +376 -237
  206. data/test/cases/query_cache_test.rb +446 -326
  207. data/test/cases/quoting_test.rb +202 -156
  208. data/test/cases/readonly_test.rb +119 -118
  209. data/test/cases/reaper_test.rb +85 -85
  210. data/test/cases/reflection_test.rb +509 -463
  211. data/test/cases/relation/delegation_test.rb +63 -68
  212. data/test/cases/relation/merging_test.rb +157 -161
  213. data/test/cases/relation/mutation_test.rb +183 -165
  214. data/test/cases/relation/or_test.rb +92 -0
  215. data/test/cases/relation/predicate_builder_test.rb +16 -14
  216. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  217. data/test/cases/relation/where_chain_test.rb +105 -181
  218. data/test/cases/relation/where_clause_test.rb +182 -0
  219. data/test/cases/relation/where_test.rb +322 -300
  220. data/test/cases/relation_test.rb +328 -319
  221. data/test/cases/relations_test.rb +2026 -1815
  222. data/test/cases/reload_models_test.rb +22 -22
  223. data/test/cases/result_test.rb +90 -80
  224. data/test/cases/sanitize_test.rb +176 -83
  225. data/test/cases/schema_dumper_test.rb +457 -463
  226. data/test/cases/schema_loading_test.rb +52 -0
  227. data/test/cases/scoping/default_scoping_test.rb +528 -454
  228. data/test/cases/scoping/named_scoping_test.rb +561 -524
  229. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  230. data/test/cases/secure_token_test.rb +32 -0
  231. data/test/cases/serialization_test.rb +104 -104
  232. data/test/cases/serialized_attribute_test.rb +364 -277
  233. data/test/cases/statement_cache_test.rb +136 -98
  234. data/test/cases/store_test.rb +195 -194
  235. data/test/cases/suppressor_test.rb +63 -0
  236. data/test/cases/tasks/database_tasks_test.rb +462 -398
  237. data/test/cases/tasks/mysql_rake_test.rb +345 -324
  238. data/test/cases/tasks/postgresql_rake_test.rb +304 -250
  239. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  240. data/test/cases/test_case.rb +131 -123
  241. data/test/cases/test_fixtures_test.rb +36 -0
  242. data/test/cases/time_precision_test.rb +102 -0
  243. data/test/cases/timestamp_test.rb +501 -467
  244. data/test/cases/touch_later_test.rb +121 -0
  245. data/test/cases/transaction_callbacks_test.rb +518 -452
  246. data/test/cases/transaction_isolation_test.rb +106 -106
  247. data/test/cases/transactions_test.rb +834 -817
  248. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  249. data/test/cases/type/date_time_test.rb +14 -0
  250. data/test/cases/type/integer_test.rb +27 -121
  251. data/test/cases/type/string_test.rb +22 -36
  252. data/test/cases/type/type_map_test.rb +177 -177
  253. data/test/cases/type_test.rb +39 -0
  254. data/test/cases/types_test.rb +24 -141
  255. data/test/cases/unconnected_test.rb +33 -33
  256. data/test/cases/validations/absence_validation_test.rb +73 -0
  257. data/test/cases/validations/association_validation_test.rb +97 -86
  258. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  259. data/test/cases/validations/i18n_validation_test.rb +86 -90
  260. data/test/cases/validations/length_validation_test.rb +79 -47
  261. data/test/cases/validations/presence_validation_test.rb +103 -68
  262. data/test/cases/validations/uniqueness_validation_test.rb +548 -457
  263. data/test/cases/validations_repair_helper.rb +19 -23
  264. data/test/cases/validations_test.rb +194 -165
  265. data/test/cases/view_test.rb +216 -119
  266. data/test/cases/yaml_serialization_test.rb +121 -126
  267. data/test/config.example.yml +97 -0
  268. data/test/config.rb +5 -5
  269. data/test/fixtures/accounts.yml +29 -29
  270. data/test/fixtures/admin/accounts.yml +2 -2
  271. data/test/fixtures/admin/users.yml +10 -10
  272. data/test/fixtures/author_addresses.original +11 -0
  273. data/test/fixtures/author_addresses.yml +17 -17
  274. data/test/fixtures/author_favorites.yml +3 -3
  275. data/test/fixtures/authors.original +17 -0
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -0
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -11
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -0
  295. data/test/fixtures/content_positions.yml +3 -0
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -0
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -0
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -0
  333. data/test/fixtures/naked/yml/trees.yml +3 -0
  334. data/test/fixtures/nodes.yml +29 -0
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -0
  337. data/test/fixtures/other_dogs.yml +2 -0
  338. data/test/fixtures/other_posts.yml +7 -0
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +15 -12
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -7
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -0
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/randomly_named_c1.rb +6 -2
  414. data/test/models/admin/user.rb +40 -40
  415. data/test/models/aircraft.rb +5 -4
  416. data/test/models/arunit2_model.rb +3 -3
  417. data/test/models/author.rb +209 -212
  418. data/test/models/auto_id.rb +4 -4
  419. data/test/models/autoloadable/extra_firm.rb +2 -2
  420. data/test/models/binary.rb +2 -2
  421. data/test/models/bird.rb +12 -12
  422. data/test/models/book.rb +23 -18
  423. data/test/models/boolean.rb +2 -2
  424. data/test/models/bulb.rb +52 -51
  425. data/test/models/cake_designer.rb +3 -3
  426. data/test/models/car.rb +29 -26
  427. data/test/models/carrier.rb +2 -2
  428. data/test/models/cat.rb +10 -0
  429. data/test/models/categorization.rb +19 -19
  430. data/test/models/category.rb +35 -35
  431. data/test/models/chef.rb +8 -7
  432. data/test/models/citation.rb +3 -3
  433. data/test/models/club.rb +25 -23
  434. data/test/models/college.rb +10 -10
  435. data/test/models/column.rb +3 -3
  436. data/test/models/column_name.rb +3 -3
  437. data/test/models/comment.rb +76 -64
  438. data/test/models/company.rb +230 -228
  439. data/test/models/company_in_module.rb +98 -98
  440. data/test/models/computer.rb +3 -3
  441. data/test/models/contact.rb +41 -41
  442. data/test/models/content.rb +40 -0
  443. data/test/models/contract.rb +20 -20
  444. data/test/models/country.rb +7 -7
  445. data/test/models/course.rb +6 -6
  446. data/test/models/customer.rb +83 -77
  447. data/test/models/customer_carrier.rb +14 -14
  448. data/test/models/dashboard.rb +3 -3
  449. data/test/models/default.rb +2 -2
  450. data/test/models/department.rb +4 -4
  451. data/test/models/developer.rb +274 -255
  452. data/test/models/dog.rb +5 -5
  453. data/test/models/dog_lover.rb +5 -5
  454. data/test/models/doubloon.rb +12 -12
  455. data/test/models/drink_designer.rb +3 -3
  456. data/test/models/edge.rb +5 -5
  457. data/test/models/electron.rb +5 -5
  458. data/test/models/engine.rb +4 -4
  459. data/test/models/entrant.rb +3 -3
  460. data/test/models/essay.rb +5 -5
  461. data/test/models/event.rb +3 -3
  462. data/test/models/eye.rb +37 -37
  463. data/test/models/face.rb +9 -9
  464. data/test/models/friendship.rb +6 -6
  465. data/test/models/guid.rb +2 -2
  466. data/test/models/guitar.rb +4 -0
  467. data/test/models/hotel.rb +11 -9
  468. data/test/models/image.rb +3 -3
  469. data/test/models/interest.rb +5 -5
  470. data/test/models/invoice.rb +4 -4
  471. data/test/models/item.rb +7 -7
  472. data/test/models/job.rb +7 -7
  473. data/test/models/joke.rb +7 -7
  474. data/test/models/keyboard.rb +3 -3
  475. data/test/models/legacy_thing.rb +3 -3
  476. data/test/models/lesson.rb +11 -11
  477. data/test/models/line_item.rb +3 -3
  478. data/test/models/liquid.rb +4 -4
  479. data/test/models/man.rb +11 -11
  480. data/test/models/matey.rb +4 -4
  481. data/test/models/member.rb +42 -41
  482. data/test/models/member_detail.rb +8 -7
  483. data/test/models/member_type.rb +3 -3
  484. data/test/models/membership.rb +35 -35
  485. data/test/models/mentor.rb +3 -0
  486. data/test/models/minimalistic.rb +2 -2
  487. data/test/models/minivan.rb +9 -9
  488. data/test/models/mixed_case_monkey.rb +3 -3
  489. data/test/models/mocktail_designer.rb +2 -0
  490. data/test/models/molecule.rb +6 -6
  491. data/test/models/movie.rb +5 -5
  492. data/test/models/node.rb +5 -0
  493. data/test/models/non_primary_key.rb +2 -0
  494. data/test/models/notification.rb +3 -0
  495. data/test/models/order.rb +4 -4
  496. data/test/models/organization.rb +14 -14
  497. data/test/models/other_dog.rb +5 -0
  498. data/test/models/owner.rb +37 -34
  499. data/test/models/parrot.rb +28 -29
  500. data/test/models/person.rb +142 -143
  501. data/test/models/personal_legacy_thing.rb +4 -4
  502. data/test/models/pet.rb +18 -15
  503. data/test/models/pet_treasure.rb +6 -0
  504. data/test/models/pirate.rb +92 -92
  505. data/test/models/possession.rb +3 -3
  506. data/test/models/post.rb +273 -264
  507. data/test/models/price_estimate.rb +4 -4
  508. data/test/models/professor.rb +5 -5
  509. data/test/models/project.rb +40 -31
  510. data/test/models/publisher.rb +2 -2
  511. data/test/models/publisher/article.rb +4 -4
  512. data/test/models/publisher/magazine.rb +3 -3
  513. data/test/models/randomly_named_c1.rb +1 -1
  514. data/test/models/rating.rb +4 -4
  515. data/test/models/reader.rb +23 -23
  516. data/test/models/recipe.rb +3 -0
  517. data/test/models/record.rb +2 -2
  518. data/test/models/reference.rb +22 -22
  519. data/test/models/reply.rb +61 -61
  520. data/test/models/ship.rb +39 -33
  521. data/test/models/ship_part.rb +8 -8
  522. data/test/models/shop.rb +17 -17
  523. data/test/models/shop_account.rb +6 -6
  524. data/test/models/speedometer.rb +6 -6
  525. data/test/models/sponsor.rb +7 -7
  526. data/test/models/string_key_object.rb +3 -3
  527. data/test/models/student.rb +4 -4
  528. data/test/models/subject.rb +16 -16
  529. data/test/models/subscriber.rb +8 -8
  530. data/test/models/subscription.rb +4 -4
  531. data/test/models/tag.rb +13 -7
  532. data/test/models/tagging.rb +13 -13
  533. data/test/models/task.rb +5 -5
  534. data/test/models/topic.rb +118 -124
  535. data/test/models/toy.rb +6 -6
  536. data/test/models/traffic_light.rb +4 -4
  537. data/test/models/treasure.rb +14 -14
  538. data/test/models/treaty.rb +7 -7
  539. data/test/models/tree.rb +3 -0
  540. data/test/models/tuning_peg.rb +4 -0
  541. data/test/models/tyre.rb +11 -11
  542. data/test/models/user.rb +14 -0
  543. data/test/models/uuid_child.rb +3 -3
  544. data/test/models/uuid_item.rb +6 -0
  545. data/test/models/uuid_parent.rb +3 -3
  546. data/test/models/vegetables.rb +24 -24
  547. data/test/models/vehicle.rb +6 -6
  548. data/test/models/vertex.rb +9 -9
  549. data/test/models/warehouse_thing.rb +5 -5
  550. data/test/models/wheel.rb +3 -3
  551. data/test/models/without_table.rb +3 -3
  552. data/test/models/zine.rb +3 -3
  553. data/test/schema/mysql2_specific_schema.rb +68 -58
  554. data/test/schema/oracle_specific_schema.rb +40 -43
  555. data/test/schema/postgresql_specific_schema.rb +114 -202
  556. data/test/schema/schema.rb +1057 -952
  557. data/test/schema/schema.rb.original +1057 -0
  558. data/test/schema/sqlite_specific_schema.rb +18 -22
  559. data/test/support/config.rb +43 -43
  560. data/test/support/connection.rb +23 -22
  561. data/test/support/connection_helper.rb +14 -14
  562. data/test/support/ddl_helper.rb +8 -8
  563. data/test/support/schema_dumping_helper.rb +20 -20
  564. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  565. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  566. metadata +129 -28
  567. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  568. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  569. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  570. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  571. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  572. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  573. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  574. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  575. data/test/cases/migration/table_and_index_test.rb +0 -24
  576. data/test/cases/relation/where_test2.rb +0 -36
  577. data/test/cases/type/decimal_test.rb +0 -56
  578. data/test/cases/type/unsigned_integer_test.rb +0 -18
  579. data/test/cases/xml_serialization_test.rb +0 -457
  580. data/test/connections/native_ibm_db/connection.rb +0 -44
  581. data/test/fixtures/naked/csv/accounts.csv +0 -1
  582. data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
  583. data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
  584. data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
  585. data/test/schema/mysql_specific_schema.rb +0 -70
  586. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,1429 +1,1514 @@
1
- require "cases/helper"
2
- require 'models/post'
3
- require 'models/tagging'
4
- require 'models/tag'
5
- require 'models/comment'
6
- require 'models/author'
7
- require 'models/essay'
8
- require 'models/category'
9
- require 'models/company'
10
- require 'models/person'
11
- require 'models/reader'
12
- require 'models/owner'
13
- require 'models/pet'
14
- require 'models/reference'
15
- require 'models/job'
16
- require 'models/subscriber'
17
- require 'models/subscription'
18
- require 'models/book'
19
- require 'models/developer'
20
- require 'models/computer'
21
- require 'models/project'
22
- require 'models/member'
23
- require 'models/membership'
24
- require 'models/club'
25
- require 'models/categorization'
26
- require 'models/sponsor'
27
-
28
- class EagerAssociationTest < ActiveRecord::TestCase
29
- fixtures :posts, :comments, :authors, :essays, :author_addresses, :categories, :categories_posts,
30
- :companies, :accounts, :tags, :taggings, :people, :readers, :categorizations,
31
- :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
32
- :developers, :projects, :developers_projects, :members, :memberships, :clubs, :sponsors
33
-
34
- def test_eager_with_has_one_through_join_model_with_conditions_on_the_through
35
- member = Member.all.merge!(:includes => :favourite_club).find(members(:some_other_guy).id)
36
- assert_nil member.favourite_club
37
- end
38
-
39
- def test_loading_with_one_association
40
- posts = Post.all.merge!(:includes => :comments).to_a
41
- post = posts.find { |p| p.id == 1 }
42
- assert_equal 2, post.comments.size
43
- assert post.comments.include?(comments(:greetings))
44
-
45
- post = Post.all.merge!(:includes => :comments, :where => "posts.title = 'Welcome to the weblog'").first
46
- assert_equal 2, post.comments.size
47
- assert post.comments.include?(comments(:greetings))
48
-
49
- posts = Post.all.merge!(:includes => :last_comment).to_a
50
- post = posts.find { |p| p.id == 1 }
51
- assert_equal Post.find(1).last_comment, post.last_comment
52
- end
53
-
54
- def test_loading_with_one_association_with_non_preload
55
- posts = Post.all.merge!(:includes => :last_comment, :order => 'comments.id DESC').to_a
56
- post = posts.find { |p| p.id == 1 }
57
- assert_equal Post.find(1).last_comment, post.last_comment
58
- end
59
-
60
- def test_loading_conditions_with_or
61
- posts = authors(:david).posts.references(:comments).merge(
62
- :includes => :comments,
63
- :where => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'"
64
- ).to_a
65
- assert_nil posts.detect { |p| p.author_id != authors(:david).id },
66
- "expected to find only david's posts"
67
- end
68
-
69
- def test_with_ordering
70
- list = Post.all.merge!(:includes => :comments, :order => "posts.id DESC").to_a
71
- [:other_by_mary, :other_by_bob, :misc_by_mary, :misc_by_bob, :eager_other,
72
- :sti_habtm, :sti_post_and_comments, :sti_comments, :authorless, :thinking, :welcome
73
- ].each_with_index do |post, index|
74
- assert_equal posts(post), list[index]
75
- end
76
- end
77
-
78
- def test_has_many_through_with_order
79
- authors = Author.includes(:favorite_authors).to_a
80
- assert authors.count > 0
81
- assert_no_queries { authors.map(&:favorite_authors) }
82
- end
83
-
84
- def test_eager_loaded_has_one_association_with_references_does_not_run_additional_queries
85
- Post.update_all(author_id: nil)
86
- authors = Author.includes(:post).references(:post).to_a
87
- assert authors.count > 0
88
- assert_no_queries { authors.map(&:post) }
89
- end
90
-
91
- def test_with_two_tables_in_from_without_getting_double_quoted
92
- posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
93
- assert_equal 2, posts.first.comments.size
94
- end
95
-
96
- def test_loading_with_multiple_associations
97
- posts = Post.all.merge!(:includes => [ :comments, :author, :categories ], :order => "posts.id").to_a
98
- assert_equal 2, posts.first.comments.size
99
- assert_equal 2, posts.first.categories.size
100
- assert posts.first.comments.include?(comments(:greetings))
101
- end
102
-
103
- def test_duplicate_middle_objects
104
- comments = Comment.all.merge!(:where => 'post_id = 1', :includes => [:post => :author]).to_a
105
- assert_no_queries do
106
- comments.each {|comment| comment.post.author.name}
107
- end
108
- end
109
-
110
- def test_preloading_has_many_in_multiple_queries_with_more_ids_than_database_can_handle
111
- Comment.connection.expects(:in_clause_length).at_least_once.returns(5)
112
- posts = Post.all.merge!(:includes=>:comments).to_a
113
- assert_equal 11, posts.size
114
- end
115
-
116
- def test_preloading_has_many_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
117
- Comment.connection.expects(:in_clause_length).at_least_once.returns(nil)
118
- posts = Post.all.merge!(:includes=>:comments).to_a
119
- assert_equal 11, posts.size
120
- end
121
-
122
- def test_preloading_habtm_in_multiple_queries_with_more_ids_than_database_can_handle
123
- Comment.connection.expects(:in_clause_length).at_least_once.returns(5)
124
- posts = Post.all.merge!(:includes=>:categories).to_a
125
- assert_equal 11, posts.size
126
- end
127
-
128
- def test_preloading_habtm_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
129
- Comment.connection.expects(:in_clause_length).at_least_once.returns(nil)
130
- posts = Post.all.merge!(:includes=>:categories).to_a
131
- assert_equal 11, posts.size
132
- end
133
-
134
- def test_load_associated_records_in_one_query_when_adapter_has_no_limit
135
- Comment.connection.expects(:in_clause_length).at_least_once.returns(nil)
136
-
137
- post = posts(:welcome)
138
- assert_queries(2) do
139
- Post.includes(:comments).where(:id => post.id).to_a
140
- end
141
- end
142
-
143
- def test_load_associated_records_in_several_queries_when_many_ids_passed
144
- Comment.connection.expects(:in_clause_length).at_least_once.returns(1)
145
-
146
- post1, post2 = posts(:welcome), posts(:thinking)
147
- assert_queries(3) do
148
- Post.includes(:comments).where(:id => [post1.id, post2.id]).to_a
149
- end
150
- end
151
-
152
- def test_load_associated_records_in_one_query_when_a_few_ids_passed
153
- Comment.connection.expects(:in_clause_length).at_least_once.returns(3)
154
-
155
- post = posts(:welcome)
156
- assert_queries(2) do
157
- Post.includes(:comments).where(:id => post.id).to_a
158
- end
159
- end
160
-
161
- def test_including_duplicate_objects_from_belongs_to
162
- popular_post = Post.create!(:title => 'foo', :body => "I like cars!")
163
- comment = popular_post.comments.create!(:body => "lol")
164
- popular_post.readers.create!(:person => people(:michael))
165
- popular_post.readers.create!(:person => people(:david))
166
-
167
- readers = Reader.all.merge!(:where => ["post_id = ?", popular_post.id],
168
- :includes => {:post => :comments}).to_a
169
- readers.each do |reader|
170
- assert_equal [comment], reader.post.comments
171
- end
172
- end
173
-
174
- def test_including_duplicate_objects_from_has_many
175
- car_post = Post.create!(:title => 'foo', :body => "I like cars!")
176
- car_post.categories << categories(:general)
177
- car_post.categories << categories(:technology)
178
-
179
- comment = car_post.comments.create!(:body => "hmm")
180
- categories = Category.all.merge!(:where => { 'posts.id' => car_post.id },
181
- :includes => {:posts => :comments}).to_a
182
- categories.each do |category|
183
- assert_equal [comment], category.posts[0].comments
184
- end
185
- end
186
-
187
- def test_associations_loaded_for_all_records
188
- post = Post.create!(:title => 'foo', :body => "I like cars!")
189
- SpecialComment.create!(:body => 'Come on!', :post => post)
190
- first_category = Category.create! :name => 'First!', :posts => [post]
191
- second_category = Category.create! :name => 'Second!', :posts => [post]
192
-
193
- categories = Category.where(:id => [first_category.id, second_category.id]).includes(:posts => :special_comments)
194
- assert_equal categories.map { |category| category.posts.first.special_comments.loaded? }, [true, true]
195
- end
196
-
197
- def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
198
- author_id = authors(:david).id
199
- author = assert_queries(3) { Author.all.merge!(:includes => {:posts_with_comments => :comments}).find(author_id) } # find the author, then find the posts, then find the comments
200
- author.posts_with_comments.each do |post_with_comments|
201
- assert_equal post_with_comments.comments.length, post_with_comments.comments.count
202
- assert_nil post_with_comments.comments.to_a.uniq!
203
- end
204
- end
205
-
206
- def test_finding_with_includes_on_has_one_association_with_same_include_includes_only_once
207
- author = authors(:david)
208
- post = author.post_about_thinking_with_last_comment
209
- last_comment = post.last_comment
210
- author = assert_queries(3) { Author.all.merge!(:includes => {:post_about_thinking_with_last_comment => :last_comment}).find(author.id)} # find the author, then find the posts, then find the comments
211
- assert_no_queries do
212
- assert_equal post, author.post_about_thinking_with_last_comment
213
- assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
214
- end
215
- end
216
-
217
- def test_finding_with_includes_on_belongs_to_association_with_same_include_includes_only_once
218
- post = posts(:welcome)
219
- author = post.author
220
- author_address = author.author_address
221
- post = assert_queries(3) { Post.all.merge!(:includes => {:author_with_address => :author_address}).find(post.id) } # find the post, then find the author, then find the address
222
- assert_no_queries do
223
- assert_equal author, post.author_with_address
224
- assert_equal author_address, post.author_with_address.author_address
225
- end
226
- end
227
-
228
- def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
229
- post = posts(:welcome)
230
- post.update!(author: nil)
231
- post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) }
232
- # find the post, then find the author which is null so no query for the author or address
233
- assert_no_queries do
234
- assert_equal nil, post.author_with_address
235
- end
236
- end
237
-
238
- def test_finding_with_includes_on_null_belongs_to_polymorphic_association
239
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
240
- sponsor.update!(sponsorable: nil)
241
- sponsor = assert_queries(1) { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
242
- assert_no_queries do
243
- assert_equal nil, sponsor.sponsorable
244
- end
245
- end
246
-
247
- def test_finding_with_includes_on_empty_polymorphic_type_column
248
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
249
- sponsor.update!(sponsorable_type: '', sponsorable_id: nil) # sponsorable_type column might be declared NOT NULL
250
- sponsor = assert_queries(1) do
251
- assert_nothing_raised { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
252
- end
253
- assert_no_queries do
254
- assert_equal nil, sponsor.sponsorable
255
- end
256
- end
257
-
258
- def test_loading_from_an_association
259
- posts = authors(:david).posts.merge(:includes => :comments, :order => "posts.id").to_a
260
- assert_equal 2, posts.first.comments.size
261
- end
262
-
263
- def test_loading_from_an_association_that_has_a_hash_of_conditions
264
- assert_nothing_raised do
265
- Author.all.merge!(:includes => :hello_posts_with_hash_conditions).to_a
266
- end
267
- assert !Author.all.merge!(:includes => :hello_posts_with_hash_conditions).find(authors(:david).id).hello_posts.empty?
268
- end
269
-
270
- def test_loading_with_no_associations
271
- assert_nil Post.all.merge!(:includes => :author).find(posts(:authorless).id).author
272
- end
273
-
274
- # Regression test for 21c75e5
275
- def test_nested_loading_does_not_raise_exception_when_association_does_not_exist
276
- assert_nothing_raised do
277
- Post.all.merge!(:includes => {:author => :author_addresss}).find(posts(:authorless).id)
278
- end
279
- end
280
-
281
- def test_three_level_nested_preloading_does_not_raise_exception_when_association_does_not_exist
282
- post_id = Comment.where(author_id: nil).where.not(post_id: nil).first.post_id
283
-
284
- assert_nothing_raised do
285
- Post.preload(:comments => [{:author => :essays}]).find(post_id)
286
- end
287
- end
288
-
289
- def test_nested_loading_through_has_one_association
290
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}).find(author_addresses(:david_address).id)
291
- assert_equal aa.author.posts.count, aa.author.posts.length
292
- end
293
-
294
- def test_nested_loading_through_has_one_association_with_order
295
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'author_addresses.id').find(author_addresses(:david_address).id)
296
- assert_equal aa.author.posts.count, aa.author.posts.length
297
- end
298
-
299
- def test_nested_loading_through_has_one_association_with_order_on_association
300
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'authors.id').find(author_addresses(:david_address).id)
301
- assert_equal aa.author.posts.count, aa.author.posts.length
302
- end
303
-
304
- def test_nested_loading_through_has_one_association_with_order_on_nested_association
305
- aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'posts.id').find(author_addresses(:david_address).id)
306
- assert_equal aa.author.posts.count, aa.author.posts.length
307
- end
308
-
309
- def test_nested_loading_through_has_one_association_with_conditions
310
- aa = AuthorAddress.references(:author_addresses).merge(
311
- :includes => {:author => :posts},
312
- :where => "author_addresses.id > 0"
313
- ).find author_addresses(:david_address).id
314
- assert_equal aa.author.posts.count, aa.author.posts.length
315
- end
316
-
317
- def test_nested_loading_through_has_one_association_with_conditions_on_association
318
- aa = AuthorAddress.references(:authors).merge(
319
- :includes => {:author => :posts},
320
- :where => "authors.id > 0"
321
- ).find author_addresses(:david_address).id
322
- assert_equal aa.author.posts.count, aa.author.posts.length
323
- end
324
-
325
- def test_nested_loading_through_has_one_association_with_conditions_on_nested_association
326
- aa = AuthorAddress.references(:posts).merge(
327
- :includes => {:author => :posts},
328
- :where => "posts.id > 0"
329
- ).find author_addresses(:david_address).id
330
- assert_equal aa.author.posts.count, aa.author.posts.length
331
- end
332
-
333
- def test_eager_association_loading_with_belongs_to_and_foreign_keys
334
- pets = Pet.all.merge!(:includes => :owner).to_a
335
- assert_equal 4, pets.length
336
- end
337
-
338
- def test_eager_association_loading_with_belongs_to
339
- comments = Comment.all.merge!(:includes => :post).to_a
340
- assert_equal 11, comments.length
341
- titles = comments.map { |c| c.post.title }
342
- assert titles.include?(posts(:welcome).title)
343
- assert titles.include?(posts(:sti_post_and_comments).title)
344
- end
345
-
346
- def test_eager_association_loading_with_belongs_to_and_limit
347
- comments = Comment.all.merge!(:includes => :post, :limit => 5, :order => 'comments.id').to_a
348
- assert_equal 5, comments.length
349
- assert_equal [1,2,3,5,6], comments.collect { |c| c.id }
350
- end
351
-
352
- def test_eager_association_loading_with_belongs_to_and_limit_and_conditions
353
- comments = Comment.all.merge!(:includes => :post, :where => 'post_id = 4', :limit => 3, :order => 'comments.id').to_a
354
- assert_equal 3, comments.length
355
- assert_equal [5,6,7], comments.collect { |c| c.id }
356
- end
357
-
358
- def test_eager_association_loading_with_belongs_to_and_limit_and_offset
359
- comments = Comment.all.merge!(:includes => :post, :limit => 3, :offset => 2, :order => 'comments.id').to_a
360
- assert_equal 3, comments.length
361
- assert_equal [3,5,6], comments.collect { |c| c.id }
362
- end
363
-
364
- def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions
365
- comments = Comment.all.merge!(:includes => :post, :where => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id').to_a
366
- assert_equal 3, comments.length
367
- assert_equal [6,7,8], comments.collect { |c| c.id }
368
- end
369
-
370
- def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array
371
- comments = Comment.all.merge!(:includes => :post, :where => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id').to_a
372
- assert_equal 3, comments.length
373
- assert_equal [6,7,8], comments.collect { |c| c.id }
374
- end
375
-
376
- def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
377
- assert_nothing_raised do
378
- Comment.includes(:post).references(:posts).where('posts.id = ?', 4)
379
- end
380
- end
381
-
382
- def test_eager_association_loading_with_belongs_to_and_conditions_hash
383
- comments = []
384
- assert_nothing_raised do
385
- comments = Comment.all.merge!(:includes => :post, :where => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id').to_a
386
- end
387
- assert_equal 3, comments.length
388
- assert_equal [5,6,7], comments.collect { |c| c.id }
389
- assert_no_queries do
390
- comments.first.post
391
- end
392
- end
393
-
394
- def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
395
- quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
396
- assert_nothing_raised do
397
- Comment.includes(:post).references(:posts).where("#{quoted_posts_id} = ?", 4)
398
- end
399
- end
400
-
401
- def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
402
- assert_nothing_raised do
403
- Comment.all.merge!(:includes => :post, :order => 'posts.id').to_a
404
- end
405
- end
406
-
407
- def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name
408
- quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
409
- assert_nothing_raised do
410
- Comment.includes(:post).references(:posts).order(quoted_posts_id)
411
- end
412
- end
413
-
414
- def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations
415
- posts = Post.all.merge!(:includes => [:author, :very_special_comment], :limit => 1, :order => 'posts.id').to_a
416
- assert_equal 1, posts.length
417
- assert_equal [1], posts.collect { |p| p.id }
418
- end
419
-
420
- def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations
421
- posts = Post.all.merge!(:includes => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id').to_a
422
- assert_equal 1, posts.length
423
- assert_equal [2], posts.collect { |p| p.id }
424
- end
425
-
426
- def test_eager_association_loading_with_belongs_to_inferred_foreign_key_from_association_name
427
- author_favorite = AuthorFavorite.all.merge!(:includes => :favorite_author).first
428
- assert_equal authors(:mary), assert_no_queries { author_favorite.favorite_author }
429
- end
430
-
431
- def test_eager_load_belongs_to_quotes_table_and_column_names
432
- job = Job.includes(:ideal_reference).find jobs(:unicyclist).id
433
- references(:michael_unicyclist)
434
- assert_no_queries{ assert_equal references(:michael_unicyclist), job.ideal_reference}
435
- end
436
-
437
- def test_eager_load_has_one_quotes_table_and_column_names
438
- michael = Person.all.merge!(:includes => :favourite_reference).find(people(:michael).id)
439
- references(:michael_unicyclist)
440
- assert_no_queries{ assert_equal references(:michael_unicyclist), michael.favourite_reference}
441
- end
442
-
443
- def test_eager_load_has_many_quotes_table_and_column_names
444
- michael = Person.all.merge!(:includes => :references).find(people(:michael).id)
445
- references(:michael_magician,:michael_unicyclist)
446
- assert_no_queries{ assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) }
447
- end
448
-
449
- def test_eager_load_has_many_through_quotes_table_and_column_names
450
- michael = Person.all.merge!(:includes => :jobs).find(people(:michael).id)
451
- jobs(:magician, :unicyclist)
452
- assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
453
- end
454
-
455
- def test_eager_load_has_many_with_string_keys
456
- subscriptions = subscriptions(:webster_awdr, :webster_rfr)
457
- subscriber =Subscriber.all.merge!(:includes => :subscriptions).find(subscribers(:second).id)
458
- assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
459
- end
460
-
461
- def test_string_id_column_joins
462
- s = Subscriber.create! do |c|
463
- c.id = "PL"
464
- end
465
-
466
- b = Book.create!
467
-
468
- Subscription.create!(:subscriber_id => "PL", :book_id => b.id)
469
- s.reload
470
- s.book_ids = s.book_ids
471
- end
472
-
473
- def test_eager_load_has_many_through_with_string_keys
474
- books = books(:awdr, :rfr)
475
- subscriber = Subscriber.all.merge!(:includes => :books).find(subscribers(:second).id)
476
- assert_equal books, subscriber.books.sort_by(&:id)
477
- end
478
-
479
- def test_eager_load_belongs_to_with_string_keys
480
- subscriber = subscribers(:second)
481
- subscription = Subscription.all.merge!(:includes => :subscriber).find(subscriptions(:webster_awdr).id)
482
- assert_equal subscriber, subscription.subscriber
483
- end
484
-
485
- def test_eager_association_loading_with_explicit_join
486
- posts = Post.all.merge!(:includes => :comments, :joins => "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", :limit => 1, :order => 'author_id').to_a
487
- assert_equal 1, posts.length
488
- end
489
-
490
- def test_eager_with_has_many_through
491
- posts_with_comments = people(:michael).posts.merge(:includes => :comments, :order => 'posts.id').to_a
492
- posts_with_author = people(:michael).posts.merge(:includes => :author, :order => 'posts.id').to_a
493
- posts_with_comments_and_author = people(:michael).posts.merge(:includes => [ :comments, :author ], :order => 'posts.id').to_a
494
- assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum + post.comments.size }
495
- assert_equal authors(:david), assert_no_queries { posts_with_author.first.author }
496
- assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
497
- end
498
-
499
- def test_eager_with_has_many_through_a_belongs_to_association
500
- author = authors(:mary)
501
- Post.create!(:author => author, :title => "TITLE", :body => "BODY")
502
- author.author_favorites.create(:favorite_author_id => 1)
503
- author.author_favorites.create(:favorite_author_id => 2)
504
- posts_with_author_favorites = author.posts.merge(:includes => :author_favorites).to_a
505
- assert_no_queries { posts_with_author_favorites.first.author_favorites.first.author_id }
506
- end
507
-
508
- def test_eager_with_has_many_through_an_sti_join_model
509
- author = Author.all.merge!(:includes => :special_post_comments, :order => 'authors.id').first
510
- assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }
511
- end
512
-
513
- def test_eager_with_has_many_through_an_sti_join_model_with_conditions_on_both
514
- author = Author.all.merge!(:includes => :special_nonexistant_post_comments, :order => 'authors.id').first
515
- assert_equal [], author.special_nonexistant_post_comments
516
- end
517
-
518
- def test_eager_with_has_many_through_join_model_with_conditions
519
- assert_equal Author.all.merge!(:includes => :hello_post_comments,
520
- :order => 'authors.id').first.hello_post_comments.sort_by(&:id),
521
- Author.all.merge!(:order => 'authors.id').first.hello_post_comments.sort_by(&:id)
522
- end
523
-
524
- def test_eager_with_has_many_through_join_model_with_conditions_on_top_level
525
- assert_equal comments(:more_greetings), Author.all.merge!(:includes => :comments_with_order_and_conditions).find(authors(:david).id).comments_with_order_and_conditions.first
526
- end
527
-
528
- def test_eager_with_has_many_through_join_model_with_include
529
- author_comments = Author.all.merge!(:includes => :comments_with_include).find(authors(:david).id).comments_with_include.to_a
530
- assert_no_queries do
531
- author_comments.first.post.title
532
- end
533
- end
534
-
535
- def test_eager_with_has_many_through_with_conditions_join_model_with_include
536
- post_tags = Post.find(posts(:welcome).id).misc_tags
537
- eager_post_tags = Post.all.merge!(:includes => :misc_tags).find(1).misc_tags
538
- assert_equal post_tags, eager_post_tags
539
- end
540
-
541
- def test_eager_with_has_many_through_join_model_ignores_default_includes
542
- assert_nothing_raised do
543
- authors(:david).comments_on_posts_with_default_include.to_a
544
- end
545
- end
546
-
547
- def test_eager_with_has_many_and_limit
548
- posts = Post.all.merge!(:order => 'posts.id asc', :includes => [ :author, :comments ], :limit => 2).to_a
549
- assert_equal 2, posts.size
550
- assert_equal 3, posts.inject(0) { |sum, post| sum + post.comments.size }
551
- end
552
-
553
- def test_eager_with_has_many_and_limit_and_conditions
554
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => "posts.body = 'hello'", :order => "posts.id").to_a
555
- assert_equal 2, posts.size
556
- assert_equal [4,5], posts.collect { |p| p.id }
557
- end
558
-
559
- def test_eager_with_has_many_and_limit_and_conditions_array
560
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => [ "posts.body = ?", 'hello' ], :order => "posts.id").to_a
561
- assert_equal 2, posts.size
562
- assert_equal [4,5], posts.collect { |p| p.id }
563
- end
564
-
565
- def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
566
- posts = Post.includes(:author, :comments).limit(2).references(:author).where("authors.name = ?", 'David')
567
- assert_equal 2, posts.size
568
-
569
- count = Post.includes(:author, :comments).limit(2).references(:author).where("authors.name = ?", 'David').count
570
- assert_equal posts.size, count
571
- end
572
-
573
- def test_eager_with_has_many_and_limit_and_high_offset
574
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10, :where => { 'authors.name' => 'David' }).to_a
575
- assert_equal 0, posts.size
576
- end
577
-
578
- def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
579
- assert_queries(1) do
580
- posts = Post.references(:authors, :comments).
581
- merge(:includes => [ :author, :comments ], :limit => 2, :offset => 10,
582
- :where => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ]).to_a
583
- assert_equal 0, posts.size
584
- end
585
- end
586
-
587
- def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
588
- assert_queries(1) do
589
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10,
590
- :where => { 'authors.name' => 'David', 'comments.body' => 'go crazy' }).to_a
591
- assert_equal 0, posts.size
592
- end
593
- end
594
-
595
- def test_count_eager_with_has_many_and_limit_and_high_offset
596
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10, :where => { 'authors.name' => 'David' }).count(:all)
597
- assert_equal 0, posts
598
- end
599
-
600
- def test_eager_with_has_many_and_limit_with_no_results
601
- posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => "posts.title = 'magic forest'").to_a
602
- assert_equal 0, posts.size
603
- end
604
-
605
- def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
606
- author = authors(:david)
607
- author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
608
- assert_equal author_posts_without_comments.size, author.posts.includes(:comments).where('comments.id is null').references(:comments).count
609
- end
610
-
611
- def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
612
- person = people(:michael)
613
- person_posts_without_comments = person.posts.select { |post| post.comments.blank? }
614
- assert_equal person_posts_without_comments.size, person.posts_with_no_comments.count
615
- end
616
-
617
- def test_eager_with_has_and_belongs_to_many_and_limit
618
- posts = Post.all.merge!(:includes => :categories, :order => "posts.id", :limit => 3).to_a
619
- assert_equal 3, posts.size
620
- assert_equal 2, posts[0].categories.size
621
- assert_equal 1, posts[1].categories.size
622
- assert_equal 0, posts[2].categories.size
623
- assert posts[0].categories.include?(categories(:technology))
624
- assert posts[1].categories.include?(categories(:general))
625
- end
626
-
627
- # Since the preloader for habtm gets raw row hashes from the database and then
628
- # instantiates them, this test ensures that it only instantiates one actual
629
- # object per record from the database.
630
- def test_has_and_belongs_to_many_should_not_instantiate_same_records_multiple_times
631
- welcome = posts(:welcome)
632
- categories = Category.includes(:posts)
633
-
634
- general = categories.find { |c| c == categories(:general) }
635
- technology = categories.find { |c| c == categories(:technology) }
636
-
637
- post1 = general.posts.to_a.find { |p| p == welcome }
638
- post2 = technology.posts.to_a.find { |p| p == welcome }
639
-
640
- assert_equal post1.object_id, post2.object_id
641
- end
642
-
643
- def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
644
- posts =
645
- authors(:david).posts
646
- .includes(:comments)
647
- .where("comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'")
648
- .references(:comments)
649
- .limit(2)
650
- .to_a
651
- assert_equal 2, posts.size
652
-
653
- count =
654
- Post.includes(:comments, :author)
655
- .where("authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')")
656
- .references(:authors, :comments)
657
- .limit(2)
658
- .count
659
- assert_equal count, posts.size
660
- end
661
-
662
- def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
663
- posts = nil
664
- Post.includes(:comments)
665
- .where("comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'")
666
- .references(:comments)
667
- .scoping do
668
-
669
- posts = authors(:david).posts.limit(2).to_a
670
- assert_equal 2, posts.size
671
- end
672
-
673
- Post.includes(:comments, :author)
674
- .where("authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')")
675
- .references(:authors, :comments)
676
- .scoping do
677
-
678
- count = Post.limit(2).count
679
- assert_equal count, posts.size
680
- end
681
- end
682
-
683
- def test_eager_association_loading_with_habtm
684
- posts = Post.all.merge!(:includes => :categories, :order => "posts.id").to_a
685
- assert_equal 2, posts[0].categories.size
686
- assert_equal 1, posts[1].categories.size
687
- assert_equal 0, posts[2].categories.size
688
- assert posts[0].categories.include?(categories(:technology))
689
- assert posts[1].categories.include?(categories(:general))
690
- end
691
-
692
- def test_eager_with_inheritance
693
- SpecialPost.all.merge!(:includes => [ :comments ]).to_a
694
- end
695
-
696
- def test_eager_has_one_with_association_inheritance
697
- post = Post.all.merge!(:includes => [ :very_special_comment ]).find(4)
698
- assert_equal "VerySpecialComment", post.very_special_comment.class.to_s
699
- end
700
-
701
- def test_eager_has_many_with_association_inheritance
702
- post = Post.all.merge!(:includes => [ :special_comments ]).find(4)
703
- post.special_comments.each do |special_comment|
704
- assert special_comment.is_a?(SpecialComment)
705
- end
706
- end
707
-
708
- def test_eager_habtm_with_association_inheritance
709
- post = Post.all.merge!(:includes => [ :special_categories ]).find(6)
710
- assert_equal 1, post.special_categories.size
711
- post.special_categories.each do |special_category|
712
- assert_equal "SpecialCategory", special_category.class.to_s
713
- end
714
- end
715
-
716
- def test_eager_with_has_one_dependent_does_not_destroy_dependent
717
- assert_not_nil companies(:first_firm).account
718
- f = Firm.all.merge!(:includes => :account,
719
- :where => ["companies.name = ?", "37signals"]).first
720
- assert_not_nil f.account
721
- assert_equal companies(:first_firm, :reload).account, f.account
722
- end
723
-
724
- def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size
725
- author = authors(:david)
726
- posts_with_no_comments = author.posts.select { |post| post.comments.blank? }
727
- assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size
728
- assert_equal posts_with_no_comments, author.posts_with_no_comments
729
- end
730
-
731
- def test_eager_with_invalid_association_reference
732
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
733
- Post.all.merge!(:includes=> :monkeys ).find(6)
734
- }
735
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
736
- Post.all.merge!(:includes=>[ :monkeys ]).find(6)
737
- }
738
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
739
- Post.all.merge!(:includes=>[ 'monkeys' ]).find(6)
740
- }
741
- assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
742
- Post.all.merge!(:includes=>[ :monkeys, :elephants ]).find(6)
743
- }
744
- end
745
-
746
- def test_eager_with_default_scope
747
- developer = EagerDeveloperWithDefaultScope.where(:name => 'David').first
748
- projects = Project.order(:id).to_a
749
- assert_no_queries do
750
- assert_equal(projects, developer.projects)
751
- end
752
- end
753
-
754
- def test_eager_with_default_scope_as_class_method
755
- developer = EagerDeveloperWithClassMethodDefaultScope.where(:name => 'David').first
756
- projects = Project.order(:id).to_a
757
- assert_no_queries do
758
- assert_equal(projects, developer.projects)
759
- end
760
- end
761
-
762
- def test_eager_with_default_scope_as_lambda
763
- developer = EagerDeveloperWithLambdaDefaultScope.where(:name => 'David').first
764
- projects = Project.order(:id).to_a
765
- assert_no_queries do
766
- assert_equal(projects, developer.projects)
767
- end
768
- end
769
-
770
- def test_eager_with_default_scope_as_block
771
- # warm up the habtm cache
772
- EagerDeveloperWithBlockDefaultScope.where(:name => 'David').first.projects
773
- developer = EagerDeveloperWithBlockDefaultScope.where(:name => 'David').first
774
- projects = Project.order(:id).to_a
775
- assert_no_queries do
776
- assert_equal(projects, developer.projects)
777
- end
778
- end
779
-
780
- def test_eager_with_default_scope_as_callable
781
- developer = EagerDeveloperWithCallableDefaultScope.where(:name => 'David').first
782
- projects = Project.order(:id).to_a
783
- assert_no_queries do
784
- assert_equal(projects, developer.projects)
785
- end
786
- end
787
-
788
- def find_all_ordered(className, include=nil)
789
- className.all.merge!(:order=>"#{className.table_name}.#{className.primary_key}", :includes=>include).to_a
790
- end
791
-
792
- def test_limited_eager_with_order
793
- unless current_adapter?(:IBM_DBAdapter)
794
- assert_equal(
795
- posts(:thinking, :sti_comments),
796
- Post.all.merge!(
797
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
798
- :order => 'UPPER(posts.title)', :limit => 2, :offset => 1
799
- ).to_a
800
- )
801
- assert_equal(
802
- posts(:sti_post_and_comments, :sti_comments),
803
- Post.all.merge!(
804
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
805
- :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1
806
- ).to_a
807
- )
808
- else
809
- assert_equal(
810
- posts(:thinking, :sti_comments),
811
- Post.all.merge!(
812
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
813
- :order => 'posts.id', :limit => 2, :offset => 1
814
- ).to_a
815
- )
816
- assert_equal(
817
- posts(:sti_post_and_comments, :sti_comments),
818
- Post.all.merge!(
819
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
820
- :order => 'posts.id DESC', :limit => 2, :offset => 1
821
- ).to_a
822
- )
823
- end
824
- end
825
-
826
- def test_limited_eager_with_multiple_order_columns
827
- unless current_adapter?(:IBM_DBAdapter)
828
- assert_equal(
829
- posts(:thinking, :sti_comments),
830
- Post.all.merge!(
831
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
832
- :order => ['UPPER(posts.title)', 'posts.id'], :limit => 2, :offset => 1
833
- ).to_a
834
- )
835
- assert_equal(
836
- posts(:sti_post_and_comments, :sti_comments),
837
- Post.all.merge!(
838
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
839
- :order => ['UPPER(posts.title) DESC', 'posts.id'], :limit => 2, :offset => 1
840
- ).to_a
841
- )
842
- else
843
- assert_equal(
844
- posts(:thinking, :sti_comments),
845
- Post.all.merge!(
846
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
847
- :order => ['posts.id'], :limit => 2, :offset => 1
848
- ).to_a
849
- )
850
- assert_equal(
851
- posts(:sti_post_and_comments, :sti_comments),
852
- Post.all.merge!(
853
- :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
854
- :order => ['posts.id DESC'], :limit => 2, :offset => 1
855
- ).to_a
856
- )
857
- end
858
- end
859
-
860
- def test_limited_eager_with_numeric_in_association
861
- assert_equal(
862
- people(:david, :susan),
863
- Person.references(:number1_fans_people).merge(
864
- :includes => [:readers, :primary_contact, :number1_fan],
865
- :where => "number1_fans_people.first_name like 'M%'",
866
- :order => 'people.id', :limit => 2, :offset => 0
867
- ).to_a
868
- )
869
- end
870
-
871
- def test_preload_with_interpolation
872
- assert_deprecated do
873
- post = Post.includes(:comments_with_interpolated_conditions).find(posts(:welcome).id)
874
- assert_equal [comments(:greetings)], post.comments_with_interpolated_conditions
875
- end
876
-
877
- assert_deprecated do
878
- post = Post.joins(:comments_with_interpolated_conditions).find(posts(:welcome).id)
879
- assert_equal [comments(:greetings)], post.comments_with_interpolated_conditions
880
- end
881
- end
882
-
883
- def test_polymorphic_type_condition
884
- post = Post.all.merge!(:includes => :taggings).find(posts(:thinking).id)
885
- assert post.taggings.include?(taggings(:thinking_general))
886
- post = SpecialPost.all.merge!(:includes => :taggings).find(posts(:thinking).id)
887
- assert post.taggings.include?(taggings(:thinking_general))
888
- end
889
-
890
- def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm
891
- # Eager includes of has many and habtm associations aren't necessarily sorted in the same way
892
- def assert_equal_after_sort(item1, item2, item3 = nil)
893
- assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id})
894
- assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3
895
- end
896
- # Test regular association, association with conditions, association with
897
- # STI, and association with conditions assured not to be true
898
- post_types = [:posts, :other_posts, :special_posts]
899
- # test both has_many and has_and_belongs_to_many
900
- [Author, Category].each do |className|
901
- d1 = find_all_ordered(className)
902
- # test including all post types at once
903
- d2 = find_all_ordered(className, post_types)
904
- d1.each_index do |i|
905
- assert_equal(d1[i], d2[i])
906
- assert_equal_after_sort(d1[i].posts, d2[i].posts)
907
- post_types[1..-1].each do |post_type|
908
- # test including post_types together
909
- d3 = find_all_ordered(className, [:posts, post_type])
910
- assert_equal(d1[i], d3[i])
911
- assert_equal_after_sort(d1[i].posts, d3[i].posts)
912
- assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type))
913
- end
914
- end
915
- end
916
- end
917
-
918
- def test_eager_with_multiple_associations_with_same_table_has_one
919
- d1 = find_all_ordered(Firm)
920
- d2 = find_all_ordered(Firm, :account)
921
- d1.each_index do |i|
922
- assert_equal(d1[i], d2[i])
923
- assert_equal(d1[i].account, d2[i].account)
924
- end
925
- end
926
-
927
- def test_eager_with_multiple_associations_with_same_table_belongs_to
928
- firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition]
929
- d1 = find_all_ordered(Client)
930
- d2 = find_all_ordered(Client, firm_types)
931
- d1.each_index do |i|
932
- assert_equal(d1[i], d2[i])
933
- firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) }
934
- end
935
- end
936
- def test_eager_with_valid_association_as_string_not_symbol
937
- assert_nothing_raised { Post.all.merge!(:includes => 'comments').to_a }
938
- end
939
-
940
- def test_eager_with_floating_point_numbers
941
- assert_queries(2) do
942
- # Before changes, the floating point numbers will be interpreted as table names and will cause this to run in one query
943
- Comment.all.merge!(:where => "123.456 = 123.456", :includes => :post).to_a
944
- end
945
- end
946
-
947
- def test_preconfigured_includes_with_belongs_to
948
- author = posts(:welcome).author_with_posts
949
- assert_no_queries {assert_equal 5, author.posts.size}
950
- end
951
-
952
- def test_preconfigured_includes_with_has_one
953
- comment = posts(:sti_comments).very_special_comment_with_post
954
- assert_no_queries {assert_equal posts(:sti_comments), comment.post}
955
- end
956
-
957
- def test_eager_association_with_scope_with_joins
958
- assert_nothing_raised do
959
- Post.includes(:very_special_comment_with_post_with_joins).to_a
960
- end
961
- end
962
-
963
- def test_preconfigured_includes_with_has_many
964
- posts = authors(:david).posts_with_comments
965
- one = posts.detect { |p| p.id == 1 }
966
- assert_no_queries do
967
- assert_equal 5, posts.size
968
- assert_equal 2, one.comments.size
969
- end
970
- end
971
-
972
- def test_preconfigured_includes_with_habtm
973
- posts = authors(:david).posts_with_categories
974
- one = posts.detect { |p| p.id == 1 }
975
- assert_no_queries do
976
- assert_equal 5, posts.size
977
- assert_equal 2, one.categories.size
978
- end
979
- end
980
-
981
- def test_preconfigured_includes_with_has_many_and_habtm
982
- posts = authors(:david).posts_with_comments_and_categories
983
- one = posts.detect { |p| p.id == 1 }
984
- assert_no_queries do
985
- assert_equal 5, posts.size
986
- assert_equal 2, one.comments.size
987
- assert_equal 2, one.categories.size
988
- end
989
- end
990
-
991
- def test_count_with_include
992
- assert_equal 3, authors(:david).posts_with_comments.where("length(comments.body) > 15").references(:comments).count
993
- end
994
-
995
- def test_association_loading_notification
996
- notifications = messages_for('instantiation.active_record') do
997
- Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
998
- end
999
-
1000
- message = notifications.first
1001
- payload = message.last
1002
- count = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1003
-
1004
- # eagerloaded row count should be greater than just developer count
1005
- assert_operator payload[:record_count], :>, count
1006
- assert_equal Developer.name, payload[:class_name]
1007
- end
1008
-
1009
- def test_base_messages
1010
- notifications = messages_for('instantiation.active_record') do
1011
- Developer.all.to_a
1012
- end
1013
- message = notifications.first
1014
- payload = message.last
1015
-
1016
- assert_equal Developer.all.to_a.count, payload[:record_count]
1017
- assert_equal Developer.name, payload[:class_name]
1018
- end
1019
-
1020
- def messages_for(name)
1021
- notifications = []
1022
- ActiveSupport::Notifications.subscribe(name) do |*args|
1023
- notifications << args
1024
- end
1025
- yield
1026
- notifications
1027
- ensure
1028
- ActiveSupport::Notifications.unsubscribe(name)
1029
- end
1030
-
1031
- def test_load_with_sti_sharing_association
1032
- assert_queries(2) do #should not do 1 query per subclass
1033
- Comment.includes(:post).to_a
1034
- end
1035
- end
1036
-
1037
- def test_conditions_on_join_table_with_include_and_limit
1038
- assert_equal 3, Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1039
- end
1040
-
1041
- def test_dont_create_temporary_active_record_instances
1042
- Developer.instance_count = 0
1043
- developers = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a
1044
- assert_equal developers.count, Developer.instance_count
1045
- end
1046
-
1047
- def test_order_on_join_table_with_include_and_limit
1048
- assert_equal 5, Developer.all.merge!(:includes => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).to_a.size
1049
- end
1050
-
1051
- def test_eager_loading_with_order_on_joined_table_preloads
1052
- posts = assert_queries(2) do
1053
- Post.all.merge!(:joins => :comments, :includes => :author, :order => 'comments.id DESC').to_a
1054
- end
1055
- assert_equal posts(:eager_other), posts[1]
1056
- assert_equal authors(:mary), assert_no_queries { posts[1].author}
1057
- end
1058
-
1059
- def test_eager_loading_with_conditions_on_joined_table_preloads
1060
- posts = assert_queries(2) do
1061
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => [:comments], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1062
- end
1063
- assert_equal [posts(:welcome)], posts
1064
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1065
-
1066
- posts = assert_queries(2) do
1067
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => [:comments], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1068
- end
1069
- assert_equal [posts(:welcome)], posts
1070
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1071
-
1072
- posts = assert_queries(2) do
1073
- Post.all.merge!(:includes => :author, :joins => {:taggings => :tag}, :where => "tags.name = 'General'", :order => 'posts.id').to_a
1074
- end
1075
- assert_equal posts(:welcome, :thinking), posts
1076
-
1077
- posts = assert_queries(2) do
1078
- Post.all.merge!(:includes => :author, :joins => {:taggings => {:tag => :taggings}}, :where => "taggings_tags.super_tag_id=2", :order => 'posts.id').to_a
1079
- end
1080
- assert_equal posts(:welcome, :thinking), posts
1081
- end
1082
-
1083
- def test_preload_has_many_with_association_condition_and_default_scope
1084
- post = Post.create!(:title => 'Beaches', :body => "I like beaches!")
1085
- Reader.create! :person => people(:david), :post => post
1086
- LazyReader.create! :person => people(:susan), :post => post
1087
-
1088
- assert_equal 1, post.lazy_readers.to_a.size
1089
- assert_equal 2, post.lazy_readers_skimmers_or_not.to_a.size
1090
-
1091
- post_with_readers = Post.includes(:lazy_readers_skimmers_or_not).find(post.id)
1092
- assert_equal 2, post_with_readers.lazy_readers_skimmers_or_not.to_a.size
1093
- end
1094
-
1095
- def test_eager_loading_with_conditions_on_string_joined_table_preloads
1096
- posts = assert_queries(2) do
1097
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1098
- end
1099
- assert_equal [posts(:welcome)], posts
1100
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1101
-
1102
- posts = assert_queries(2) do
1103
- Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1104
- end
1105
- assert_equal [posts(:welcome)], posts
1106
- assert_equal authors(:david), assert_no_queries { posts[0].author}
1107
- end
1108
-
1109
- def test_eager_loading_with_select_on_joined_table_preloads
1110
- posts = assert_queries(2) do
1111
- Post.all.merge!(:select => 'posts.*, authors.name as author_name', :includes => :comments, :joins => :author, :order => 'posts.id').to_a
1112
- end
1113
- assert_equal 'David', posts[0].author_name
1114
- assert_equal posts(:welcome).comments, assert_no_queries { posts[0].comments}
1115
- end
1116
-
1117
- def test_eager_loading_with_conditions_on_join_model_preloads
1118
- authors = assert_queries(2) do
1119
- Author.all.merge!(:includes => :author_address, :joins => :comments, :where => "posts.title like 'Welcome%'").to_a
1120
- end
1121
- assert_equal authors(:david), authors[0]
1122
- assert_equal author_addresses(:david_address), authors[0].author_address
1123
- end
1124
-
1125
- def test_preload_belongs_to_uses_exclusive_scope
1126
- people = Person.males.merge(:includes => :primary_contact).to_a
1127
- assert_not_equal people.length, 0
1128
- people.each do |person|
1129
- assert_no_queries {assert_not_nil person.primary_contact}
1130
- assert_equal Person.find(person.id).primary_contact, person.primary_contact
1131
- end
1132
- end
1133
-
1134
- def test_preload_has_many_uses_exclusive_scope
1135
- people = Person.males.includes(:agents).to_a
1136
- people.each do |person|
1137
- assert_equal Person.find(person.id).agents, person.agents
1138
- end
1139
- end
1140
-
1141
- def test_preload_has_many_using_primary_key
1142
- expected = Firm.first.clients_using_primary_key.to_a
1143
- firm = Firm.includes(:clients_using_primary_key).first
1144
- assert_no_queries do
1145
- assert_equal expected, firm.clients_using_primary_key
1146
- end
1147
- end
1148
-
1149
- def test_include_has_many_using_primary_key
1150
- expected = Firm.find(1).clients_using_primary_key.sort_by(&:name)
1151
- # Oracle adapter truncates alias to 30 characters
1152
- if current_adapter?(:OracleAdapter)
1153
- firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies'[0,30]+'.name').find(1)
1154
- elsif current_adapter?(:IBM_DBAdapter)
1155
- #firm = Firm.all.merge!(:includes => :clients_using_primary_key).find(1)
1156
- firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name').find(1)
1157
- else
1158
- firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name').find(1)
1159
- end
1160
- assert_no_queries do
1161
- assert_equal expected, firm.clients_using_primary_key
1162
- end
1163
- end
1164
-
1165
- def test_preload_has_one_using_primary_key
1166
- expected = accounts(:signals37)
1167
- firm = Firm.all.merge!(:includes => :account_using_primary_key, :order => 'companies.id').first
1168
- assert_no_queries do
1169
- assert_equal expected, firm.account_using_primary_key
1170
- end
1171
- end
1172
-
1173
- def test_include_has_one_using_primary_key
1174
- expected = accounts(:signals37)
1175
- firm = Firm.all.merge!(:includes => :account_using_primary_key, :order => 'accounts.id').to_a.detect {|f| f.id == 1}
1176
- assert_no_queries do
1177
- assert_equal expected, firm.account_using_primary_key
1178
- end
1179
- end
1180
-
1181
- def test_preloading_empty_belongs_to
1182
- c = Client.create!(:name => 'Foo', :client_of => Company.maximum(:id) + 1)
1183
-
1184
- client = assert_queries(2) { Client.preload(:firm).find(c.id) }
1185
- assert_no_queries { assert_nil client.firm }
1186
- end
1187
-
1188
- def test_preloading_empty_belongs_to_polymorphic
1189
- t = Tagging.create!(:taggable_type => 'Post', :taggable_id => Post.maximum(:id) + 1, :tag => tags(:general))
1190
-
1191
- tagging = assert_queries(2) { Tagging.preload(:taggable).find(t.id) }
1192
- assert_no_queries { assert_nil tagging.taggable }
1193
- end
1194
-
1195
- def test_preloading_through_empty_belongs_to
1196
- c = Client.create!(:name => 'Foo', :client_of => Company.maximum(:id) + 1)
1197
-
1198
- client = assert_queries(2) { Client.preload(:accounts).find(c.id) }
1199
- assert_no_queries { assert client.accounts.empty? }
1200
- end
1201
-
1202
- def test_preloading_has_many_through_with_uniq
1203
- mary = Author.includes(:unique_categorized_posts).where(:id => authors(:mary).id).first
1204
- assert_equal 1, mary.unique_categorized_posts.length
1205
- assert_equal 1, mary.unique_categorized_post_ids.length
1206
- end
1207
-
1208
- def test_preloading_has_one_using_reorder
1209
- klass = Class.new(ActiveRecord::Base) do
1210
- def self.name; "TempAuthor"; end
1211
- self.table_name = "authors"
1212
- has_one :post, class_name: "PostWithDefaultScope", foreign_key: :author_id
1213
- has_one :reorderd_post, -> { reorder(title: :desc) }, class_name: "PostWithDefaultScope", foreign_key: :author_id
1214
- end
1215
-
1216
- author = klass.first
1217
- # PRECONDITION: make sure ordering results in different results
1218
- assert_not_equal author.post, author.reorderd_post
1219
-
1220
- preloaded_reorderd_post = klass.preload(:reorderd_post).first.reorderd_post
1221
-
1222
- assert_equal author.reorderd_post, preloaded_reorderd_post
1223
- assert_equal Post.order(title: :desc).first.title, preloaded_reorderd_post.title
1224
- end
1225
-
1226
- def test_preloading_polymorphic_with_custom_foreign_type
1227
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
1228
- groucho = members(:groucho)
1229
-
1230
- sponsor = assert_queries(2) {
1231
- Sponsor.includes(:thing).where(:id => sponsor.id).first
1232
- }
1233
- assert_no_queries { assert_equal groucho, sponsor.thing }
1234
- end
1235
-
1236
- def test_joins_with_includes_should_preload_via_joins
1237
- post = assert_queries(1) { Post.includes(:comments).joins(:comments).order('posts.id desc').to_a.first }
1238
-
1239
- assert_queries(0) do
1240
- assert_not_equal 0, post.comments.to_a.count
1241
- end
1242
- end
1243
-
1244
- def test_join_eager_with_empty_order_should_generate_valid_sql
1245
- assert_nothing_raised(ActiveRecord::StatementInvalid) do
1246
- Post.includes(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
1247
- end
1248
- end
1249
-
1250
- def test_join_eager_with_nil_order_should_generate_valid_sql
1251
- assert_nothing_raised(ActiveRecord::StatementInvalid) do
1252
- Post.includes(:comments).order(nil).where(:comments => {:body => "Thank you for the welcome"}).first
1253
- end
1254
- end
1255
-
1256
- def test_deep_including_through_habtm
1257
- # warm up habtm cache
1258
- posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1259
- posts[0].categories[0].categorizations.length
1260
-
1261
- posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1262
- assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.length }
1263
- assert_no_queries { assert_equal 1, posts[0].categories[1].categorizations.length }
1264
- assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.length }
1265
- end
1266
-
1267
- test "scoping with a circular preload" do
1268
- assert_equal Comment.find(1), Comment.preload(:post => :comments).scoping { Comment.find(1) }
1269
- end
1270
-
1271
- test "circular preload does not modify unscoped" do
1272
- expected = FirstPost.unscoped.find(2)
1273
- FirstPost.preload(:comments => :first_post).find(1)
1274
- assert_equal expected, FirstPost.unscoped.find(2)
1275
- end
1276
-
1277
- test "preload ignores the scoping" do
1278
- assert_equal(
1279
- Comment.find(1).post,
1280
- Post.where('1 = 0').scoping { Comment.preload(:post).find(1).post }
1281
- )
1282
- end
1283
-
1284
- test "deep preload" do
1285
- post = Post.preload(author: :posts, comments: :post).first
1286
-
1287
- assert_predicate post.author.association(:posts), :loaded?
1288
- assert_predicate post.comments.first.association(:post), :loaded?
1289
- end
1290
-
1291
- test "preloading does not cache has many association subset when preloaded with a through association" do
1292
- author = Author.includes(:comments_with_order_and_conditions, :posts).first
1293
- assert_no_queries { assert_equal 2, author.comments_with_order_and_conditions.size }
1294
- assert_no_queries { assert_equal 5, author.posts.size, "should not cache a subset of the association" }
1295
- end
1296
-
1297
- test "preloading a through association twice does not reset it" do
1298
- members = Member.includes(current_membership: :club).includes(:club).to_a
1299
- assert_no_queries {
1300
- assert_equal 3, members.map(&:current_membership).map(&:club).size
1301
- }
1302
- end
1303
-
1304
- test "works in combination with order(:symbol) and reorder(:symbol)" do
1305
- author = Author.includes(:posts).references(:posts).order(:name).find_by('posts.title IS NOT NULL')
1306
- assert_equal authors(:bob), author
1307
-
1308
- author = Author.includes(:posts).references(:posts).reorder(:name).find_by('posts.title IS NOT NULL')
1309
- assert_equal authors(:bob), author
1310
- end
1311
-
1312
- test "preloading with a polymorphic association and using the existential predicate but also using a select" do
1313
- assert_equal authors(:david), authors(:david).essays.includes(:writer).first.writer
1314
-
1315
- assert_nothing_raised do
1316
- authors(:david).essays.includes(:writer).select(:name).any?
1317
- end
1318
- end
1319
-
1320
- test "preloading the same association twice works" do
1321
- Member.create!
1322
- members = Member.preload(:current_membership).includes(current_membership: :club).all.to_a
1323
- assert_no_queries {
1324
- members_with_membership = members.select(&:current_membership)
1325
- assert_equal 3, members_with_membership.map(&:current_membership).map(&:club).size
1326
- }
1327
- end
1328
-
1329
- test "preloading with a polymorphic association and using the existential predicate" do
1330
- assert_equal authors(:david), authors(:david).essays.includes(:writer).first.writer
1331
-
1332
- assert_nothing_raised do
1333
- authors(:david).essays.includes(:writer).any?
1334
- end
1335
- end
1336
-
1337
- test "preloading associations with string joins and order references" do
1338
- author = assert_queries(2) {
1339
- Author.includes(:posts).joins("LEFT JOIN posts ON posts.author_id = authors.id").order("posts.title DESC").first
1340
- }
1341
- assert_no_queries {
1342
- assert_equal 5, author.posts.size
1343
- }
1344
- end
1345
-
1346
- test "including associations with where.not adds implicit references" do
1347
- author = assert_queries(2) {
1348
- Author.includes(:posts).where.not(posts: { title: 'Welcome to the weblog'} ).last
1349
- }
1350
-
1351
- assert_no_queries {
1352
- assert_equal 2, author.posts.size
1353
- }
1354
- end
1355
-
1356
- test "including association based on sql condition and no database column" do
1357
- assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet
1358
- end
1359
-
1360
- test "include instance dependent associations is deprecated" do
1361
- message = "association scope 'posts_with_signature' is"
1362
- assert_deprecated message do
1363
- begin
1364
- Author.includes(:posts_with_signature).to_a
1365
- rescue NoMethodError
1366
- # it's expected that preloading of this association fails
1367
- end
1368
- end
1369
-
1370
- assert_deprecated message do
1371
- Author.preload(:posts_with_signature).to_a rescue NoMethodError
1372
- end
1373
-
1374
- assert_deprecated message do
1375
- Author.eager_load(:posts_with_signature).to_a
1376
- end
1377
- end
1378
-
1379
- test "associations with extensions are not instance dependent" do
1380
- assert_not_deprecated do
1381
- Author.includes(:posts_with_extension).to_a
1382
- end
1383
- end
1384
-
1385
- test "including associations with extensions and an instance dependent scope is deprecated" do
1386
- assert_deprecated do
1387
- Author.includes(:posts_with_extension_and_instance).to_a
1388
- end
1389
- end
1390
-
1391
- test "preloading readonly association" do
1392
- # has-one
1393
- firm = Firm.where(id: "1").preload(:readonly_account).first!
1394
- assert firm.readonly_account.readonly?
1395
-
1396
- # has_and_belongs_to_many
1397
- project = Project.where(id: "2").preload(:readonly_developers).first!
1398
- assert project.readonly_developers.first.readonly?
1399
-
1400
- # has-many :through
1401
- david = Author.where(id: "1").preload(:readonly_comments).first!
1402
- assert david.readonly_comments.first.readonly?
1403
- end
1404
-
1405
- test "eager-loading readonly association" do
1406
- skip "eager_load does not yet preserve readonly associations"
1407
- # has-one
1408
- firm = Firm.where(id: "1").eager_load(:readonly_account).first!
1409
- assert firm.readonly_account.readonly?
1410
-
1411
- # has_and_belongs_to_many
1412
- project = Project.where(id: "2").eager_load(:readonly_developers).first!
1413
- assert project.readonly_developers.first.readonly?
1414
-
1415
- # has-many :through
1416
- david = Author.where(id: "1").eager_load(:readonly_comments).first!
1417
- assert david.readonly_comments.first.readonly?
1418
- end
1419
-
1420
- test "preloading a polymorphic association with references to the associated table" do
1421
- post = Post.includes(:tags).references(:tags).where('tags.name = ?', 'General').first
1422
- assert_equal posts(:welcome), post
1423
- end
1424
-
1425
- test "eager-loading a polymorphic association with references to the associated table" do
1426
- post = Post.eager_load(:tags).where('tags.name = ?', 'General').first
1427
- assert_equal posts(:welcome), post
1428
- end
1429
- end
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/tagging'
4
+ require 'models/tag'
5
+ require 'models/comment'
6
+ require 'models/author'
7
+ require 'models/essay'
8
+ require 'models/category'
9
+ require 'models/company'
10
+ require 'models/person'
11
+ require 'models/reader'
12
+ require 'models/owner'
13
+ require 'models/pet'
14
+ require 'models/reference'
15
+ require 'models/job'
16
+ require 'models/subscriber'
17
+ require 'models/subscription'
18
+ require 'models/book'
19
+ require 'models/developer'
20
+ require 'models/computer'
21
+ require 'models/project'
22
+ require 'models/member'
23
+ require 'models/membership'
24
+ require 'models/club'
25
+ require 'models/categorization'
26
+ require 'models/sponsor'
27
+ require 'models/mentor'
28
+ require 'models/contract'
29
+
30
+ class EagerAssociationTest < ActiveRecord::TestCase
31
+ fixtures :posts, :comments, :authors, :essays, :author_addresses, :categories, :categories_posts,
32
+ :companies, :accounts, :tags, :taggings, :people, :readers, :categorizations,
33
+ :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
34
+ :developers, :projects, :developers_projects, :members, :memberships, :clubs, :sponsors
35
+
36
+ def test_eager_with_has_one_through_join_model_with_conditions_on_the_through
37
+ member = Member.all.merge!(:includes => :favourite_club).find(members(:some_other_guy).id)
38
+ assert_nil member.favourite_club
39
+ end
40
+
41
+ def test_loading_with_one_association
42
+ posts = Post.all.merge!(:includes => :comments).to_a
43
+ post = posts.find { |p| p.id == 1 }
44
+ assert_equal 2, post.comments.size
45
+ assert post.comments.include?(comments(:greetings))
46
+
47
+ post = Post.all.merge!(:includes => :comments, :where => "posts.title = 'Welcome to the weblog'").first
48
+ assert_equal 2, post.comments.size
49
+ assert post.comments.include?(comments(:greetings))
50
+
51
+ posts = Post.all.merge!(:includes => :last_comment).to_a
52
+ post = posts.find { |p| p.id == 1 }
53
+ assert_equal Post.find(1).last_comment, post.last_comment
54
+ end
55
+
56
+ def test_loading_with_one_association_with_non_preload
57
+ posts = Post.all.merge!(:includes => :last_comment, :order => 'comments.id DESC').to_a
58
+ post = posts.find { |p| p.id == 1 }
59
+ assert_equal Post.find(1).last_comment, post.last_comment
60
+ end
61
+
62
+ def test_loading_conditions_with_or
63
+ posts = authors(:david).posts.references(:comments).merge(
64
+ :includes => :comments,
65
+ :where => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'"
66
+ ).to_a
67
+ assert_nil posts.detect { |p| p.author_id != authors(:david).id },
68
+ "expected to find only david's posts"
69
+ end
70
+
71
+ def test_loading_with_scope_including_joins
72
+ assert_equal clubs(:boring_club), Member.preload(:general_club).find(1).general_club
73
+ end
74
+
75
+ def test_with_ordering
76
+ list = Post.all.merge!(:includes => :comments, :order => "posts.id DESC").to_a
77
+ [:other_by_mary, :other_by_bob, :misc_by_mary, :misc_by_bob, :eager_other,
78
+ :sti_habtm, :sti_post_and_comments, :sti_comments, :authorless, :thinking, :welcome
79
+ ].each_with_index do |post, index|
80
+ assert_equal posts(post), list[index]
81
+ end
82
+ end
83
+
84
+ def test_has_many_through_with_order
85
+ authors = Author.includes(:favorite_authors).to_a
86
+ assert authors.count > 0
87
+ assert_no_queries { authors.map(&:favorite_authors) }
88
+ end
89
+
90
+ def test_eager_loaded_has_one_association_with_references_does_not_run_additional_queries
91
+ Post.update_all(author_id: nil)
92
+ authors = Author.includes(:post).references(:post).to_a
93
+ assert authors.count > 0
94
+ assert_no_queries { authors.map(&:post) }
95
+ end
96
+
97
+ def test_with_two_tables_in_from_without_getting_double_quoted
98
+ posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
99
+ assert_equal 2, posts.first.comments.size
100
+ end
101
+
102
+ def test_loading_with_multiple_associations
103
+ posts = Post.all.merge!(:includes => [ :comments, :author, :categories ], :order => "posts.id").to_a
104
+ assert_equal 2, posts.first.comments.size
105
+ assert_equal 2, posts.first.categories.size
106
+ assert posts.first.comments.include?(comments(:greetings))
107
+ end
108
+
109
+ def test_duplicate_middle_objects
110
+ comments = Comment.all.merge!(:where => 'post_id = 1', :includes => [:post => :author]).to_a
111
+ assert_no_queries do
112
+ comments.each {|comment| comment.post.author.name}
113
+ end
114
+ end
115
+
116
+ def test_preloading_has_many_in_multiple_queries_with_more_ids_than_database_can_handle
117
+ assert_called(Comment.connection, :in_clause_length, returns: 5) do
118
+ posts = Post.all.merge!(:includes=>:comments).to_a
119
+ assert_equal 11, posts.size
120
+ end
121
+ end
122
+
123
+ def test_preloading_has_many_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
124
+ assert_called(Comment.connection, :in_clause_length, returns: nil) do
125
+ posts = Post.all.merge!(:includes=>:comments).to_a
126
+ assert_equal 11, posts.size
127
+ end
128
+ end
129
+
130
+ def test_preloading_habtm_in_multiple_queries_with_more_ids_than_database_can_handle
131
+ assert_called(Comment.connection, :in_clause_length, times: 2, returns: 5) do
132
+ posts = Post.all.merge!(:includes=>:categories).to_a
133
+ assert_equal 11, posts.size
134
+ end
135
+ end
136
+
137
+ def test_preloading_habtm_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
138
+ assert_called(Comment.connection, :in_clause_length, times: 2, returns: nil) do
139
+ posts = Post.all.merge!(:includes=>:categories).to_a
140
+ assert_equal 11, posts.size
141
+ end
142
+ end
143
+
144
+ def test_load_associated_records_in_one_query_when_adapter_has_no_limit
145
+ assert_called(Comment.connection, :in_clause_length, returns: nil) do
146
+ post = posts(:welcome)
147
+ assert_queries(2) do
148
+ Post.includes(:comments).where(:id => post.id).to_a
149
+ end
150
+ end
151
+ end
152
+
153
+ def test_load_associated_records_in_several_queries_when_many_ids_passed
154
+ assert_called(Comment.connection, :in_clause_length, returns: 1) do
155
+ post1, post2 = posts(:welcome), posts(:thinking)
156
+ assert_queries(3) do
157
+ Post.includes(:comments).where(:id => [post1.id, post2.id]).to_a
158
+ end
159
+ end
160
+ end
161
+
162
+ def test_load_associated_records_in_one_query_when_a_few_ids_passed
163
+ assert_called(Comment.connection, :in_clause_length, returns: 3) do
164
+ post = posts(:welcome)
165
+ assert_queries(2) do
166
+ Post.includes(:comments).where(:id => post.id).to_a
167
+ end
168
+ end
169
+ end
170
+
171
+ def test_including_duplicate_objects_from_belongs_to
172
+ popular_post = Post.create!(:title => 'foo', :body => "I like cars!")
173
+ comment = popular_post.comments.create!(:body => "lol")
174
+ popular_post.readers.create!(:person => people(:michael))
175
+ popular_post.readers.create!(:person => people(:david))
176
+
177
+ readers = Reader.all.merge!(:where => ["post_id = ?", popular_post.id],
178
+ :includes => {:post => :comments}).to_a
179
+ readers.each do |reader|
180
+ assert_equal [comment], reader.post.comments
181
+ end
182
+ end
183
+
184
+ def test_including_duplicate_objects_from_has_many
185
+ car_post = Post.create!(:title => 'foo', :body => "I like cars!")
186
+ car_post.categories << categories(:general)
187
+ car_post.categories << categories(:technology)
188
+
189
+ comment = car_post.comments.create!(:body => "hmm")
190
+ categories = Category.all.merge!(:where => { 'posts.id' => car_post.id },
191
+ :includes => {:posts => :comments}).to_a
192
+ categories.each do |category|
193
+ assert_equal [comment], category.posts[0].comments
194
+ end
195
+ end
196
+
197
+ def test_associations_loaded_for_all_records
198
+ post = Post.create!(:title => 'foo', :body => "I like cars!")
199
+ SpecialComment.create!(:body => 'Come on!', :post => post)
200
+ first_category = Category.create! :name => 'First!', :posts => [post]
201
+ second_category = Category.create! :name => 'Second!', :posts => [post]
202
+
203
+ categories = Category.where(:id => [first_category.id, second_category.id]).includes(:posts => :special_comments)
204
+ assert_equal categories.map { |category| category.posts.first.special_comments.loaded? }, [true, true]
205
+ end
206
+
207
+ def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
208
+ author_id = authors(:david).id
209
+ author = assert_queries(3) { Author.all.merge!(:includes => {:posts_with_comments => :comments}).find(author_id) } # find the author, then find the posts, then find the comments
210
+ author.posts_with_comments.each do |post_with_comments|
211
+ assert_equal post_with_comments.comments.length, post_with_comments.comments.count
212
+ assert_nil post_with_comments.comments.to_a.uniq!
213
+ end
214
+ end
215
+
216
+ def test_finding_with_includes_on_has_one_association_with_same_include_includes_only_once
217
+ author = authors(:david)
218
+ post = author.post_about_thinking_with_last_comment
219
+ last_comment = post.last_comment
220
+ author = assert_queries(3) { Author.all.merge!(:includes => {:post_about_thinking_with_last_comment => :last_comment}).find(author.id)} # find the author, then find the posts, then find the comments
221
+ assert_no_queries do
222
+ assert_equal post, author.post_about_thinking_with_last_comment
223
+ assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
224
+ end
225
+ end
226
+
227
+ def test_finding_with_includes_on_belongs_to_association_with_same_include_includes_only_once
228
+ post = posts(:welcome)
229
+ author = post.author
230
+ author_address = author.author_address
231
+ post = assert_queries(3) { Post.all.merge!(:includes => {:author_with_address => :author_address}).find(post.id) } # find the post, then find the author, then find the address
232
+ assert_no_queries do
233
+ assert_equal author, post.author_with_address
234
+ assert_equal author_address, post.author_with_address.author_address
235
+ end
236
+ end
237
+
238
+ def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
239
+ post = posts(:welcome)
240
+ post.update!(author: nil)
241
+ post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) }
242
+ # find the post, then find the author which is null so no query for the author or address
243
+ assert_no_queries do
244
+ assert_equal nil, post.author_with_address
245
+ end
246
+ end
247
+
248
+ def test_finding_with_includes_on_null_belongs_to_polymorphic_association
249
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
250
+ sponsor.update!(sponsorable: nil)
251
+ sponsor = assert_queries(1) { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
252
+ assert_no_queries do
253
+ assert_equal nil, sponsor.sponsorable
254
+ end
255
+ end
256
+
257
+ def test_finding_with_includes_on_empty_polymorphic_type_column
258
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
259
+ sponsor.update!(sponsorable_type: '', sponsorable_id: nil) # sponsorable_type column might be declared NOT NULL
260
+ sponsor = assert_queries(1) do
261
+ assert_nothing_raised { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
262
+ end
263
+ assert_no_queries do
264
+ assert_equal nil, sponsor.sponsorable
265
+ end
266
+ end
267
+
268
+ def test_loading_from_an_association
269
+ posts = authors(:david).posts.merge(:includes => :comments, :order => "posts.id").to_a
270
+ assert_equal 2, posts.first.comments.size
271
+ end
272
+
273
+ def test_loading_from_an_association_that_has_a_hash_of_conditions
274
+ assert_nothing_raised do
275
+ Author.all.merge!(:includes => :hello_posts_with_hash_conditions).to_a
276
+ end
277
+ assert !Author.all.merge!(:includes => :hello_posts_with_hash_conditions).find(authors(:david).id).hello_posts.empty?
278
+ end
279
+
280
+ def test_loading_with_no_associations
281
+ assert_nil Post.all.merge!(:includes => :author).find(posts(:authorless).id).author
282
+ end
283
+
284
+ # Regression test for 21c75e5
285
+ def test_nested_loading_does_not_raise_exception_when_association_does_not_exist
286
+ assert_nothing_raised do
287
+ Post.all.merge!(:includes => {:author => :author_addresss}).find(posts(:authorless).id)
288
+ end
289
+ end
290
+
291
+ def test_three_level_nested_preloading_does_not_raise_exception_when_association_does_not_exist
292
+ post_id = Comment.where(author_id: nil).where.not(post_id: nil).first.post_id
293
+
294
+ assert_nothing_raised do
295
+ Post.preload(:comments => [{:author => :essays}]).find(post_id)
296
+ end
297
+ end
298
+
299
+ def test_nested_loading_through_has_one_association
300
+ aa = AuthorAddress.all.merge!(:includes => {:author => :posts}).find(author_addresses(:david_address).id)
301
+ assert_equal aa.author.posts.count, aa.author.posts.length
302
+ end
303
+
304
+ def test_nested_loading_through_has_one_association_with_order
305
+ aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'author_addresses.id').find(author_addresses(:david_address).id)
306
+ assert_equal aa.author.posts.count, aa.author.posts.length
307
+ end
308
+
309
+ def test_nested_loading_through_has_one_association_with_order_on_association
310
+ aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'authors.id').find(author_addresses(:david_address).id)
311
+ assert_equal aa.author.posts.count, aa.author.posts.length
312
+ end
313
+
314
+ def test_nested_loading_through_has_one_association_with_order_on_nested_association
315
+ aa = AuthorAddress.all.merge!(:includes => {:author => :posts}, :order => 'posts.id').find(author_addresses(:david_address).id)
316
+ assert_equal aa.author.posts.count, aa.author.posts.length
317
+ end
318
+
319
+ def test_nested_loading_through_has_one_association_with_conditions
320
+ aa = AuthorAddress.references(:author_addresses).merge(
321
+ :includes => {:author => :posts},
322
+ :where => "author_addresses.id > 0"
323
+ ).find author_addresses(:david_address).id
324
+ assert_equal aa.author.posts.count, aa.author.posts.length
325
+ end
326
+
327
+ def test_nested_loading_through_has_one_association_with_conditions_on_association
328
+ aa = AuthorAddress.references(:authors).merge(
329
+ :includes => {:author => :posts},
330
+ :where => "authors.id > 0"
331
+ ).find author_addresses(:david_address).id
332
+ assert_equal aa.author.posts.count, aa.author.posts.length
333
+ end
334
+
335
+ def test_nested_loading_through_has_one_association_with_conditions_on_nested_association
336
+ aa = AuthorAddress.references(:posts).merge(
337
+ :includes => {:author => :posts},
338
+ :where => "posts.id > 0"
339
+ ).find author_addresses(:david_address).id
340
+ assert_equal aa.author.posts.count, aa.author.posts.length
341
+ end
342
+
343
+ def test_eager_association_loading_with_belongs_to_and_foreign_keys
344
+ pets = Pet.all.merge!(:includes => :owner).to_a
345
+ assert_equal 4, pets.length
346
+ end
347
+
348
+ def test_eager_association_loading_with_belongs_to
349
+ comments = Comment.all.merge!(:includes => :post).to_a
350
+ assert_equal 11, comments.length
351
+ titles = comments.map { |c| c.post.title }
352
+ assert titles.include?(posts(:welcome).title)
353
+ assert titles.include?(posts(:sti_post_and_comments).title)
354
+ end
355
+
356
+ def test_eager_association_loading_with_belongs_to_and_limit
357
+ comments = Comment.all.merge!(:includes => :post, :limit => 5, :order => 'comments.id').to_a
358
+ assert_equal 5, comments.length
359
+ assert_equal [1,2,3,5,6], comments.collect(&:id)
360
+ end
361
+
362
+ def test_eager_association_loading_with_belongs_to_and_limit_and_conditions
363
+ comments = Comment.all.merge!(:includes => :post, :where => 'post_id = 4', :limit => 3, :order => 'comments.id').to_a
364
+ assert_equal 3, comments.length
365
+ assert_equal [5,6,7], comments.collect(&:id)
366
+ end
367
+
368
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset
369
+ comments = Comment.all.merge!(:includes => :post, :limit => 3, :offset => 2, :order => 'comments.id').to_a
370
+ assert_equal 3, comments.length
371
+ assert_equal [3,5,6], comments.collect(&:id)
372
+ end
373
+
374
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions
375
+ comments = Comment.all.merge!(:includes => :post, :where => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id').to_a
376
+ assert_equal 3, comments.length
377
+ assert_equal [6,7,8], comments.collect(&:id)
378
+ end
379
+
380
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array
381
+ comments = Comment.all.merge!(:includes => :post, :where => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id').to_a
382
+ assert_equal 3, comments.length
383
+ assert_equal [6,7,8], comments.collect(&:id)
384
+ end
385
+
386
+ def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
387
+ assert_nothing_raised do
388
+ Comment.includes(:post).references(:posts).where('posts.id = ?', 4)
389
+ end
390
+ end
391
+
392
+ def test_eager_association_loading_with_belongs_to_and_conditions_hash
393
+ comments = []
394
+ assert_nothing_raised do
395
+ comments = Comment.all.merge!(:includes => :post, :where => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id').to_a
396
+ end
397
+ assert_equal 3, comments.length
398
+ assert_equal [5,6,7], comments.collect(&:id)
399
+ assert_no_queries do
400
+ comments.first.post
401
+ end
402
+ end
403
+
404
+ def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
405
+ quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
406
+ assert_nothing_raised do
407
+ Comment.includes(:post).references(:posts).where("#{quoted_posts_id} = ?", 4)
408
+ end
409
+ end
410
+
411
+ def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
412
+ assert_nothing_raised do
413
+ Comment.all.merge!(:includes => :post, :order => 'posts.id').to_a
414
+ end
415
+ end
416
+
417
+ def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name
418
+ quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
419
+ assert_nothing_raised do
420
+ Comment.includes(:post).references(:posts).order(quoted_posts_id)
421
+ end
422
+ end
423
+
424
+ def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations
425
+ posts = Post.all.merge!(:includes => [:author, :very_special_comment], :limit => 1, :order => 'posts.id').to_a
426
+ assert_equal 1, posts.length
427
+ assert_equal [1], posts.collect(&:id)
428
+ end
429
+
430
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations
431
+ posts = Post.all.merge!(:includes => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id').to_a
432
+ assert_equal 1, posts.length
433
+ assert_equal [2], posts.collect(&:id)
434
+ end
435
+
436
+ def test_eager_association_loading_with_belongs_to_inferred_foreign_key_from_association_name
437
+ author_favorite = AuthorFavorite.all.merge!(:includes => :favorite_author).first
438
+ assert_equal authors(:mary), assert_no_queries { author_favorite.favorite_author }
439
+ end
440
+
441
+ def test_eager_load_belongs_to_quotes_table_and_column_names
442
+ job = Job.includes(:ideal_reference).find jobs(:unicyclist).id
443
+ references(:michael_unicyclist)
444
+ assert_no_queries{ assert_equal references(:michael_unicyclist), job.ideal_reference}
445
+ end
446
+
447
+ def test_eager_load_has_one_quotes_table_and_column_names
448
+ michael = Person.all.merge!(:includes => :favourite_reference).find(people(:michael).id)
449
+ references(:michael_unicyclist)
450
+ assert_no_queries{ assert_equal references(:michael_unicyclist), michael.favourite_reference}
451
+ end
452
+
453
+ def test_eager_load_has_many_quotes_table_and_column_names
454
+ michael = Person.all.merge!(:includes => :references).find(people(:michael).id)
455
+ references(:michael_magician,:michael_unicyclist)
456
+ assert_no_queries{ assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) }
457
+ end
458
+
459
+ def test_eager_load_has_many_through_quotes_table_and_column_names
460
+ michael = Person.all.merge!(:includes => :jobs).find(people(:michael).id)
461
+ jobs(:magician, :unicyclist)
462
+ assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
463
+ end
464
+
465
+ def test_eager_load_has_many_with_string_keys
466
+ subscriptions = subscriptions(:webster_awdr, :webster_rfr)
467
+ subscriber =Subscriber.all.merge!(:includes => :subscriptions).find(subscribers(:second).id)
468
+ assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
469
+ end
470
+
471
+ def test_string_id_column_joins
472
+ s = Subscriber.create! do |c|
473
+ c.id = "PL"
474
+ end
475
+
476
+ b = Book.create!
477
+
478
+ Subscription.create!(:subscriber_id => "PL", :book_id => b.id)
479
+ s.reload
480
+ s.book_ids = s.book_ids
481
+ end
482
+
483
+ def test_eager_load_has_many_through_with_string_keys
484
+ books = books(:awdr, :rfr)
485
+ subscriber = Subscriber.all.merge!(:includes => :books).find(subscribers(:second).id)
486
+ assert_equal books, subscriber.books.sort_by(&:id)
487
+ end
488
+
489
+ def test_eager_load_belongs_to_with_string_keys
490
+ subscriber = subscribers(:second)
491
+ subscription = Subscription.all.merge!(:includes => :subscriber).find(subscriptions(:webster_awdr).id)
492
+ assert_equal subscriber, subscription.subscriber
493
+ end
494
+
495
+ def test_eager_association_loading_with_explicit_join
496
+ posts = Post.all.merge!(:includes => :comments, :joins => "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", :limit => 1, :order => 'author_id').to_a
497
+ assert_equal 1, posts.length
498
+ end
499
+
500
+ def test_eager_with_has_many_through
501
+ posts_with_comments = people(:michael).posts.merge(:includes => :comments, :order => 'posts.id').to_a
502
+ posts_with_author = people(:michael).posts.merge(:includes => :author, :order => 'posts.id').to_a
503
+ posts_with_comments_and_author = people(:michael).posts.merge(:includes => [ :comments, :author ], :order => 'posts.id').to_a
504
+ assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum + post.comments.size }
505
+ assert_equal authors(:david), assert_no_queries { posts_with_author.first.author }
506
+ assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
507
+ end
508
+
509
+ def test_eager_with_has_many_through_a_belongs_to_association
510
+ author = authors(:mary)
511
+ Post.create!(:author => author, :title => "TITLE", :body => "BODY")
512
+ author.author_favorites.create(:favorite_author_id => 1)
513
+ author.author_favorites.create(:favorite_author_id => 2)
514
+ posts_with_author_favorites = author.posts.merge(:includes => :author_favorites).to_a
515
+ assert_no_queries { posts_with_author_favorites.first.author_favorites.first.author_id }
516
+ end
517
+
518
+ def test_eager_with_has_many_through_an_sti_join_model
519
+ author = Author.all.merge!(:includes => :special_post_comments, :order => 'authors.id').first
520
+ assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }
521
+ end
522
+
523
+ def test_eager_with_has_many_through_an_sti_join_model_with_conditions_on_both
524
+ author = Author.all.merge!(:includes => :special_nonexistent_post_comments, :order => 'authors.id').first
525
+ assert_equal [], author.special_nonexistent_post_comments
526
+ end
527
+
528
+ def test_eager_with_has_many_through_join_model_with_conditions
529
+ assert_equal Author.all.merge!(:includes => :hello_post_comments,
530
+ :order => 'authors.id').first.hello_post_comments.sort_by(&:id),
531
+ Author.all.merge!(:order => 'authors.id').first.hello_post_comments.sort_by(&:id)
532
+ end
533
+
534
+ def test_eager_with_has_many_through_join_model_with_conditions_on_top_level
535
+ assert_equal comments(:more_greetings), Author.all.merge!(:includes => :comments_with_order_and_conditions).find(authors(:david).id).comments_with_order_and_conditions.first
536
+ end
537
+
538
+ def test_eager_with_has_many_through_join_model_with_include
539
+ author_comments = Author.all.merge!(:includes => :comments_with_include).find(authors(:david).id).comments_with_include.to_a
540
+ assert_no_queries do
541
+ author_comments.first.post.title
542
+ end
543
+ end
544
+
545
+ def test_eager_with_has_many_through_with_conditions_join_model_with_include
546
+ post_tags = Post.find(posts(:welcome).id).misc_tags
547
+ eager_post_tags = Post.all.merge!(:includes => :misc_tags).find(1).misc_tags
548
+ assert_equal post_tags, eager_post_tags
549
+ end
550
+
551
+ def test_eager_with_has_many_through_join_model_ignores_default_includes
552
+ assert_nothing_raised do
553
+ authors(:david).comments_on_posts_with_default_include.to_a
554
+ end
555
+ end
556
+
557
+ def test_eager_with_has_many_and_limit
558
+ posts = Post.all.merge!(:order => 'posts.id asc', :includes => [ :author, :comments ], :limit => 2).to_a
559
+ assert_equal 2, posts.size
560
+ assert_equal 3, posts.inject(0) { |sum, post| sum + post.comments.size }
561
+ end
562
+
563
+ def test_eager_with_has_many_and_limit_and_conditions
564
+ posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => "posts.body = 'hello'", :order => "posts.id").to_a
565
+ assert_equal 2, posts.size
566
+ assert_equal [4,5], posts.collect(&:id)
567
+ end
568
+
569
+ def test_eager_with_has_many_and_limit_and_conditions_array
570
+ posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => [ "posts.body = ?", 'hello' ], :order => "posts.id").to_a
571
+ assert_equal 2, posts.size
572
+ assert_equal [4,5], posts.collect(&:id)
573
+ end
574
+
575
+ def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
576
+ posts = Post.includes(:author, :comments).limit(2).references(:author).where("authors.name = ?", 'David')
577
+ assert_equal 2, posts.size
578
+
579
+ count = Post.includes(:author, :comments).limit(2).references(:author).where("authors.name = ?", 'David').count
580
+ assert_equal posts.size, count
581
+ end
582
+
583
+ def test_eager_with_has_many_and_limit_and_high_offset
584
+ posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10, :where => { 'authors.name' => 'David' }).to_a
585
+ assert_equal 0, posts.size
586
+ end
587
+
588
+ def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
589
+ assert_queries(1) do
590
+ posts = Post.references(:authors, :comments).
591
+ merge(:includes => [ :author, :comments ], :limit => 2, :offset => 10,
592
+ :where => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ]).to_a
593
+ assert_equal 0, posts.size
594
+ end
595
+ end
596
+
597
+ def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
598
+ assert_queries(1) do
599
+ posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10,
600
+ :where => { 'authors.name' => 'David', 'comments.body' => 'go crazy' }).to_a
601
+ assert_equal 0, posts.size
602
+ end
603
+ end
604
+
605
+ def test_count_eager_with_has_many_and_limit_and_high_offset
606
+ posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :offset => 10, :where => { 'authors.name' => 'David' }).count(:all)
607
+ assert_equal 0, posts
608
+ end
609
+
610
+ def test_eager_with_has_many_and_limit_with_no_results
611
+ posts = Post.all.merge!(:includes => [ :author, :comments ], :limit => 2, :where => "posts.title = 'magic forest'").to_a
612
+ assert_equal 0, posts.size
613
+ end
614
+
615
+ def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
616
+ author = authors(:david)
617
+ author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
618
+ assert_equal author_posts_without_comments.size, author.posts.includes(:comments).where('comments.id is null').references(:comments).count
619
+ end
620
+
621
+ def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
622
+ person = people(:michael)
623
+ person_posts_without_comments = person.posts.select { |post| post.comments.blank? }
624
+ assert_equal person_posts_without_comments.size, person.posts_with_no_comments.count
625
+ end
626
+
627
+ def test_eager_with_has_and_belongs_to_many_and_limit
628
+ posts = Post.all.merge!(:includes => :categories, :order => "posts.id", :limit => 3).to_a
629
+ assert_equal 3, posts.size
630
+ assert_equal 2, posts[0].categories.size
631
+ assert_equal 1, posts[1].categories.size
632
+ assert_equal 0, posts[2].categories.size
633
+ assert posts[0].categories.include?(categories(:technology))
634
+ assert posts[1].categories.include?(categories(:general))
635
+ end
636
+
637
+ # Since the preloader for habtm gets raw row hashes from the database and then
638
+ # instantiates them, this test ensures that it only instantiates one actual
639
+ # object per record from the database.
640
+ def test_has_and_belongs_to_many_should_not_instantiate_same_records_multiple_times
641
+ welcome = posts(:welcome)
642
+ categories = Category.includes(:posts)
643
+
644
+ general = categories.find { |c| c == categories(:general) }
645
+ technology = categories.find { |c| c == categories(:technology) }
646
+
647
+ post1 = general.posts.to_a.find { |p| p == welcome }
648
+ post2 = technology.posts.to_a.find { |p| p == welcome }
649
+
650
+ assert_equal post1.object_id, post2.object_id
651
+ end
652
+
653
+ def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
654
+ posts =
655
+ authors(:david).posts
656
+ .includes(:comments)
657
+ .where("comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'")
658
+ .references(:comments)
659
+ .limit(2)
660
+ .to_a
661
+ assert_equal 2, posts.size
662
+
663
+ count =
664
+ Post.includes(:comments, :author)
665
+ .where("authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')")
666
+ .references(:authors, :comments)
667
+ .limit(2)
668
+ .count
669
+ assert_equal count, posts.size
670
+ end
671
+
672
+ def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
673
+ posts = nil
674
+ Post.includes(:comments)
675
+ .where("comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'")
676
+ .references(:comments)
677
+ .scoping do
678
+
679
+ posts = authors(:david).posts.limit(2).to_a
680
+ assert_equal 2, posts.size
681
+ end
682
+
683
+ Post.includes(:comments, :author)
684
+ .where("authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')")
685
+ .references(:authors, :comments)
686
+ .scoping do
687
+
688
+ count = Post.limit(2).count
689
+ assert_equal count, posts.size
690
+ end
691
+ end
692
+
693
+ def test_eager_association_loading_with_habtm
694
+ posts = Post.all.merge!(:includes => :categories, :order => "posts.id").to_a
695
+ assert_equal 2, posts[0].categories.size
696
+ assert_equal 1, posts[1].categories.size
697
+ assert_equal 0, posts[2].categories.size
698
+ assert posts[0].categories.include?(categories(:technology))
699
+ assert posts[1].categories.include?(categories(:general))
700
+ end
701
+
702
+ def test_eager_with_inheritance
703
+ SpecialPost.all.merge!(:includes => [ :comments ]).to_a
704
+ end
705
+
706
+ def test_eager_has_one_with_association_inheritance
707
+ post = Post.all.merge!(:includes => [ :very_special_comment ]).find(4)
708
+ assert_equal "VerySpecialComment", post.very_special_comment.class.to_s
709
+ end
710
+
711
+ def test_eager_has_many_with_association_inheritance
712
+ post = Post.all.merge!(:includes => [ :special_comments ]).find(4)
713
+ post.special_comments.each do |special_comment|
714
+ assert special_comment.is_a?(SpecialComment)
715
+ end
716
+ end
717
+
718
+ def test_eager_habtm_with_association_inheritance
719
+ post = Post.all.merge!(:includes => [ :special_categories ]).find(6)
720
+ assert_equal 1, post.special_categories.size
721
+ post.special_categories.each do |special_category|
722
+ assert_equal "SpecialCategory", special_category.class.to_s
723
+ end
724
+ end
725
+
726
+ def test_eager_with_has_one_dependent_does_not_destroy_dependent
727
+ assert_not_nil companies(:first_firm).account
728
+ f = Firm.all.merge!(:includes => :account,
729
+ :where => ["companies.name = ?", "37signals"]).first
730
+ assert_not_nil f.account
731
+ assert_equal companies(:first_firm, :reload).account, f.account
732
+ end
733
+
734
+ def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size
735
+ author = authors(:david)
736
+ posts_with_no_comments = author.posts.select { |post| post.comments.blank? }
737
+ assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size
738
+ assert_equal posts_with_no_comments, author.posts_with_no_comments
739
+ end
740
+
741
+ def test_eager_with_invalid_association_reference
742
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
743
+ Post.all.merge!(:includes=> :monkeys ).find(6)
744
+ }
745
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
746
+ Post.all.merge!(:includes=>[ :monkeys ]).find(6)
747
+ }
748
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
749
+ Post.all.merge!(:includes=>[ 'monkeys' ]).find(6)
750
+ }
751
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
752
+ Post.all.merge!(:includes=>[ :monkeys, :elephants ]).find(6)
753
+ }
754
+ end
755
+
756
+ def test_eager_has_many_through_with_order
757
+ tag = OrderedTag.create(name: 'Foo')
758
+ post1 = Post.create!(title: 'Beaches', body: "I like beaches!")
759
+ post2 = Post.create!(title: 'Pools', body: "I like pools!")
760
+
761
+ Tagging.create!(taggable_type: 'Post', taggable_id: post1.id, tag: tag)
762
+ Tagging.create!(taggable_type: 'Post', taggable_id: post2.id, tag: tag)
763
+
764
+ tag_with_includes = OrderedTag.includes(:tagged_posts).find(tag.id)
765
+ assert_equal(tag_with_includes.taggings.map(&:taggable).map(&:title), tag_with_includes.tagged_posts.map(&:title))
766
+ end
767
+
768
+ def test_eager_has_many_through_multiple_with_order
769
+ tag1 = OrderedTag.create!(name: 'Bar')
770
+ tag2 = OrderedTag.create!(name: 'Foo')
771
+
772
+ post1 = Post.create!(title: 'Beaches', body: "I like beaches!")
773
+ post2 = Post.create!(title: 'Pools', body: "I like pools!")
774
+
775
+ Tagging.create!(taggable: post1, tag: tag1)
776
+ Tagging.create!(taggable: post2, tag: tag1)
777
+ Tagging.create!(taggable: post2, tag: tag2)
778
+ Tagging.create!(taggable: post1, tag: tag2)
779
+
780
+ tags_with_includes = OrderedTag.where(id: [tag1, tag2].map(&:id)).includes(:tagged_posts).order(:id).to_a
781
+ tag1_with_includes = tags_with_includes.first
782
+ tag2_with_includes = tags_with_includes.last
783
+
784
+ assert_equal([post2, post1].map(&:title), tag1_with_includes.tagged_posts.map(&:title))
785
+ assert_equal([post1, post2].map(&:title), tag2_with_includes.tagged_posts.map(&:title))
786
+ end
787
+
788
+ def test_eager_with_default_scope
789
+ developer = EagerDeveloperWithDefaultScope.where(:name => 'David').first
790
+ projects = Project.order(:id).to_a
791
+ assert_no_queries do
792
+ assert_equal(projects, developer.projects)
793
+ end
794
+ end
795
+
796
+ def test_eager_with_default_scope_as_class_method
797
+ developer = EagerDeveloperWithClassMethodDefaultScope.where(:name => 'David').first
798
+ projects = Project.order(:id).to_a
799
+ assert_no_queries do
800
+ assert_equal(projects, developer.projects)
801
+ end
802
+ end
803
+
804
+ def test_eager_with_default_scope_as_class_method_using_find_method
805
+ david = developers(:david)
806
+ developer = EagerDeveloperWithClassMethodDefaultScope.find(david.id)
807
+ projects = Project.order(:id).to_a
808
+ assert_no_queries do
809
+ assert_equal(projects, developer.projects)
810
+ end
811
+ end
812
+
813
+ def test_eager_with_default_scope_as_class_method_using_find_by_method
814
+ developer = EagerDeveloperWithClassMethodDefaultScope.find_by(name: 'David')
815
+ projects = Project.order(:id).to_a
816
+ assert_no_queries do
817
+ assert_equal(projects, developer.projects)
818
+ end
819
+ end
820
+
821
+ def test_eager_with_default_scope_as_lambda
822
+ developer = EagerDeveloperWithLambdaDefaultScope.where(:name => 'David').first
823
+ projects = Project.order(:id).to_a
824
+ assert_no_queries do
825
+ assert_equal(projects, developer.projects)
826
+ end
827
+ end
828
+
829
+ def test_eager_with_default_scope_as_block
830
+ # warm up the habtm cache
831
+ EagerDeveloperWithBlockDefaultScope.where(:name => 'David').first.projects
832
+ developer = EagerDeveloperWithBlockDefaultScope.where(:name => 'David').first
833
+ projects = Project.order(:id).to_a
834
+ assert_no_queries do
835
+ assert_equal(projects, developer.projects)
836
+ end
837
+ end
838
+
839
+ def test_eager_with_default_scope_as_callable
840
+ developer = EagerDeveloperWithCallableDefaultScope.where(:name => 'David').first
841
+ projects = Project.order(:id).to_a
842
+ assert_no_queries do
843
+ assert_equal(projects, developer.projects)
844
+ end
845
+ end
846
+
847
+ def find_all_ordered(className, include=nil)
848
+ className.all.merge!(:order=>"#{className.table_name}.#{className.primary_key}", :includes=>include).to_a
849
+ end
850
+
851
+ def test_limited_eager_with_order
852
+ unless current_adapter?(:IBM_DBAdapter)
853
+ assert_equal(
854
+ posts(:thinking, :sti_comments),
855
+ Post.all.merge!(
856
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
857
+ :order => 'UPPER(posts.title)', :limit => 2, :offset => 1
858
+ ).to_a
859
+ )
860
+ assert_equal(
861
+ posts(:sti_post_and_comments, :sti_comments),
862
+ Post.all.merge!(
863
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
864
+ :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1
865
+ ).to_a
866
+ )
867
+ else
868
+ assert_equal(
869
+ posts(:thinking, :sti_comments),
870
+ Post.all.merge!(
871
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
872
+ :order => 'posts.id', :limit => 2, :offset => 1
873
+ ).to_a
874
+ )
875
+ assert_equal(
876
+ posts(:sti_post_and_comments, :sti_comments),
877
+ Post.all.merge!(
878
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
879
+ :order => 'posts.id DESC', :limit => 2, :offset => 1
880
+ ).to_a
881
+ )
882
+ end
883
+ end
884
+
885
+ def test_limited_eager_with_multiple_order_columns
886
+ unless current_adapter?(:IBM_DBAdapter)
887
+ assert_equal(
888
+ posts(:thinking, :sti_comments),
889
+ Post.all.merge!(
890
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
891
+ :order => ['UPPER(posts.title)', 'posts.id'], :limit => 2, :offset => 1
892
+ ).to_a
893
+ )
894
+ assert_equal(
895
+ posts(:sti_post_and_comments, :sti_comments),
896
+ Post.all.merge!(
897
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
898
+ :order => ['UPPER(posts.title) DESC', 'posts.id'], :limit => 2, :offset => 1
899
+ ).to_a
900
+ )
901
+ else
902
+ assert_equal(
903
+ posts(:thinking, :sti_comments),
904
+ Post.all.merge!(
905
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
906
+ :order => ['posts.id'], :limit => 2, :offset => 1
907
+ ).to_a
908
+ )
909
+ assert_equal(
910
+ posts(:sti_post_and_comments, :sti_comments),
911
+ Post.all.merge!(
912
+ :includes => [:author, :comments], :where => { 'authors.name' => 'David' },
913
+ :order => ['posts.id DESC'], :limit => 2, :offset => 1
914
+ ).to_a
915
+ )
916
+ end
917
+ end
918
+
919
+ def test_limited_eager_with_numeric_in_association
920
+ assert_equal(
921
+ people(:david, :susan),
922
+ Person.references(:number1_fans_people).merge(
923
+ :includes => [:readers, :primary_contact, :number1_fan],
924
+ :where => "number1_fans_people.first_name like 'M%'",
925
+ :order => 'people.id', :limit => 2, :offset => 0
926
+ ).to_a
927
+ )
928
+ end
929
+
930
+ def test_polymorphic_type_condition
931
+ post = Post.all.merge!(:includes => :taggings).find(posts(:thinking).id)
932
+ assert post.taggings.include?(taggings(:thinking_general))
933
+ post = SpecialPost.all.merge!(:includes => :taggings).find(posts(:thinking).id)
934
+ assert post.taggings.include?(taggings(:thinking_general))
935
+ end
936
+
937
+ def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm
938
+ # Eager includes of has many and habtm associations aren't necessarily sorted in the same way
939
+ def assert_equal_after_sort(item1, item2, item3 = nil)
940
+ assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id})
941
+ assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3
942
+ end
943
+ # Test regular association, association with conditions, association with
944
+ # STI, and association with conditions assured not to be true
945
+ post_types = [:posts, :other_posts, :special_posts]
946
+ # test both has_many and has_and_belongs_to_many
947
+ [Author, Category].each do |className|
948
+ d1 = find_all_ordered(className)
949
+ # test including all post types at once
950
+ d2 = find_all_ordered(className, post_types)
951
+ d1.each_index do |i|
952
+ assert_equal(d1[i], d2[i])
953
+ assert_equal_after_sort(d1[i].posts, d2[i].posts)
954
+ post_types[1..-1].each do |post_type|
955
+ # test including post_types together
956
+ d3 = find_all_ordered(className, [:posts, post_type])
957
+ assert_equal(d1[i], d3[i])
958
+ assert_equal_after_sort(d1[i].posts, d3[i].posts)
959
+ assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type))
960
+ end
961
+ end
962
+ end
963
+ end
964
+
965
+ def test_eager_with_multiple_associations_with_same_table_has_one
966
+ d1 = find_all_ordered(Firm)
967
+ d2 = find_all_ordered(Firm, :account)
968
+ d1.each_index do |i|
969
+ assert_equal(d1[i], d2[i])
970
+ assert_equal(d1[i].account, d2[i].account)
971
+ end
972
+ end
973
+
974
+ def test_eager_with_multiple_associations_with_same_table_belongs_to
975
+ firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition]
976
+ d1 = find_all_ordered(Client)
977
+ d2 = find_all_ordered(Client, firm_types)
978
+ d1.each_index do |i|
979
+ assert_equal(d1[i], d2[i])
980
+ firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) }
981
+ end
982
+ end
983
+ def test_eager_with_valid_association_as_string_not_symbol
984
+ assert_nothing_raised { Post.all.merge!(:includes => 'comments').to_a }
985
+ end
986
+
987
+ def test_eager_with_floating_point_numbers
988
+ assert_queries(2) do
989
+ # Before changes, the floating point numbers will be interpreted as table names and will cause this to run in one query
990
+ Comment.all.merge!(:where => "123.456 = 123.456", :includes => :post).to_a
991
+ end
992
+ end
993
+
994
+ def test_preconfigured_includes_with_belongs_to
995
+ author = posts(:welcome).author_with_posts
996
+ assert_no_queries {assert_equal 5, author.posts.size}
997
+ end
998
+
999
+ def test_preconfigured_includes_with_has_one
1000
+ comment = posts(:sti_comments).very_special_comment_with_post
1001
+ assert_no_queries {assert_equal posts(:sti_comments), comment.post}
1002
+ end
1003
+
1004
+ def test_eager_association_with_scope_with_joins
1005
+ assert_nothing_raised do
1006
+ Post.includes(:very_special_comment_with_post_with_joins).to_a
1007
+ end
1008
+ end
1009
+
1010
+ def test_preconfigured_includes_with_has_many
1011
+ posts = authors(:david).posts_with_comments
1012
+ one = posts.detect { |p| p.id == 1 }
1013
+ assert_no_queries do
1014
+ assert_equal 5, posts.size
1015
+ assert_equal 2, one.comments.size
1016
+ end
1017
+ end
1018
+
1019
+ def test_preconfigured_includes_with_habtm
1020
+ posts = authors(:david).posts_with_categories
1021
+ one = posts.detect { |p| p.id == 1 }
1022
+ assert_no_queries do
1023
+ assert_equal 5, posts.size
1024
+ assert_equal 2, one.categories.size
1025
+ end
1026
+ end
1027
+
1028
+ def test_preconfigured_includes_with_has_many_and_habtm
1029
+ posts = authors(:david).posts_with_comments_and_categories
1030
+ one = posts.detect { |p| p.id == 1 }
1031
+ assert_no_queries do
1032
+ assert_equal 5, posts.size
1033
+ assert_equal 2, one.comments.size
1034
+ assert_equal 2, one.categories.size
1035
+ end
1036
+ end
1037
+
1038
+ def test_count_with_include
1039
+ assert_equal 3, authors(:david).posts_with_comments.where("length(comments.body) > 15").references(:comments).count
1040
+ end
1041
+
1042
+ def test_association_loading_notification
1043
+ notifications = messages_for('instantiation.active_record') do
1044
+ Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1045
+ end
1046
+
1047
+ message = notifications.first
1048
+ payload = message.last
1049
+ count = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1050
+
1051
+ # eagerloaded row count should be greater than just developer count
1052
+ assert_operator payload[:record_count], :>, count
1053
+ assert_equal Developer.name, payload[:class_name]
1054
+ end
1055
+
1056
+ def test_base_messages
1057
+ notifications = messages_for('instantiation.active_record') do
1058
+ Developer.all.to_a
1059
+ end
1060
+ message = notifications.first
1061
+ payload = message.last
1062
+
1063
+ assert_equal Developer.all.to_a.count, payload[:record_count]
1064
+ assert_equal Developer.name, payload[:class_name]
1065
+ end
1066
+
1067
+ def messages_for(name)
1068
+ notifications = []
1069
+ ActiveSupport::Notifications.subscribe(name) do |*args|
1070
+ notifications << args
1071
+ end
1072
+ yield
1073
+ notifications
1074
+ ensure
1075
+ ActiveSupport::Notifications.unsubscribe(name)
1076
+ end
1077
+
1078
+ def test_load_with_sti_sharing_association
1079
+ assert_queries(2) do #should not do 1 query per subclass
1080
+ Comment.includes(:post).to_a
1081
+ end
1082
+ end
1083
+
1084
+ def test_conditions_on_join_table_with_include_and_limit
1085
+ assert_equal 3, Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
1086
+ end
1087
+
1088
+ def test_dont_create_temporary_active_record_instances
1089
+ Developer.instance_count = 0
1090
+ developers = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a
1091
+ assert_equal developers.count, Developer.instance_count
1092
+ end
1093
+
1094
+ def test_order_on_join_table_with_include_and_limit
1095
+ assert_equal 5, Developer.all.merge!(:includes => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).to_a.size
1096
+ end
1097
+
1098
+ def test_eager_loading_with_order_on_joined_table_preloads
1099
+ posts = assert_queries(2) do
1100
+ Post.all.merge!(:joins => :comments, :includes => :author, :order => 'comments.id DESC').to_a
1101
+ end
1102
+ assert_equal posts(:eager_other), posts[1]
1103
+ assert_equal authors(:mary), assert_no_queries { posts[1].author}
1104
+ end
1105
+
1106
+ def test_eager_loading_with_conditions_on_joined_table_preloads
1107
+ posts = assert_queries(2) do
1108
+ Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => [:comments], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1109
+ end
1110
+ assert_equal [posts(:welcome)], posts
1111
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
1112
+
1113
+ posts = assert_queries(2) do
1114
+ Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => [:comments], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1115
+ end
1116
+ assert_equal [posts(:welcome)], posts
1117
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
1118
+
1119
+ posts = assert_queries(2) do
1120
+ Post.all.merge!(:includes => :author, :joins => {:taggings => :tag}, :where => "tags.name = 'General'", :order => 'posts.id').to_a
1121
+ end
1122
+ assert_equal posts(:welcome, :thinking), posts
1123
+
1124
+ posts = assert_queries(2) do
1125
+ Post.all.merge!(:includes => :author, :joins => {:taggings => {:tag => :taggings}}, :where => "taggings_tags.super_tag_id=2", :order => 'posts.id').to_a
1126
+ end
1127
+ assert_equal posts(:welcome, :thinking), posts
1128
+ end
1129
+
1130
+ def test_preload_has_many_with_association_condition_and_default_scope
1131
+ post = Post.create!(:title => 'Beaches', :body => "I like beaches!")
1132
+ Reader.create! :person => people(:david), :post => post
1133
+ LazyReader.create! :person => people(:susan), :post => post
1134
+
1135
+ assert_equal 1, post.lazy_readers.to_a.size
1136
+ assert_equal 2, post.lazy_readers_skimmers_or_not.to_a.size
1137
+
1138
+ post_with_readers = Post.includes(:lazy_readers_skimmers_or_not).find(post.id)
1139
+ assert_equal 2, post_with_readers.lazy_readers_skimmers_or_not.to_a.size
1140
+ end
1141
+
1142
+ def test_eager_loading_with_conditions_on_string_joined_table_preloads
1143
+ posts = assert_queries(2) do
1144
+ Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1145
+ end
1146
+ assert_equal [posts(:welcome)], posts
1147
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
1148
+
1149
+ posts = assert_queries(2) do
1150
+ Post.all.merge!(:select => 'distinct posts.*', :includes => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :where => "comments.body like 'Thank you%'", :order => 'posts.id').to_a
1151
+ end
1152
+ assert_equal [posts(:welcome)], posts
1153
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
1154
+ end
1155
+
1156
+ def test_eager_loading_with_select_on_joined_table_preloads
1157
+ posts = assert_queries(2) do
1158
+ Post.all.merge!(:select => 'posts.*, authors.name as author_name', :includes => :comments, :joins => :author, :order => 'posts.id').to_a
1159
+ end
1160
+ assert_equal 'David', posts[0].author_name
1161
+ assert_equal posts(:welcome).comments, assert_no_queries { posts[0].comments}
1162
+ end
1163
+
1164
+ def test_eager_loading_with_conditions_on_join_model_preloads
1165
+ authors = assert_queries(2) do
1166
+ Author.all.merge!(:includes => :author_address, :joins => :comments, :where => "posts.title like 'Welcome%'").to_a
1167
+ end
1168
+ assert_equal authors(:david), authors[0]
1169
+ assert_equal author_addresses(:david_address), authors[0].author_address
1170
+ end
1171
+
1172
+ def test_preload_belongs_to_uses_exclusive_scope
1173
+ people = Person.males.merge(:includes => :primary_contact).to_a
1174
+ assert_not_equal people.length, 0
1175
+ people.each do |person|
1176
+ assert_no_queries {assert_not_nil person.primary_contact}
1177
+ assert_equal Person.find(person.id).primary_contact, person.primary_contact
1178
+ end
1179
+ end
1180
+
1181
+ def test_preload_has_many_uses_exclusive_scope
1182
+ people = Person.males.includes(:agents).to_a
1183
+ people.each do |person|
1184
+ assert_equal Person.find(person.id).agents, person.agents
1185
+ end
1186
+ end
1187
+
1188
+ def test_preload_has_many_using_primary_key
1189
+ expected = Firm.first.clients_using_primary_key.to_a
1190
+ firm = Firm.includes(:clients_using_primary_key).first
1191
+ assert_no_queries do
1192
+ assert_equal expected, firm.clients_using_primary_key
1193
+ end
1194
+ end
1195
+
1196
+ def test_include_has_many_using_primary_key
1197
+ expected = Firm.find(1).clients_using_primary_key.sort_by(&:name)
1198
+ # Oracle adapter truncates alias to 30 characters
1199
+ if current_adapter?(:OracleAdapter)
1200
+ firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies'[0,30]+'.name').find(1)
1201
+ elsif current_adapter?(:IBM_DBAdapter)
1202
+ #firm = Firm.all.merge!(:includes => :clients_using_primary_key).find(1)
1203
+ firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name').find(1)
1204
+ else
1205
+ firm = Firm.all.merge!(:includes => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name').find(1)
1206
+ end
1207
+ assert_no_queries do
1208
+ assert_equal expected, firm.clients_using_primary_key
1209
+ end
1210
+ end
1211
+
1212
+ def test_preload_has_one_using_primary_key
1213
+ expected = accounts(:signals37)
1214
+ firm = Firm.all.merge!(:includes => :account_using_primary_key, :order => 'companies.id').first
1215
+ assert_no_queries do
1216
+ assert_equal expected, firm.account_using_primary_key
1217
+ end
1218
+ end
1219
+
1220
+ def test_include_has_one_using_primary_key
1221
+ expected = accounts(:signals37)
1222
+ firm = Firm.all.merge!(:includes => :account_using_primary_key, :order => 'accounts.id').to_a.detect {|f| f.id == 1}
1223
+ assert_no_queries do
1224
+ assert_equal expected, firm.account_using_primary_key
1225
+ end
1226
+ end
1227
+
1228
+ def test_preloading_empty_belongs_to
1229
+ c = Client.create!(:name => 'Foo', :client_of => Company.maximum(:id) + 1)
1230
+
1231
+ client = assert_queries(2) { Client.preload(:firm).find(c.id) }
1232
+ assert_no_queries { assert_nil client.firm }
1233
+ end
1234
+
1235
+ def test_preloading_empty_belongs_to_polymorphic
1236
+ t = Tagging.create!(:taggable_type => 'Post', :taggable_id => Post.maximum(:id) + 1, :tag => tags(:general))
1237
+
1238
+ tagging = assert_queries(2) { Tagging.preload(:taggable).find(t.id) }
1239
+ assert_no_queries { assert_nil tagging.taggable }
1240
+ end
1241
+
1242
+ def test_preloading_through_empty_belongs_to
1243
+ c = Client.create!(:name => 'Foo', :client_of => Company.maximum(:id) + 1)
1244
+
1245
+ client = assert_queries(2) { Client.preload(:accounts).find(c.id) }
1246
+ assert_no_queries { assert client.accounts.empty? }
1247
+ end
1248
+
1249
+ def test_preloading_has_many_through_with_distinct
1250
+ mary = Author.includes(:unique_categorized_posts).where(:id => authors(:mary).id).first
1251
+ assert_equal 1, mary.unique_categorized_posts.length
1252
+ assert_equal 1, mary.unique_categorized_post_ids.length
1253
+ end
1254
+
1255
+ def test_preloading_has_one_using_reorder
1256
+ klass = Class.new(ActiveRecord::Base) do
1257
+ def self.name; "TempAuthor"; end
1258
+ self.table_name = "authors"
1259
+ has_one :post, class_name: "PostWithDefaultScope", foreign_key: :author_id
1260
+ has_one :reorderd_post, -> { reorder(title: :desc) }, class_name: "PostWithDefaultScope", foreign_key: :author_id
1261
+ end
1262
+
1263
+ author = klass.first
1264
+ # PRECONDITION: make sure ordering results in different results
1265
+ assert_not_equal author.post, author.reorderd_post
1266
+
1267
+ preloaded_reorderd_post = klass.preload(:reorderd_post).first.reorderd_post
1268
+
1269
+ assert_equal author.reorderd_post, preloaded_reorderd_post
1270
+ assert_equal Post.order(title: :desc).first.title, preloaded_reorderd_post.title
1271
+ end
1272
+
1273
+ def test_preloading_polymorphic_with_custom_foreign_type
1274
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
1275
+ groucho = members(:groucho)
1276
+
1277
+ sponsor = assert_queries(2) {
1278
+ Sponsor.includes(:thing).where(:id => sponsor.id).first
1279
+ }
1280
+ assert_no_queries { assert_equal groucho, sponsor.thing }
1281
+ end
1282
+
1283
+ def test_joins_with_includes_should_preload_via_joins
1284
+ post = assert_queries(1) { Post.includes(:comments).joins(:comments).order('posts.id desc').to_a.first }
1285
+
1286
+ assert_queries(0) do
1287
+ assert_not_equal 0, post.comments.to_a.count
1288
+ end
1289
+ end
1290
+
1291
+ def test_join_eager_with_empty_order_should_generate_valid_sql
1292
+ assert_nothing_raised do
1293
+ Post.includes(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
1294
+ end
1295
+ end
1296
+
1297
+ def test_deep_including_through_habtm
1298
+ # warm up habtm cache
1299
+ posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1300
+ posts[0].categories[0].categorizations.length
1301
+
1302
+ posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1303
+ assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.length }
1304
+ assert_no_queries { assert_equal 1, posts[0].categories[1].categorizations.length }
1305
+ assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.length }
1306
+ end
1307
+
1308
+ def test_eager_load_multiple_associations_with_references
1309
+ mentor = Mentor.create!(name: "Barış Can DAYLIK")
1310
+ developer = Developer.create!(name: "Mehmet Emin İNAÇ", mentor: mentor)
1311
+ Contract.create!(developer: developer)
1312
+ project = Project.create!(name: "VNGRS", mentor: mentor)
1313
+ project.developers << developer
1314
+ projects = Project.references(:mentors).includes(mentor: { developers: :contracts }, developers: :contracts)
1315
+ assert_equal projects.last.mentor.developers.first.contracts, projects.last.developers.last.contracts
1316
+ end
1317
+
1318
+ test "scoping with a circular preload" do
1319
+ assert_equal Comment.find(1), Comment.preload(:post => :comments).scoping { Comment.find(1) }
1320
+ end
1321
+
1322
+ test "circular preload does not modify unscoped" do
1323
+ expected = FirstPost.unscoped.find(2)
1324
+ FirstPost.preload(:comments => :first_post).find(1)
1325
+ assert_equal expected, FirstPost.unscoped.find(2)
1326
+ end
1327
+
1328
+ test "preload ignores the scoping" do
1329
+ assert_equal(
1330
+ Comment.find(1).post,
1331
+ Post.where('1 = 0').scoping { Comment.preload(:post).find(1).post }
1332
+ )
1333
+ end
1334
+
1335
+ test "deep preload" do
1336
+ post = Post.preload(author: :posts, comments: :post).first
1337
+
1338
+ assert_predicate post.author.association(:posts), :loaded?
1339
+ assert_predicate post.comments.first.association(:post), :loaded?
1340
+ end
1341
+
1342
+ test "preloading does not cache has many association subset when preloaded with a through association" do
1343
+ author = Author.includes(:comments_with_order_and_conditions, :posts).first
1344
+ assert_no_queries { assert_equal 2, author.comments_with_order_and_conditions.size }
1345
+ assert_no_queries { assert_equal 5, author.posts.size, "should not cache a subset of the association" }
1346
+ end
1347
+
1348
+ test "preloading a through association twice does not reset it" do
1349
+ members = Member.includes(current_membership: :club).includes(:club).to_a
1350
+ assert_no_queries {
1351
+ assert_equal 3, members.map(&:current_membership).map(&:club).size
1352
+ }
1353
+ end
1354
+
1355
+ test "works in combination with order(:symbol) and reorder(:symbol)" do
1356
+ author = Author.includes(:posts).references(:posts).order(:name).find_by('posts.title IS NOT NULL')
1357
+ assert_equal authors(:bob), author
1358
+
1359
+ author = Author.includes(:posts).references(:posts).reorder(:name).find_by('posts.title IS NOT NULL')
1360
+ assert_equal authors(:bob), author
1361
+ end
1362
+
1363
+ test "preloading with a polymorphic association and using the existential predicate but also using a select" do
1364
+ assert_equal authors(:david), authors(:david).essays.includes(:writer).first.writer
1365
+
1366
+ assert_nothing_raised do
1367
+ authors(:david).essays.includes(:writer).select(:name).any?
1368
+ end
1369
+ end
1370
+
1371
+ test "preloading the same association twice works" do
1372
+ Member.create!
1373
+ members = Member.preload(:current_membership).includes(current_membership: :club).all.to_a
1374
+ assert_no_queries {
1375
+ members_with_membership = members.select(&:current_membership)
1376
+ assert_equal 3, members_with_membership.map(&:current_membership).map(&:club).size
1377
+ }
1378
+ end
1379
+
1380
+ test "preloading with a polymorphic association and using the existential predicate" do
1381
+ assert_equal authors(:david), authors(:david).essays.includes(:writer).first.writer
1382
+
1383
+ assert_nothing_raised do
1384
+ authors(:david).essays.includes(:writer).any?
1385
+ end
1386
+ end
1387
+
1388
+ test "preloading associations with string joins and order references" do
1389
+ author = assert_queries(2) {
1390
+ Author.includes(:posts).joins("LEFT JOIN posts ON posts.author_id = authors.id").order("posts.title DESC").first
1391
+ }
1392
+ assert_no_queries {
1393
+ assert_equal 5, author.posts.size
1394
+ }
1395
+ end
1396
+
1397
+ test "including associations with where.not adds implicit references" do
1398
+ author = assert_queries(2) {
1399
+ Author.includes(:posts).where.not(posts: { title: 'Welcome to the weblog'} ).last
1400
+ }
1401
+
1402
+ assert_no_queries {
1403
+ assert_equal 2, author.posts.size
1404
+ }
1405
+ end
1406
+
1407
+ test "including association based on sql condition and no database column" do
1408
+ assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet
1409
+ end
1410
+
1411
+ test "preloading and eager loading of instance dependent associations is not supported" do
1412
+ message = "association scope 'posts_with_signature' is"
1413
+ error = assert_raises(ArgumentError) do
1414
+ Author.includes(:posts_with_signature).to_a
1415
+ end
1416
+ assert_match message, error.message
1417
+
1418
+ error = assert_raises(ArgumentError) do
1419
+ Author.preload(:posts_with_signature).to_a
1420
+ end
1421
+ assert_match message, error.message
1422
+
1423
+ error = assert_raises(ArgumentError) do
1424
+ Author.eager_load(:posts_with_signature).to_a
1425
+ end
1426
+ assert_match message, error.message
1427
+ end
1428
+
1429
+ test "preload with invalid argument" do
1430
+ exception = assert_raises(ArgumentError) do
1431
+ Author.preload(10).to_a
1432
+ end
1433
+ assert_equal('10 was not recognized for preload', exception.message)
1434
+ end
1435
+
1436
+ test "associations with extensions are not instance dependent" do
1437
+ assert_nothing_raised do
1438
+ Author.includes(:posts_with_extension).to_a
1439
+ end
1440
+ end
1441
+
1442
+ test "including associations with extensions and an instance dependent scope is not supported" do
1443
+ e = assert_raises(ArgumentError) do
1444
+ Author.includes(:posts_with_extension_and_instance).to_a
1445
+ end
1446
+ assert_match(/Preloading instance dependent scopes is not supported/, e.message)
1447
+ end
1448
+
1449
+ test "preloading readonly association" do
1450
+ # has-one
1451
+ firm = Firm.where(id: "1").preload(:readonly_account).first!
1452
+ assert firm.readonly_account.readonly?
1453
+
1454
+ # has_and_belongs_to_many
1455
+ project = Project.where(id: "2").preload(:readonly_developers).first!
1456
+ assert project.readonly_developers.first.readonly?
1457
+
1458
+ # has-many :through
1459
+ david = Author.where(id: "1").preload(:readonly_comments).first!
1460
+ assert david.readonly_comments.first.readonly?
1461
+ end
1462
+
1463
+ test "eager-loading non-readonly association" do
1464
+ # has_one
1465
+ firm = Firm.where(id: "1").eager_load(:account).first!
1466
+ assert_not firm.account.readonly?
1467
+
1468
+ # has_and_belongs_to_many
1469
+ project = Project.where(id: "2").eager_load(:developers).first!
1470
+ assert_not project.developers.first.readonly?
1471
+
1472
+ # has_many :through
1473
+ david = Author.where(id: "1").eager_load(:comments).first!
1474
+ assert_not david.comments.first.readonly?
1475
+
1476
+ # belongs_to
1477
+ post = Post.where(id: "1").eager_load(:author).first!
1478
+ assert_not post.author.readonly?
1479
+ end
1480
+
1481
+ test "eager-loading readonly association" do
1482
+ # has-one
1483
+ firm = Firm.where(id: "1").eager_load(:readonly_account).first!
1484
+ assert firm.readonly_account.readonly?
1485
+
1486
+ # has_and_belongs_to_many
1487
+ project = Project.where(id: "2").eager_load(:readonly_developers).first!
1488
+ assert project.readonly_developers.first.readonly?
1489
+
1490
+ # has-many :through
1491
+ david = Author.where(id: "1").eager_load(:readonly_comments).first!
1492
+ assert david.readonly_comments.first.readonly?
1493
+
1494
+ # belongs_to
1495
+ post = Post.where(id: "1").eager_load(:readonly_author).first!
1496
+ assert post.readonly_author.readonly?
1497
+ end
1498
+
1499
+ test "preloading a polymorphic association with references to the associated table" do
1500
+ post = Post.includes(:tags).references(:tags).where('tags.name = ?', 'General').first
1501
+ assert_equal posts(:welcome), post
1502
+ end
1503
+
1504
+ test "eager-loading a polymorphic association with references to the associated table" do
1505
+ post = Post.eager_load(:tags).where('tags.name = ?', 'General').first
1506
+ assert_equal posts(:welcome), post
1507
+ end
1508
+
1509
+ # CollectionProxy#reader is expensive, so the preloader avoids calling it.
1510
+ test "preloading has_many_through association avoids calling association.reader" do
1511
+ ActiveRecord::Associations::HasManyAssociation.any_instance.expects(:reader).never
1512
+ Author.preload(:readonly_comments).first!
1513
+ end
1514
+ end