ibm_db 3.0.4-x86-mingw32 → 3.0.5-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -1
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/README +225 -225
  6. data/ext/Makefile.nt32 +181 -181
  7. data/ext/Makefile.nt32.191 +212 -212
  8. data/ext/extconf.rb +291 -291
  9. data/ext/ibm_db.c +11887 -11884
  10. data/ext/ruby_ibm_db.h +241 -241
  11. data/ext/ruby_ibm_db_cli.c +866 -866
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3177 -3177
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +122 -122
  19. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  20. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  21. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +46 -46
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +276 -261
  26. data/test/cases/aggregations_test.rb +158 -158
  27. data/test/cases/ar_schema_test.rb +161 -161
  28. data/test/cases/associations/association_scope_test.rb +21 -21
  29. data/test/cases/associations/belongs_to_associations_test.rb +1029 -1029
  30. data/test/cases/associations/callbacks_test.rb +192 -192
  31. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  32. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -26
  33. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  34. data/test/cases/associations/eager_load_nested_include_test.rb +128 -128
  35. data/test/cases/associations/eager_singularization_test.rb +148 -148
  36. data/test/cases/associations/eager_test.rb +1429 -1411
  37. data/test/cases/associations/extension_test.rb +82 -82
  38. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +972 -932
  39. data/test/cases/associations/has_many_associations_test.rb +2182 -2162
  40. data/test/cases/associations/has_many_through_associations_test.rb +1204 -1204
  41. data/test/cases/associations/has_one_associations_test.rb +610 -610
  42. data/test/cases/associations/has_one_through_associations_test.rb +380 -380
  43. data/test/cases/associations/inner_join_association_test.rb +139 -139
  44. data/test/cases/associations/inverse_associations_test.rb +706 -693
  45. data/test/cases/associations/join_model_test.rb +754 -754
  46. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  47. data/test/cases/associations/required_test.rb +82 -82
  48. data/test/cases/associations_test.rb +380 -380
  49. data/test/cases/attribute_decorators_test.rb +125 -125
  50. data/test/cases/attribute_methods/read_test.rb +60 -60
  51. data/test/cases/attribute_methods/serialization_test.rb +29 -29
  52. data/test/cases/attribute_methods_test.rb +952 -952
  53. data/test/cases/attribute_set_test.rb +210 -200
  54. data/test/cases/attribute_test.rb +180 -180
  55. data/test/cases/attributes_test.rb +136 -136
  56. data/test/cases/autosave_association_test.rb +1595 -1595
  57. data/test/cases/base_test.rb +1664 -1638
  58. data/test/cases/batches_test.rb +212 -212
  59. data/test/cases/binary_test.rb +52 -52
  60. data/test/cases/bind_parameter_test.rb +100 -100
  61. data/test/cases/calculations_test.rb +646 -646
  62. data/test/cases/callbacks_test.rb +543 -543
  63. data/test/cases/clone_test.rb +40 -40
  64. data/test/cases/coders/yaml_column_test.rb +63 -63
  65. data/test/cases/column_alias_test.rb +17 -17
  66. data/test/cases/column_definition_test.rb +123 -123
  67. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -54
  68. data/test/cases/connection_adapters/connection_handler_test.rb +53 -53
  69. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  70. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -293
  71. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -65
  72. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  73. data/test/cases/connection_adapters/schema_cache_test.rb +56 -56
  74. data/test/cases/connection_adapters/type_lookup_test.rb +110 -110
  75. data/test/cases/connection_management_test.rb +122 -122
  76. data/test/cases/connection_pool_test.rb +346 -346
  77. data/test/cases/connection_specification/resolver_test.rb +116 -116
  78. data/test/cases/core_test.rb +112 -112
  79. data/test/cases/counter_cache_test.rb +209 -209
  80. data/test/cases/custom_locking_test.rb +17 -17
  81. data/test/cases/database_statements_test.rb +19 -19
  82. data/test/cases/date_time_test.rb +61 -61
  83. data/test/cases/defaults_test.rb +223 -223
  84. data/test/cases/dirty_test.rb +785 -775
  85. data/test/cases/disconnected_test.rb +28 -28
  86. data/test/cases/dup_test.rb +157 -157
  87. data/test/cases/enum_test.rb +290 -290
  88. data/test/cases/explain_subscriber_test.rb +64 -64
  89. data/test/cases/explain_test.rb +76 -76
  90. data/test/cases/finder_respond_to_test.rb +60 -60
  91. data/test/cases/finder_test.rb +1169 -1166
  92. data/test/cases/fixture_set/file_test.rb +138 -138
  93. data/test/cases/fixtures_test.rb +908 -897
  94. data/test/cases/forbidden_attributes_protection_test.rb +99 -99
  95. data/test/cases/habtm_destroy_order_test.rb +61 -61
  96. data/test/cases/helper.rb +210 -210
  97. data/test/cases/hot_compatibility_test.rb +54 -54
  98. data/test/cases/i18n_test.rb +45 -45
  99. data/test/cases/inheritance_test.rb +375 -375
  100. data/test/cases/integration_test.rb +139 -139
  101. data/test/cases/invalid_connection_test.rb +22 -22
  102. data/test/cases/invalid_date_test.rb +32 -32
  103. data/test/cases/invertible_migration_test.rb +295 -295
  104. data/test/cases/json_serialization_test.rb +302 -302
  105. data/test/cases/locking_test.rb +477 -477
  106. data/test/cases/log_subscriber_test.rb +136 -136
  107. data/test/cases/migration/change_schema_test - Copy.rb +448 -448
  108. data/test/cases/migration/change_schema_test.rb +512 -472
  109. data/test/cases/migration/change_table_test.rb +224 -224
  110. data/test/cases/migration/column_attributes_test.rb +192 -192
  111. data/test/cases/migration/column_positioning_test.rb +56 -56
  112. data/test/cases/migration/columns_test.rb +304 -304
  113. data/test/cases/migration/command_recorder_test.rb +305 -305
  114. data/test/cases/migration/create_join_table_test.rb +148 -148
  115. data/test/cases/migration/foreign_key_test - Changed.rb +325 -325
  116. data/test/cases/migration/foreign_key_test.rb +328 -360
  117. data/test/cases/migration/helper.rb +39 -39
  118. data/test/cases/migration/index_test.rb +216 -216
  119. data/test/cases/migration/logger_test.rb +36 -36
  120. data/test/cases/migration/pending_migrations_test.rb +53 -53
  121. data/test/cases/migration/references_foreign_key_test.rb +169 -214
  122. data/test/cases/migration/references_index_test.rb +101 -101
  123. data/test/cases/migration/references_statements_test.rb +116 -116
  124. data/test/cases/migration/rename_table_test.rb +93 -93
  125. data/test/cases/migration/table_and_index_test.rb +24 -24
  126. data/test/cases/migration_test.rb +959 -959
  127. data/test/cases/migrator_test.rb +388 -388
  128. data/test/cases/mixin_test.rb +70 -70
  129. data/test/cases/modules_test.rb +173 -173
  130. data/test/cases/multiparameter_attributes_test.rb +350 -350
  131. data/test/cases/multiple_db_test.rb +115 -115
  132. data/test/cases/nested_attributes_test.rb +1070 -1057
  133. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  134. data/test/cases/persistence_test.rb +909 -909
  135. data/test/cases/pooled_connections_test.rb +81 -81
  136. data/test/cases/primary_keys_test.rb +237 -237
  137. data/test/cases/query_cache_test.rb +326 -326
  138. data/test/cases/quoting_test.rb +156 -156
  139. data/test/cases/readonly_test.rb +118 -118
  140. data/test/cases/reaper_test.rb +85 -85
  141. data/test/cases/reflection_test.rb +463 -454
  142. data/test/cases/relation/delegation_test.rb +68 -68
  143. data/test/cases/relation/merging_test.rb +161 -161
  144. data/test/cases/relation/mutation_test.rb +165 -165
  145. data/test/cases/relation/predicate_builder_test.rb +14 -14
  146. data/test/cases/relation/where_chain_test.rb +181 -181
  147. data/test/cases/relation/where_test.rb +300 -300
  148. data/test/cases/relation/where_test2.rb +36 -36
  149. data/test/cases/relation_test.rb +319 -297
  150. data/test/cases/relations_test.rb +1815 -1815
  151. data/test/cases/reload_models_test.rb +22 -22
  152. data/test/cases/result_test.rb +80 -80
  153. data/test/cases/sanitize_test.rb +83 -83
  154. data/test/cases/schema_dumper_test.rb +463 -463
  155. data/test/cases/scoping/default_scoping_test.rb +454 -454
  156. data/test/cases/scoping/named_scoping_test.rb +524 -524
  157. data/test/cases/scoping/relation_scoping_test.rb +357 -357
  158. data/test/cases/serialization_test.rb +104 -104
  159. data/test/cases/serialized_attribute_test.rb +277 -277
  160. data/test/cases/statement_cache_test.rb +98 -98
  161. data/test/cases/store_test.rb +194 -194
  162. data/test/cases/tasks/database_tasks_test.rb +398 -396
  163. data/test/cases/tasks/mysql_rake_test.rb +324 -311
  164. data/test/cases/tasks/postgresql_rake_test.rb +250 -245
  165. data/test/cases/tasks/sqlite_rake_test.rb +193 -193
  166. data/test/cases/test_case.rb +123 -123
  167. data/test/cases/timestamp_test.rb +467 -468
  168. data/test/cases/transaction_callbacks_test.rb +452 -452
  169. data/test/cases/transaction_isolation_test.rb +106 -106
  170. data/test/cases/transactions_test.rb +817 -817
  171. data/test/cases/type/decimal_test.rb +56 -51
  172. data/test/cases/type/integer_test.rb +121 -121
  173. data/test/cases/type/string_test.rb +36 -36
  174. data/test/cases/type/type_map_test.rb +177 -177
  175. data/test/cases/type/unsigned_integer_test.rb +18 -18
  176. data/test/cases/types_test.rb +141 -141
  177. data/test/cases/unconnected_test.rb +33 -33
  178. data/test/cases/validations/association_validation_test.rb +86 -86
  179. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  180. data/test/cases/validations/i18n_validation_test.rb +90 -90
  181. data/test/cases/validations/length_validation_test.rb +47 -47
  182. data/test/cases/validations/presence_validation_test.rb +68 -68
  183. data/test/cases/validations/uniqueness_validation_test.rb +457 -434
  184. data/test/cases/validations_repair_helper.rb +23 -23
  185. data/test/cases/validations_test.rb +165 -165
  186. data/test/cases/view_test.rb +119 -113
  187. data/test/cases/xml_serialization_test.rb +457 -457
  188. data/test/cases/yaml_serialization_test.rb +126 -86
  189. data/test/config.rb +5 -5
  190. data/test/config.yml +154 -154
  191. data/test/connections/native_ibm_db/connection.rb +43 -43
  192. data/test/fixtures/accounts.yml +29 -29
  193. data/test/fixtures/admin/accounts.yml +2 -2
  194. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  195. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  196. data/test/fixtures/admin/users.yml +10 -10
  197. data/test/fixtures/author_addresses.yml +17 -17
  198. data/test/fixtures/author_favorites.yml +3 -3
  199. data/test/fixtures/authors.yml +23 -23
  200. data/test/fixtures/binaries.yml +133 -133
  201. data/test/fixtures/books.yml +11 -11
  202. data/test/fixtures/bulbs.yml +5 -5
  203. data/test/fixtures/cars.yml +9 -9
  204. data/test/fixtures/categories.yml +19 -19
  205. data/test/fixtures/categories/special_categories.yml +9 -9
  206. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  207. data/test/fixtures/categories_ordered.yml +7 -7
  208. data/test/fixtures/categories_posts.yml +31 -31
  209. data/test/fixtures/categorizations.yml +23 -23
  210. data/test/fixtures/clubs.yml +8 -8
  211. data/test/fixtures/collections.yml +3 -3
  212. data/test/fixtures/colleges.yml +3 -3
  213. data/test/fixtures/comments.yml +65 -65
  214. data/test/fixtures/companies.yml +67 -67
  215. data/test/fixtures/computers.yml +10 -10
  216. data/test/fixtures/courses.yml +8 -8
  217. data/test/fixtures/customers.yml +25 -25
  218. data/test/fixtures/dashboards.yml +6 -6
  219. data/test/fixtures/developers.yml +21 -21
  220. data/test/fixtures/developers_projects.yml +16 -16
  221. data/test/fixtures/dog_lovers.yml +7 -7
  222. data/test/fixtures/dogs.yml +4 -4
  223. data/test/fixtures/doubloons.yml +3 -3
  224. data/test/fixtures/edges.yml +5 -5
  225. data/test/fixtures/entrants.yml +14 -14
  226. data/test/fixtures/essays.yml +6 -6
  227. data/test/fixtures/faces.yml +11 -11
  228. data/test/fixtures/fk_test_has_fk.yml +3 -3
  229. data/test/fixtures/fk_test_has_pk.yml +1 -1
  230. data/test/fixtures/friendships.yml +4 -4
  231. data/test/fixtures/funny_jokes.yml +10 -10
  232. data/test/fixtures/interests.yml +33 -33
  233. data/test/fixtures/items.yml +3 -3
  234. data/test/fixtures/jobs.yml +7 -7
  235. data/test/fixtures/legacy_things.yml +3 -3
  236. data/test/fixtures/mateys.yml +4 -4
  237. data/test/fixtures/member_details.yml +8 -8
  238. data/test/fixtures/member_types.yml +6 -6
  239. data/test/fixtures/members.yml +11 -11
  240. data/test/fixtures/memberships.yml +34 -34
  241. data/test/fixtures/men.yml +5 -5
  242. data/test/fixtures/minimalistics.yml +2 -2
  243. data/test/fixtures/minivans.yml +5 -5
  244. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  245. data/test/fixtures/mixins.yml +29 -29
  246. data/test/fixtures/movies.yml +7 -7
  247. data/test/fixtures/naked/csv/accounts.csv +1 -1
  248. data/test/fixtures/naked/yml/accounts.yml +1 -1
  249. data/test/fixtures/naked/yml/companies.yml +1 -1
  250. data/test/fixtures/naked/yml/courses.yml +1 -1
  251. data/test/fixtures/organizations.yml +5 -5
  252. data/test/fixtures/other_topics.yml +42 -42
  253. data/test/fixtures/owners.yml +9 -9
  254. data/test/fixtures/parrots.yml +27 -27
  255. data/test/fixtures/parrots_pirates.yml +7 -7
  256. data/test/fixtures/people.yml +24 -24
  257. data/test/fixtures/peoples_treasures.yml +3 -3
  258. data/test/fixtures/pets.yml +19 -19
  259. data/test/fixtures/pirates.yml +12 -12
  260. data/test/fixtures/posts.yml +80 -80
  261. data/test/fixtures/price_estimates.yml +7 -7
  262. data/test/fixtures/products.yml +4 -4
  263. data/test/fixtures/projects.yml +7 -7
  264. data/test/fixtures/randomly_named_a9.yml +7 -7
  265. data/test/fixtures/ratings.yml +14 -14
  266. data/test/fixtures/readers.yml +11 -11
  267. data/test/fixtures/references.yml +17 -17
  268. data/test/fixtures/reserved_words/distinct.yml +5 -5
  269. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  270. data/test/fixtures/reserved_words/group.yml +14 -14
  271. data/test/fixtures/reserved_words/select.yml +8 -8
  272. data/test/fixtures/reserved_words/values.yml +7 -7
  273. data/test/fixtures/ships.yml +6 -6
  274. data/test/fixtures/speedometers.yml +8 -8
  275. data/test/fixtures/sponsors.yml +12 -12
  276. data/test/fixtures/string_key_objects.yml +7 -7
  277. data/test/fixtures/subscribers.yml +10 -10
  278. data/test/fixtures/subscriptions.yml +12 -12
  279. data/test/fixtures/taggings.yml +78 -78
  280. data/test/fixtures/tags.yml +11 -11
  281. data/test/fixtures/tasks.yml +7 -7
  282. data/test/fixtures/teapots.yml +3 -3
  283. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  284. data/test/fixtures/to_be_linked/users.yml +10 -10
  285. data/test/fixtures/topics.yml +49 -49
  286. data/test/fixtures/toys.yml +14 -14
  287. data/test/fixtures/traffic_lights.yml +9 -9
  288. data/test/fixtures/treasures.yml +10 -10
  289. data/test/fixtures/uuid_children.yml +3 -3
  290. data/test/fixtures/uuid_parents.yml +2 -2
  291. data/test/fixtures/variants.yml +4 -4
  292. data/test/fixtures/vegetables.yml +19 -19
  293. data/test/fixtures/vertices.yml +3 -3
  294. data/test/fixtures/warehouse_things.yml +2 -2
  295. data/test/fixtures/zines.yml +5 -5
  296. data/test/ibm_db_test.rb +24 -24
  297. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  298. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  299. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  300. data/test/migrations/missing/1000_people_have_middle_names.rb +8 -8
  301. data/test/migrations/missing/1_people_have_last_names.rb +8 -8
  302. data/test/migrations/missing/3_we_need_reminders.rb +11 -11
  303. data/test/migrations/missing/4_innocent_jointable.rb +11 -11
  304. data/test/migrations/rename/1_we_need_things.rb +10 -10
  305. data/test/migrations/rename/2_rename_things.rb +8 -8
  306. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  307. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  308. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  309. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  310. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  311. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  312. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  313. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  314. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  315. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  316. data/test/migrations/valid/2_we_need_reminders.rb +11 -11
  317. data/test/migrations/valid/3_innocent_jointable.rb +11 -11
  318. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  319. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +11 -11
  320. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +11 -11
  321. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  322. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  323. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  324. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  325. data/test/models/admin.rb +4 -4
  326. data/test/models/admin/account.rb +2 -2
  327. data/test/models/admin/randomly_named_c1.rb +3 -3
  328. data/test/models/admin/user.rb +40 -40
  329. data/test/models/aircraft.rb +4 -4
  330. data/test/models/arunit2_model.rb +3 -3
  331. data/test/models/author.rb +212 -212
  332. data/test/models/auto_id.rb +4 -4
  333. data/test/models/autoloadable/extra_firm.rb +2 -2
  334. data/test/models/binary.rb +1 -1
  335. data/test/models/bird.rb +12 -12
  336. data/test/models/book.rb +18 -18
  337. data/test/models/boolean.rb +2 -2
  338. data/test/models/bulb.rb +51 -51
  339. data/test/models/cake_designer.rb +3 -3
  340. data/test/models/car.rb +26 -26
  341. data/test/models/carrier.rb +2 -2
  342. data/test/models/categorization.rb +19 -19
  343. data/test/models/category.rb +35 -35
  344. data/test/models/chef.rb +7 -3
  345. data/test/models/citation.rb +3 -3
  346. data/test/models/club.rb +23 -23
  347. data/test/models/college.rb +10 -10
  348. data/test/models/column.rb +3 -3
  349. data/test/models/column_name.rb +3 -3
  350. data/test/models/comment.rb +64 -64
  351. data/test/models/company.rb +228 -225
  352. data/test/models/company_in_module.rb +98 -98
  353. data/test/models/computer.rb +3 -3
  354. data/test/models/contact.rb +41 -41
  355. data/test/models/contract.rb +20 -20
  356. data/test/models/country.rb +7 -7
  357. data/test/models/course.rb +6 -6
  358. data/test/models/customer.rb +77 -77
  359. data/test/models/customer_carrier.rb +14 -14
  360. data/test/models/dashboard.rb +3 -3
  361. data/test/models/default.rb +2 -2
  362. data/test/models/department.rb +4 -4
  363. data/test/models/developer.rb +255 -252
  364. data/test/models/dog.rb +5 -5
  365. data/test/models/dog_lover.rb +5 -5
  366. data/test/models/doubloon.rb +12 -12
  367. data/test/models/drink_designer.rb +3 -3
  368. data/test/models/edge.rb +5 -5
  369. data/test/models/electron.rb +5 -5
  370. data/test/models/engine.rb +4 -4
  371. data/test/models/entrant.rb +3 -3
  372. data/test/models/essay.rb +5 -5
  373. data/test/models/event.rb +2 -2
  374. data/test/models/eye.rb +37 -37
  375. data/test/models/face.rb +9 -9
  376. data/test/models/friendship.rb +6 -6
  377. data/test/models/guid.rb +1 -1
  378. data/test/models/hotel.rb +9 -6
  379. data/test/models/image.rb +3 -3
  380. data/test/models/interest.rb +5 -5
  381. data/test/models/invoice.rb +4 -4
  382. data/test/models/item.rb +7 -7
  383. data/test/models/job.rb +7 -7
  384. data/test/models/joke.rb +7 -7
  385. data/test/models/keyboard.rb +3 -3
  386. data/test/models/legacy_thing.rb +3 -3
  387. data/test/models/lesson.rb +11 -11
  388. data/test/models/line_item.rb +3 -3
  389. data/test/models/liquid.rb +4 -4
  390. data/test/models/man.rb +11 -11
  391. data/test/models/matey.rb +4 -4
  392. data/test/models/member.rb +41 -41
  393. data/test/models/member_detail.rb +7 -7
  394. data/test/models/member_type.rb +3 -3
  395. data/test/models/membership.rb +35 -35
  396. data/test/models/minimalistic.rb +2 -2
  397. data/test/models/minivan.rb +9 -9
  398. data/test/models/mixed_case_monkey.rb +3 -3
  399. data/test/models/molecule.rb +6 -6
  400. data/test/models/movie.rb +5 -5
  401. data/test/models/order.rb +4 -4
  402. data/test/models/organization.rb +14 -14
  403. data/test/models/owner.rb +34 -34
  404. data/test/models/parrot.rb +29 -29
  405. data/test/models/person.rb +143 -143
  406. data/test/models/personal_legacy_thing.rb +4 -4
  407. data/test/models/pet.rb +15 -15
  408. data/test/models/pirate.rb +92 -92
  409. data/test/models/possession.rb +3 -3
  410. data/test/models/post.rb +264 -264
  411. data/test/models/price_estimate.rb +4 -4
  412. data/test/models/professor.rb +5 -5
  413. data/test/models/project.rb +31 -29
  414. data/test/models/publisher.rb +2 -2
  415. data/test/models/publisher/article.rb +4 -4
  416. data/test/models/publisher/magazine.rb +3 -3
  417. data/test/models/randomly_named_c1.rb +3 -3
  418. data/test/models/rating.rb +4 -4
  419. data/test/models/reader.rb +23 -23
  420. data/test/models/record.rb +2 -2
  421. data/test/models/reference.rb +22 -22
  422. data/test/models/reply.rb +61 -61
  423. data/test/models/ship.rb +33 -33
  424. data/test/models/ship_part.rb +7 -7
  425. data/test/models/shop.rb +17 -17
  426. data/test/models/shop_account.rb +6 -6
  427. data/test/models/speedometer.rb +6 -6
  428. data/test/models/sponsor.rb +7 -7
  429. data/test/models/string_key_object.rb +3 -3
  430. data/test/models/student.rb +4 -4
  431. data/test/models/subject.rb +16 -16
  432. data/test/models/subscriber.rb +8 -8
  433. data/test/models/subscription.rb +4 -4
  434. data/test/models/tag.rb +7 -7
  435. data/test/models/tagging.rb +13 -13
  436. data/test/models/task.rb +5 -5
  437. data/test/models/topic.rb +124 -124
  438. data/test/models/toy.rb +6 -6
  439. data/test/models/traffic_light.rb +4 -4
  440. data/test/models/treasure.rb +14 -14
  441. data/test/models/treaty.rb +7 -7
  442. data/test/models/tyre.rb +11 -11
  443. data/test/models/uuid_child.rb +3 -3
  444. data/test/models/uuid_parent.rb +3 -3
  445. data/test/models/vegetables.rb +24 -24
  446. data/test/models/vehicle.rb +6 -6
  447. data/test/models/vertex.rb +9 -9
  448. data/test/models/warehouse_thing.rb +5 -5
  449. data/test/models/wheel.rb +3 -3
  450. data/test/models/without_table.rb +3 -3
  451. data/test/models/zine.rb +3 -3
  452. data/test/schema/mysql2_specific_schema.rb +58 -58
  453. data/test/schema/mysql_specific_schema.rb +70 -70
  454. data/test/schema/oracle_specific_schema.rb +43 -43
  455. data/test/schema/postgresql_specific_schema.rb +202 -202
  456. data/test/schema/schema.rb +952 -938
  457. data/test/schema/sqlite_specific_schema.rb +21 -21
  458. data/test/support/config.rb +43 -43
  459. data/test/support/connection.rb +22 -22
  460. data/test/support/connection_helper.rb +14 -14
  461. data/test/support/ddl_helper.rb +8 -8
  462. data/test/support/schema_dumping_helper.rb +20 -20
  463. metadata +2 -2
@@ -1,1411 +1,1429 @@
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_polymorphic_with_custom_foreign_type
1209
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
1210
- groucho = members(:groucho)
1211
-
1212
- sponsor = assert_queries(2) {
1213
- Sponsor.includes(:thing).where(:id => sponsor.id).first
1214
- }
1215
- assert_no_queries { assert_equal groucho, sponsor.thing }
1216
- end
1217
-
1218
- def test_joins_with_includes_should_preload_via_joins
1219
- post = assert_queries(1) { Post.includes(:comments).joins(:comments).order('posts.id desc').to_a.first }
1220
-
1221
- assert_queries(0) do
1222
- assert_not_equal 0, post.comments.to_a.count
1223
- end
1224
- end
1225
-
1226
- def test_join_eager_with_empty_order_should_generate_valid_sql
1227
- assert_nothing_raised(ActiveRecord::StatementInvalid) do
1228
- Post.includes(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
1229
- end
1230
- end
1231
-
1232
- def test_join_eager_with_nil_order_should_generate_valid_sql
1233
- assert_nothing_raised(ActiveRecord::StatementInvalid) do
1234
- Post.includes(:comments).order(nil).where(:comments => {:body => "Thank you for the welcome"}).first
1235
- end
1236
- end
1237
-
1238
- def test_deep_including_through_habtm
1239
- # warm up habtm cache
1240
- posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1241
- posts[0].categories[0].categorizations.length
1242
-
1243
- posts = Post.all.merge!(:includes => {:categories => :categorizations}, :order => "posts.id").to_a
1244
- assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.length }
1245
- assert_no_queries { assert_equal 1, posts[0].categories[1].categorizations.length }
1246
- assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.length }
1247
- end
1248
-
1249
- test "scoping with a circular preload" do
1250
- assert_equal Comment.find(1), Comment.preload(:post => :comments).scoping { Comment.find(1) }
1251
- end
1252
-
1253
- test "circular preload does not modify unscoped" do
1254
- expected = FirstPost.unscoped.find(2)
1255
- FirstPost.preload(:comments => :first_post).find(1)
1256
- assert_equal expected, FirstPost.unscoped.find(2)
1257
- end
1258
-
1259
- test "preload ignores the scoping" do
1260
- assert_equal(
1261
- Comment.find(1).post,
1262
- Post.where('1 = 0').scoping { Comment.preload(:post).find(1).post }
1263
- )
1264
- end
1265
-
1266
- test "deep preload" do
1267
- post = Post.preload(author: :posts, comments: :post).first
1268
-
1269
- assert_predicate post.author.association(:posts), :loaded?
1270
- assert_predicate post.comments.first.association(:post), :loaded?
1271
- end
1272
-
1273
- test "preloading does not cache has many association subset when preloaded with a through association" do
1274
- author = Author.includes(:comments_with_order_and_conditions, :posts).first
1275
- assert_no_queries { assert_equal 2, author.comments_with_order_and_conditions.size }
1276
- assert_no_queries { assert_equal 5, author.posts.size, "should not cache a subset of the association" }
1277
- end
1278
-
1279
- test "preloading a through association twice does not reset it" do
1280
- members = Member.includes(current_membership: :club).includes(:club).to_a
1281
- assert_no_queries {
1282
- assert_equal 3, members.map(&:current_membership).map(&:club).size
1283
- }
1284
- end
1285
-
1286
- test "works in combination with order(:symbol) and reorder(:symbol)" do
1287
- author = Author.includes(:posts).references(:posts).order(:name).find_by('posts.title IS NOT NULL')
1288
- assert_equal authors(:bob), author
1289
-
1290
- author = Author.includes(:posts).references(:posts).reorder(:name).find_by('posts.title IS NOT NULL')
1291
- assert_equal authors(:bob), author
1292
- end
1293
-
1294
- test "preloading with a polymorphic association and using the existential predicate but also using a select" do
1295
- assert_equal authors(:david), authors(:david).essays.includes(:writer).first.writer
1296
-
1297
- assert_nothing_raised do
1298
- authors(:david).essays.includes(:writer).select(:name).any?
1299
- end
1300
- end
1301
-
1302
- test "preloading the same association twice works" do
1303
- Member.create!
1304
- members = Member.preload(:current_membership).includes(current_membership: :club).all.to_a
1305
- assert_no_queries {
1306
- members_with_membership = members.select(&:current_membership)
1307
- assert_equal 3, members_with_membership.map(&:current_membership).map(&:club).size
1308
- }
1309
- end
1310
-
1311
- test "preloading with a polymorphic association and using the existential predicate" do
1312
- assert_equal authors(:david), authors(:david).essays.includes(:writer).first.writer
1313
-
1314
- assert_nothing_raised do
1315
- authors(:david).essays.includes(:writer).any?
1316
- end
1317
- end
1318
-
1319
- test "preloading associations with string joins and order references" do
1320
- author = assert_queries(2) {
1321
- Author.includes(:posts).joins("LEFT JOIN posts ON posts.author_id = authors.id").order("posts.title DESC").first
1322
- }
1323
- assert_no_queries {
1324
- assert_equal 5, author.posts.size
1325
- }
1326
- end
1327
-
1328
- test "including associations with where.not adds implicit references" do
1329
- author = assert_queries(2) {
1330
- Author.includes(:posts).where.not(posts: { title: 'Welcome to the weblog'} ).last
1331
- }
1332
-
1333
- assert_no_queries {
1334
- assert_equal 2, author.posts.size
1335
- }
1336
- end
1337
-
1338
- test "including association based on sql condition and no database column" do
1339
- assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet
1340
- end
1341
-
1342
- test "include instance dependent associations is deprecated" do
1343
- message = "association scope 'posts_with_signature' is"
1344
- assert_deprecated message do
1345
- begin
1346
- Author.includes(:posts_with_signature).to_a
1347
- rescue NoMethodError
1348
- # it's expected that preloading of this association fails
1349
- end
1350
- end
1351
-
1352
- assert_deprecated message do
1353
- Author.preload(:posts_with_signature).to_a rescue NoMethodError
1354
- end
1355
-
1356
- assert_deprecated message do
1357
- Author.eager_load(:posts_with_signature).to_a
1358
- end
1359
- end
1360
-
1361
- test "associations with extensions are not instance dependent" do
1362
- assert_not_deprecated do
1363
- Author.includes(:posts_with_extension).to_a
1364
- end
1365
- end
1366
-
1367
- test "including associations with extensions and an instance dependent scope is deprecated" do
1368
- assert_deprecated do
1369
- Author.includes(:posts_with_extension_and_instance).to_a
1370
- end
1371
- end
1372
-
1373
- test "preloading readonly association" do
1374
- # has-one
1375
- firm = Firm.where(id: "1").preload(:readonly_account).first!
1376
- assert firm.readonly_account.readonly?
1377
-
1378
- # has_and_belongs_to_many
1379
- project = Project.where(id: "2").preload(:readonly_developers).first!
1380
- assert project.readonly_developers.first.readonly?
1381
-
1382
- # has-many :through
1383
- david = Author.where(id: "1").preload(:readonly_comments).first!
1384
- assert david.readonly_comments.first.readonly?
1385
- end
1386
-
1387
- test "eager-loading readonly association" do
1388
- skip "eager_load does not yet preserve readonly associations"
1389
- # has-one
1390
- firm = Firm.where(id: "1").eager_load(:readonly_account).first!
1391
- assert firm.readonly_account.readonly?
1392
-
1393
- # has_and_belongs_to_many
1394
- project = Project.where(id: "2").eager_load(:readonly_developers).first!
1395
- assert project.readonly_developers.first.readonly?
1396
-
1397
- # has-many :through
1398
- david = Author.where(id: "1").eager_load(:readonly_comments).first!
1399
- assert david.readonly_comments.first.readonly?
1400
- end
1401
-
1402
- test "preloading a polymorphic association with references to the associated table" do
1403
- post = Post.includes(:tags).references(:tags).where('tags.name = ?', 'General').first
1404
- assert_equal posts(:welcome), post
1405
- end
1406
-
1407
- test "eager-loading a polymorphic association with references to the associated table" do
1408
- post = Post.eager_load(:tags).where('tags.name = ?', 'General').first
1409
- assert_equal posts(:welcome), post
1410
- end
1411
- 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
+
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