activerecord_csi 2.3.5.p6

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 (333) hide show
  1. data/CHANGELOG +5858 -0
  2. data/README +351 -0
  3. data/RUNNING_UNIT_TESTS +36 -0
  4. data/Rakefile +270 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/performance.rb +162 -0
  7. data/install.rb +30 -0
  8. data/lib/active_record/aggregations.rb +261 -0
  9. data/lib/active_record/association_preload.rb +389 -0
  10. data/lib/active_record/associations/association_collection.rb +475 -0
  11. data/lib/active_record/associations/association_proxy.rb +278 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +76 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +53 -0
  14. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +143 -0
  15. data/lib/active_record/associations/has_many_association.rb +122 -0
  16. data/lib/active_record/associations/has_many_through_association.rb +266 -0
  17. data/lib/active_record/associations/has_one_association.rb +133 -0
  18. data/lib/active_record/associations/has_one_through_association.rb +37 -0
  19. data/lib/active_record/associations.rb +2241 -0
  20. data/lib/active_record/attribute_methods.rb +388 -0
  21. data/lib/active_record/autosave_association.rb +364 -0
  22. data/lib/active_record/base.rb +3171 -0
  23. data/lib/active_record/batches.rb +81 -0
  24. data/lib/active_record/calculations.rb +311 -0
  25. data/lib/active_record/callbacks.rb +360 -0
  26. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +371 -0
  27. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +139 -0
  28. data/lib/active_record/connection_adapters/abstract/database_statements.rb +289 -0
  29. data/lib/active_record/connection_adapters/abstract/query_cache.rb +94 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +722 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +434 -0
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +241 -0
  34. data/lib/active_record/connection_adapters/mysql_adapter.rb +630 -0
  35. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1113 -0
  36. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  37. data/lib/active_record/connection_adapters/sqlite_adapter.rb +453 -0
  38. data/lib/active_record/dirty.rb +183 -0
  39. data/lib/active_record/dynamic_finder_match.rb +41 -0
  40. data/lib/active_record/dynamic_scope_match.rb +25 -0
  41. data/lib/active_record/fixtures.rb +996 -0
  42. data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
  43. data/lib/active_record/locale/en.yml +58 -0
  44. data/lib/active_record/locking/optimistic.rb +148 -0
  45. data/lib/active_record/locking/pessimistic.rb +55 -0
  46. data/lib/active_record/migration.rb +566 -0
  47. data/lib/active_record/named_scope.rb +192 -0
  48. data/lib/active_record/nested_attributes.rb +392 -0
  49. data/lib/active_record/observer.rb +197 -0
  50. data/lib/active_record/query_cache.rb +33 -0
  51. data/lib/active_record/reflection.rb +320 -0
  52. data/lib/active_record/schema.rb +51 -0
  53. data/lib/active_record/schema_dumper.rb +182 -0
  54. data/lib/active_record/serialization.rb +101 -0
  55. data/lib/active_record/serializers/json_serializer.rb +91 -0
  56. data/lib/active_record/serializers/xml_serializer.rb +357 -0
  57. data/lib/active_record/session_store.rb +326 -0
  58. data/lib/active_record/test_case.rb +66 -0
  59. data/lib/active_record/timestamp.rb +71 -0
  60. data/lib/active_record/transactions.rb +235 -0
  61. data/lib/active_record/validations.rb +1135 -0
  62. data/lib/active_record/version.rb +9 -0
  63. data/lib/active_record.rb +84 -0
  64. data/lib/activerecord.rb +2 -0
  65. data/test/assets/example.log +1 -0
  66. data/test/assets/flowers.jpg +0 -0
  67. data/test/cases/aaa_create_tables_test.rb +24 -0
  68. data/test/cases/active_schema_test_mysql.rb +100 -0
  69. data/test/cases/active_schema_test_postgresql.rb +24 -0
  70. data/test/cases/adapter_test.rb +145 -0
  71. data/test/cases/aggregations_test.rb +167 -0
  72. data/test/cases/ar_schema_test.rb +32 -0
  73. data/test/cases/associations/belongs_to_associations_test.rb +425 -0
  74. data/test/cases/associations/callbacks_test.rb +161 -0
  75. data/test/cases/associations/cascaded_eager_loading_test.rb +131 -0
  76. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  77. data/test/cases/associations/eager_load_nested_include_test.rb +130 -0
  78. data/test/cases/associations/eager_singularization_test.rb +145 -0
  79. data/test/cases/associations/eager_test.rb +834 -0
  80. data/test/cases/associations/extension_test.rb +62 -0
  81. data/test/cases/associations/habtm_join_table_test.rb +56 -0
  82. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +822 -0
  83. data/test/cases/associations/has_many_associations_test.rb +1134 -0
  84. data/test/cases/associations/has_many_through_associations_test.rb +346 -0
  85. data/test/cases/associations/has_one_associations_test.rb +330 -0
  86. data/test/cases/associations/has_one_through_associations_test.rb +209 -0
  87. data/test/cases/associations/inner_join_association_test.rb +93 -0
  88. data/test/cases/associations/join_model_test.rb +712 -0
  89. data/test/cases/associations_test.rb +262 -0
  90. data/test/cases/attribute_methods_test.rb +305 -0
  91. data/test/cases/autosave_association_test.rb +1142 -0
  92. data/test/cases/base_test.rb +2154 -0
  93. data/test/cases/batches_test.rb +61 -0
  94. data/test/cases/binary_test.rb +30 -0
  95. data/test/cases/calculations_test.rb +348 -0
  96. data/test/cases/callbacks_observers_test.rb +38 -0
  97. data/test/cases/callbacks_test.rb +438 -0
  98. data/test/cases/class_inheritable_attributes_test.rb +32 -0
  99. data/test/cases/column_alias_test.rb +17 -0
  100. data/test/cases/column_definition_test.rb +70 -0
  101. data/test/cases/connection_pool_test.rb +25 -0
  102. data/test/cases/connection_test_firebird.rb +8 -0
  103. data/test/cases/connection_test_mysql.rb +64 -0
  104. data/test/cases/copy_table_test_sqlite.rb +80 -0
  105. data/test/cases/database_statements_test.rb +12 -0
  106. data/test/cases/datatype_test_postgresql.rb +204 -0
  107. data/test/cases/date_time_test.rb +37 -0
  108. data/test/cases/default_test_firebird.rb +16 -0
  109. data/test/cases/defaults_test.rb +111 -0
  110. data/test/cases/deprecated_finder_test.rb +30 -0
  111. data/test/cases/dirty_test.rb +316 -0
  112. data/test/cases/finder_respond_to_test.rb +76 -0
  113. data/test/cases/finder_test.rb +1066 -0
  114. data/test/cases/fixtures_test.rb +656 -0
  115. data/test/cases/helper.rb +68 -0
  116. data/test/cases/i18n_test.rb +46 -0
  117. data/test/cases/inheritance_test.rb +262 -0
  118. data/test/cases/invalid_date_test.rb +24 -0
  119. data/test/cases/json_serialization_test.rb +205 -0
  120. data/test/cases/lifecycle_test.rb +193 -0
  121. data/test/cases/locking_test.rb +304 -0
  122. data/test/cases/method_scoping_test.rb +704 -0
  123. data/test/cases/migration_test.rb +1523 -0
  124. data/test/cases/migration_test_firebird.rb +124 -0
  125. data/test/cases/mixin_test.rb +96 -0
  126. data/test/cases/modules_test.rb +81 -0
  127. data/test/cases/multiple_db_test.rb +85 -0
  128. data/test/cases/named_scope_test.rb +361 -0
  129. data/test/cases/nested_attributes_test.rb +581 -0
  130. data/test/cases/pk_test.rb +119 -0
  131. data/test/cases/pooled_connections_test.rb +103 -0
  132. data/test/cases/query_cache_test.rb +123 -0
  133. data/test/cases/readonly_test.rb +107 -0
  134. data/test/cases/reflection_test.rb +194 -0
  135. data/test/cases/reload_models_test.rb +22 -0
  136. data/test/cases/repair_helper.rb +50 -0
  137. data/test/cases/reserved_word_test_mysql.rb +176 -0
  138. data/test/cases/sanitize_test.rb +25 -0
  139. data/test/cases/schema_authorization_test_postgresql.rb +75 -0
  140. data/test/cases/schema_dumper_test.rb +211 -0
  141. data/test/cases/schema_test_postgresql.rb +178 -0
  142. data/test/cases/serialization_test.rb +47 -0
  143. data/test/cases/synonym_test_oracle.rb +17 -0
  144. data/test/cases/timestamp_test.rb +75 -0
  145. data/test/cases/transactions_test.rb +522 -0
  146. data/test/cases/unconnected_test.rb +32 -0
  147. data/test/cases/validations_i18n_test.rb +955 -0
  148. data/test/cases/validations_test.rb +1640 -0
  149. data/test/cases/xml_serialization_test.rb +240 -0
  150. data/test/config.rb +5 -0
  151. data/test/connections/jdbc_jdbcderby/connection.rb +18 -0
  152. data/test/connections/jdbc_jdbch2/connection.rb +18 -0
  153. data/test/connections/jdbc_jdbchsqldb/connection.rb +18 -0
  154. data/test/connections/jdbc_jdbcmysql/connection.rb +26 -0
  155. data/test/connections/jdbc_jdbcpostgresql/connection.rb +26 -0
  156. data/test/connections/jdbc_jdbcsqlite3/connection.rb +25 -0
  157. data/test/connections/native_db2/connection.rb +25 -0
  158. data/test/connections/native_firebird/connection.rb +26 -0
  159. data/test/connections/native_frontbase/connection.rb +27 -0
  160. data/test/connections/native_mysql/connection.rb +25 -0
  161. data/test/connections/native_openbase/connection.rb +21 -0
  162. data/test/connections/native_oracle/connection.rb +27 -0
  163. data/test/connections/native_postgresql/connection.rb +25 -0
  164. data/test/connections/native_sqlite/connection.rb +25 -0
  165. data/test/connections/native_sqlite3/connection.rb +25 -0
  166. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  167. data/test/connections/native_sybase/connection.rb +23 -0
  168. data/test/fixtures/accounts.yml +29 -0
  169. data/test/fixtures/all/developers.yml +0 -0
  170. data/test/fixtures/all/people.csv +0 -0
  171. data/test/fixtures/all/tasks.yml +0 -0
  172. data/test/fixtures/author_addresses.yml +5 -0
  173. data/test/fixtures/author_favorites.yml +4 -0
  174. data/test/fixtures/authors.yml +9 -0
  175. data/test/fixtures/binaries.yml +132 -0
  176. data/test/fixtures/books.yml +7 -0
  177. data/test/fixtures/categories/special_categories.yml +9 -0
  178. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  179. data/test/fixtures/categories.yml +14 -0
  180. data/test/fixtures/categories_ordered.yml +7 -0
  181. data/test/fixtures/categories_posts.yml +23 -0
  182. data/test/fixtures/categorizations.yml +17 -0
  183. data/test/fixtures/clubs.yml +6 -0
  184. data/test/fixtures/comments.yml +59 -0
  185. data/test/fixtures/companies.yml +56 -0
  186. data/test/fixtures/computers.yml +4 -0
  187. data/test/fixtures/courses.yml +7 -0
  188. data/test/fixtures/customers.yml +26 -0
  189. data/test/fixtures/developers.yml +21 -0
  190. data/test/fixtures/developers_projects.yml +17 -0
  191. data/test/fixtures/edges.yml +6 -0
  192. data/test/fixtures/entrants.yml +14 -0
  193. data/test/fixtures/fixture_database.sqlite3 +0 -0
  194. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  195. data/test/fixtures/fk_test_has_fk.yml +3 -0
  196. data/test/fixtures/fk_test_has_pk.yml +2 -0
  197. data/test/fixtures/funny_jokes.yml +10 -0
  198. data/test/fixtures/items.yml +4 -0
  199. data/test/fixtures/jobs.yml +7 -0
  200. data/test/fixtures/legacy_things.yml +3 -0
  201. data/test/fixtures/mateys.yml +4 -0
  202. data/test/fixtures/member_types.yml +6 -0
  203. data/test/fixtures/members.yml +6 -0
  204. data/test/fixtures/memberships.yml +20 -0
  205. data/test/fixtures/minimalistics.yml +2 -0
  206. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  207. data/test/fixtures/mixins.yml +29 -0
  208. data/test/fixtures/movies.yml +7 -0
  209. data/test/fixtures/naked/csv/accounts.csv +1 -0
  210. data/test/fixtures/naked/yml/accounts.yml +1 -0
  211. data/test/fixtures/naked/yml/companies.yml +1 -0
  212. data/test/fixtures/naked/yml/courses.yml +1 -0
  213. data/test/fixtures/organizations.yml +5 -0
  214. data/test/fixtures/owners.yml +7 -0
  215. data/test/fixtures/parrots.yml +27 -0
  216. data/test/fixtures/parrots_pirates.yml +7 -0
  217. data/test/fixtures/people.yml +15 -0
  218. data/test/fixtures/pets.yml +14 -0
  219. data/test/fixtures/pirates.yml +9 -0
  220. data/test/fixtures/posts.yml +52 -0
  221. data/test/fixtures/price_estimates.yml +7 -0
  222. data/test/fixtures/projects.yml +7 -0
  223. data/test/fixtures/readers.yml +9 -0
  224. data/test/fixtures/references.yml +17 -0
  225. data/test/fixtures/reserved_words/distinct.yml +5 -0
  226. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  227. data/test/fixtures/reserved_words/group.yml +14 -0
  228. data/test/fixtures/reserved_words/select.yml +8 -0
  229. data/test/fixtures/reserved_words/values.yml +7 -0
  230. data/test/fixtures/ships.yml +5 -0
  231. data/test/fixtures/sponsors.yml +9 -0
  232. data/test/fixtures/subscribers.yml +7 -0
  233. data/test/fixtures/subscriptions.yml +12 -0
  234. data/test/fixtures/taggings.yml +28 -0
  235. data/test/fixtures/tags.yml +7 -0
  236. data/test/fixtures/tasks.yml +7 -0
  237. data/test/fixtures/topics.yml +42 -0
  238. data/test/fixtures/toys.yml +4 -0
  239. data/test/fixtures/treasures.yml +10 -0
  240. data/test/fixtures/vertices.yml +4 -0
  241. data/test/fixtures/warehouse-things.yml +3 -0
  242. data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
  243. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  244. data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
  245. data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
  246. data/test/migrations/duplicate/3_foo.rb +7 -0
  247. data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
  248. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  249. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  250. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
  251. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
  252. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
  253. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
  254. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  255. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  256. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  257. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  258. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  259. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  260. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  261. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  262. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  263. data/test/models/author.rb +146 -0
  264. data/test/models/auto_id.rb +4 -0
  265. data/test/models/binary.rb +2 -0
  266. data/test/models/bird.rb +3 -0
  267. data/test/models/book.rb +4 -0
  268. data/test/models/categorization.rb +5 -0
  269. data/test/models/category.rb +34 -0
  270. data/test/models/citation.rb +6 -0
  271. data/test/models/club.rb +13 -0
  272. data/test/models/column_name.rb +3 -0
  273. data/test/models/comment.rb +29 -0
  274. data/test/models/company.rb +171 -0
  275. data/test/models/company_in_module.rb +61 -0
  276. data/test/models/computer.rb +3 -0
  277. data/test/models/contact.rb +16 -0
  278. data/test/models/contract.rb +5 -0
  279. data/test/models/course.rb +3 -0
  280. data/test/models/customer.rb +73 -0
  281. data/test/models/default.rb +2 -0
  282. data/test/models/developer.rb +101 -0
  283. data/test/models/edge.rb +5 -0
  284. data/test/models/entrant.rb +3 -0
  285. data/test/models/essay.rb +3 -0
  286. data/test/models/event.rb +3 -0
  287. data/test/models/guid.rb +2 -0
  288. data/test/models/item.rb +7 -0
  289. data/test/models/job.rb +5 -0
  290. data/test/models/joke.rb +3 -0
  291. data/test/models/keyboard.rb +3 -0
  292. data/test/models/legacy_thing.rb +3 -0
  293. data/test/models/matey.rb +4 -0
  294. data/test/models/member.rb +12 -0
  295. data/test/models/member_detail.rb +5 -0
  296. data/test/models/member_type.rb +3 -0
  297. data/test/models/membership.rb +9 -0
  298. data/test/models/minimalistic.rb +2 -0
  299. data/test/models/mixed_case_monkey.rb +3 -0
  300. data/test/models/movie.rb +5 -0
  301. data/test/models/order.rb +4 -0
  302. data/test/models/organization.rb +6 -0
  303. data/test/models/owner.rb +5 -0
  304. data/test/models/parrot.rb +16 -0
  305. data/test/models/person.rb +16 -0
  306. data/test/models/pet.rb +5 -0
  307. data/test/models/pirate.rb +70 -0
  308. data/test/models/post.rb +100 -0
  309. data/test/models/price_estimate.rb +3 -0
  310. data/test/models/project.rb +30 -0
  311. data/test/models/reader.rb +4 -0
  312. data/test/models/reference.rb +4 -0
  313. data/test/models/reply.rb +46 -0
  314. data/test/models/ship.rb +10 -0
  315. data/test/models/ship_part.rb +5 -0
  316. data/test/models/sponsor.rb +4 -0
  317. data/test/models/subject.rb +4 -0
  318. data/test/models/subscriber.rb +8 -0
  319. data/test/models/subscription.rb +4 -0
  320. data/test/models/tag.rb +7 -0
  321. data/test/models/tagging.rb +10 -0
  322. data/test/models/task.rb +3 -0
  323. data/test/models/topic.rb +80 -0
  324. data/test/models/toy.rb +6 -0
  325. data/test/models/treasure.rb +8 -0
  326. data/test/models/vertex.rb +9 -0
  327. data/test/models/warehouse_thing.rb +5 -0
  328. data/test/schema/mysql_specific_schema.rb +24 -0
  329. data/test/schema/postgresql_specific_schema.rb +114 -0
  330. data/test/schema/schema.rb +493 -0
  331. data/test/schema/schema2.rb +6 -0
  332. data/test/schema/sqlite_specific_schema.rb +25 -0
  333. metadata +420 -0
@@ -0,0 +1,834 @@
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/category'
8
+ require 'models/company'
9
+ require 'models/person'
10
+ require 'models/reader'
11
+ require 'models/owner'
12
+ require 'models/pet'
13
+ require 'models/reference'
14
+ require 'models/job'
15
+ require 'models/subscriber'
16
+ require 'models/subscription'
17
+ require 'models/book'
18
+ require 'models/developer'
19
+ require 'models/project'
20
+
21
+ class EagerAssociationTest < ActiveRecord::TestCase
22
+ fixtures :posts, :comments, :authors, :author_addresses, :categories, :categories_posts,
23
+ :companies, :accounts, :tags, :taggings, :people, :readers,
24
+ :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
25
+ :developers, :projects, :developers_projects
26
+
27
+ def test_loading_with_one_association
28
+ posts = Post.find(:all, :include => :comments)
29
+ post = posts.find { |p| p.id == 1 }
30
+ assert_equal 2, post.comments.size
31
+ assert post.comments.include?(comments(:greetings))
32
+
33
+ post = Post.find(:first, :include => :comments, :conditions => "posts.title = 'Welcome to the weblog'")
34
+ assert_equal 2, post.comments.size
35
+ assert post.comments.include?(comments(:greetings))
36
+
37
+ posts = Post.find(:all, :include => :last_comment)
38
+ post = posts.find { |p| p.id == 1 }
39
+ assert_equal Post.find(1).last_comment, post.last_comment
40
+ end
41
+
42
+ def test_loading_with_one_association_with_non_preload
43
+ posts = Post.find(:all, :include => :last_comment, :order => 'comments.id DESC')
44
+ post = posts.find { |p| p.id == 1 }
45
+ assert_equal Post.find(1).last_comment, post.last_comment
46
+ end
47
+
48
+ def test_loading_conditions_with_or
49
+ posts = authors(:david).posts.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'")
50
+ assert_nil posts.detect { |p| p.author_id != authors(:david).id },
51
+ "expected to find only david's posts"
52
+ end
53
+
54
+ def test_with_ordering
55
+ list = Post.find(:all, :include => :comments, :order => "posts.id DESC")
56
+ [:eager_other, :sti_habtm, :sti_post_and_comments, :sti_comments,
57
+ :authorless, :thinking, :welcome
58
+ ].each_with_index do |post, index|
59
+ assert_equal posts(post), list[index]
60
+ end
61
+ end
62
+
63
+ def test_with_two_tables_in_from_without_getting_double_quoted
64
+ posts = Post.find(:all,
65
+ :select => "posts.*",
66
+ :from => "authors, posts",
67
+ :include => :comments,
68
+ :conditions => "posts.author_id = authors.id",
69
+ :order => "posts.id"
70
+ )
71
+
72
+ assert_equal 2, posts.first.comments.size
73
+ end
74
+
75
+ def test_loading_with_multiple_associations
76
+ posts = Post.find(:all, :include => [ :comments, :author, :categories ], :order => "posts.id")
77
+ assert_equal 2, posts.first.comments.size
78
+ assert_equal 2, posts.first.categories.size
79
+ assert posts.first.comments.include?(comments(:greetings))
80
+ end
81
+
82
+ def test_duplicate_middle_objects
83
+ comments = Comment.find :all, :conditions => 'post_id = 1', :include => [:post => :author]
84
+ assert_no_queries do
85
+ comments.each {|comment| comment.post.author.name}
86
+ end
87
+ end
88
+
89
+ def test_including_duplicate_objects_from_belongs_to
90
+ popular_post = Post.create!(:title => 'foo', :body => "I like cars!")
91
+ comment = popular_post.comments.create!(:body => "lol")
92
+ popular_post.readers.create!(:person => people(:michael))
93
+ popular_post.readers.create!(:person => people(:david))
94
+
95
+ readers = Reader.find(:all, :conditions => ["post_id = ?", popular_post.id],
96
+ :include => {:post => :comments})
97
+ readers.each do |reader|
98
+ assert_equal [comment], reader.post.comments
99
+ end
100
+ end
101
+
102
+ def test_including_duplicate_objects_from_has_many
103
+ car_post = Post.create!(:title => 'foo', :body => "I like cars!")
104
+ car_post.categories << categories(:general)
105
+ car_post.categories << categories(:technology)
106
+
107
+ comment = car_post.comments.create!(:body => "hmm")
108
+ categories = Category.find(:all, :conditions => ["posts.id=?", car_post.id],
109
+ :include => {:posts => :comments})
110
+ categories.each do |category|
111
+ assert_equal [comment], category.posts[0].comments
112
+ end
113
+ end
114
+
115
+ def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
116
+ author_id = authors(:david).id
117
+ author = assert_queries(3) { Author.find(author_id, :include => {:posts_with_comments => :comments}) } # find the author, then find the posts, then find the comments
118
+ author.posts_with_comments.each do |post_with_comments|
119
+ assert_equal post_with_comments.comments.length, post_with_comments.comments.count
120
+ assert_equal nil, post_with_comments.comments.uniq!
121
+ end
122
+ end
123
+
124
+ def test_finding_with_includes_on_has_one_assocation_with_same_include_includes_only_once
125
+ author = authors(:david)
126
+ post = author.post_about_thinking_with_last_comment
127
+ last_comment = post.last_comment
128
+ author = assert_queries(3) { Author.find(author.id, :include => {:post_about_thinking_with_last_comment => :last_comment})} # find the author, then find the posts, then find the comments
129
+ assert_no_queries do
130
+ assert_equal post, author.post_about_thinking_with_last_comment
131
+ assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
132
+ end
133
+ end
134
+
135
+ def test_finding_with_includes_on_belongs_to_association_with_same_include_includes_only_once
136
+ post = posts(:welcome)
137
+ author = post.author
138
+ author_address = author.author_address
139
+ post = assert_queries(3) { Post.find(post.id, :include => {:author_with_address => :author_address}) } # find the post, then find the author, then find the address
140
+ assert_no_queries do
141
+ assert_equal author, post.author_with_address
142
+ assert_equal author_address, post.author_with_address.author_address
143
+ end
144
+ end
145
+
146
+ def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
147
+ post = posts(:welcome)
148
+ post.update_attributes!(:author => nil)
149
+ post = assert_queries(1) { Post.find(post.id, :include => {:author_with_address => :author_address}) } # find the post, then find the author which is null so no query for the author or address
150
+ assert_no_queries do
151
+ assert_equal nil, post.author_with_address
152
+ end
153
+ end
154
+
155
+ def test_loading_from_an_association
156
+ posts = authors(:david).posts.find(:all, :include => :comments, :order => "posts.id")
157
+ assert_equal 2, posts.first.comments.size
158
+ end
159
+
160
+ def test_loading_from_an_association_that_has_a_hash_of_conditions
161
+ assert_nothing_raised do
162
+ Author.find(:all, :include => :hello_posts_with_hash_conditions)
163
+ end
164
+ assert !Author.find(authors(:david).id, :include => :hello_posts_with_hash_conditions).hello_posts.empty?
165
+ end
166
+
167
+ def test_loading_with_no_associations
168
+ assert_nil Post.find(posts(:authorless).id, :include => :author).author
169
+ end
170
+
171
+ def test_nested_loading_with_no_associations
172
+ assert_nothing_raised do
173
+ Post.find(posts(:authorless).id, :include => {:author => :author_addresss})
174
+ end
175
+ end
176
+
177
+ def test_eager_association_loading_with_belongs_to_and_foreign_keys
178
+ pets = Pet.find(:all, :include => :owner)
179
+ assert_equal 3, pets.length
180
+ end
181
+
182
+ def test_eager_association_loading_with_belongs_to
183
+ comments = Comment.find(:all, :include => :post)
184
+ assert_equal 10, comments.length
185
+ titles = comments.map { |c| c.post.title }
186
+ assert titles.include?(posts(:welcome).title)
187
+ assert titles.include?(posts(:sti_post_and_comments).title)
188
+ end
189
+
190
+ def test_eager_association_loading_with_belongs_to_and_limit
191
+ comments = Comment.find(:all, :include => :post, :limit => 5, :order => 'comments.id')
192
+ assert_equal 5, comments.length
193
+ assert_equal [1,2,3,5,6], comments.collect { |c| c.id }
194
+ end
195
+
196
+ def test_eager_association_loading_with_belongs_to_and_limit_and_conditions
197
+ comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :order => 'comments.id')
198
+ assert_equal 3, comments.length
199
+ assert_equal [5,6,7], comments.collect { |c| c.id }
200
+ end
201
+
202
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset
203
+ comments = Comment.find(:all, :include => :post, :limit => 3, :offset => 2, :order => 'comments.id')
204
+ assert_equal 3, comments.length
205
+ assert_equal [3,5,6], comments.collect { |c| c.id }
206
+ end
207
+
208
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions
209
+ comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id')
210
+ assert_equal 3, comments.length
211
+ assert_equal [6,7,8], comments.collect { |c| c.id }
212
+ end
213
+
214
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array
215
+ comments = Comment.find(:all, :include => :post, :conditions => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id')
216
+ assert_equal 3, comments.length
217
+ assert_equal [6,7,8], comments.collect { |c| c.id }
218
+ end
219
+
220
+ def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
221
+ assert_nothing_raised do
222
+ Comment.find(:all, :include => :post, :conditions => ['posts.id = ?',4])
223
+ end
224
+ end
225
+
226
+ def test_eager_association_loading_with_belongs_to_and_conditions_hash
227
+ comments = []
228
+ assert_nothing_raised do
229
+ comments = Comment.find(:all, :include => :post, :conditions => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id')
230
+ end
231
+ assert_equal 3, comments.length
232
+ assert_equal [5,6,7], comments.collect { |c| c.id }
233
+ assert_no_queries do
234
+ comments.first.post
235
+ end
236
+ end
237
+
238
+ def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
239
+ quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
240
+ assert_nothing_raised do
241
+ Comment.find(:all, :include => :post, :conditions => ["#{quoted_posts_id} = ?",4])
242
+ end
243
+ end
244
+
245
+ def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
246
+ assert_nothing_raised do
247
+ Comment.find(:all, :include => :post, :order => 'posts.id')
248
+ end
249
+ end
250
+
251
+ def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name
252
+ quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
253
+ assert_nothing_raised do
254
+ Comment.find(:all, :include => :post, :order => quoted_posts_id)
255
+ end
256
+ end
257
+
258
+ def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations
259
+ posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :order => 'posts.id')
260
+ assert_equal 1, posts.length
261
+ assert_equal [1], posts.collect { |p| p.id }
262
+ end
263
+
264
+ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations
265
+ posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id')
266
+ assert_equal 1, posts.length
267
+ assert_equal [2], posts.collect { |p| p.id }
268
+ end
269
+
270
+ def test_eager_association_loading_with_belongs_to_inferred_foreign_key_from_association_name
271
+ author_favorite = AuthorFavorite.find(:first, :include => :favorite_author)
272
+ assert_equal authors(:mary), assert_no_queries { author_favorite.favorite_author }
273
+ end
274
+
275
+ def test_eager_load_belongs_to_quotes_table_and_column_names
276
+ job = Job.find jobs(:unicyclist).id, :include => :ideal_reference
277
+ references(:michael_unicyclist)
278
+ assert_no_queries{ assert_equal references(:michael_unicyclist), job.ideal_reference}
279
+ end
280
+
281
+ def test_eager_load_has_one_quotes_table_and_column_names
282
+ michael = Person.find(people(:michael), :include => :favourite_reference)
283
+ references(:michael_unicyclist)
284
+ assert_no_queries{ assert_equal references(:michael_unicyclist), michael.favourite_reference}
285
+ end
286
+
287
+ def test_eager_load_has_many_quotes_table_and_column_names
288
+ michael = Person.find(people(:michael), :include => :references)
289
+ references(:michael_magician,:michael_unicyclist)
290
+ assert_no_queries{ assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) }
291
+ end
292
+
293
+ def test_eager_load_has_many_through_quotes_table_and_column_names
294
+ michael = Person.find(people(:michael), :include => :jobs)
295
+ jobs(:magician, :unicyclist)
296
+ assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
297
+ end
298
+
299
+ def test_eager_load_has_many_with_string_keys
300
+ subscriptions = subscriptions(:webster_awdr, :webster_rfr)
301
+ subscriber =Subscriber.find(subscribers(:second).id, :include => :subscriptions)
302
+ assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
303
+ end
304
+
305
+ def test_eager_load_has_many_through_with_string_keys
306
+ books = books(:awdr, :rfr)
307
+ subscriber = Subscriber.find(subscribers(:second).id, :include => :books)
308
+ assert_equal books, subscriber.books.sort_by(&:id)
309
+ end
310
+
311
+ def test_eager_load_belongs_to_with_string_keys
312
+ subscriber = subscribers(:second)
313
+ subscription = Subscription.find(subscriptions(:webster_awdr).id, :include => :subscriber)
314
+ assert_equal subscriber, subscription.subscriber
315
+ end
316
+
317
+ def test_eager_association_loading_with_explicit_join
318
+ posts = Post.find(:all, :include => :comments, :joins => "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", :limit => 1, :order => 'author_id')
319
+ assert_equal 1, posts.length
320
+ end
321
+
322
+ def test_eager_with_has_many_through
323
+ posts_with_comments = people(:michael).posts.find(:all, :include => :comments, :order => 'posts.id')
324
+ posts_with_author = people(:michael).posts.find(:all, :include => :author, :order => 'posts.id')
325
+ posts_with_comments_and_author = people(:michael).posts.find(:all, :include => [ :comments, :author ], :order => 'posts.id')
326
+ assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum += post.comments.size }
327
+ assert_equal authors(:david), assert_no_queries { posts_with_author.first.author }
328
+ assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
329
+ end
330
+
331
+ def test_eager_with_has_many_through_a_belongs_to_association
332
+ author = authors(:mary)
333
+ post = Post.create!(:author => author, :title => "TITLE", :body => "BODY")
334
+ author.author_favorites.create(:favorite_author_id => 1)
335
+ author.author_favorites.create(:favorite_author_id => 2)
336
+ posts_with_author_favorites = author.posts.find(:all, :include => :author_favorites)
337
+ assert_no_queries { posts_with_author_favorites.first.author_favorites.first.author_id }
338
+ end
339
+
340
+ def test_eager_with_has_many_through_an_sti_join_model
341
+ author = Author.find(:first, :include => :special_post_comments, :order => 'authors.id')
342
+ assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }
343
+ end
344
+
345
+ def test_eager_with_has_many_through_an_sti_join_model_with_conditions_on_both
346
+ author = Author.find(:first, :include => :special_nonexistant_post_comments, :order => 'authors.id')
347
+ assert_equal [], author.special_nonexistant_post_comments
348
+ end
349
+
350
+ def test_eager_with_has_many_through_join_model_with_conditions
351
+ assert_equal Author.find(:first, :include => :hello_post_comments,
352
+ :order => 'authors.id').hello_post_comments.sort_by(&:id),
353
+ Author.find(:first, :order => 'authors.id').hello_post_comments.sort_by(&:id)
354
+ end
355
+
356
+ def test_eager_with_has_many_through_join_model_with_conditions_on_top_level
357
+ assert_equal comments(:more_greetings), Author.find(authors(:david).id, :include => :comments_with_order_and_conditions).comments_with_order_and_conditions.first
358
+ end
359
+
360
+ def test_eager_with_has_many_through_join_model_with_include
361
+ author_comments = Author.find(authors(:david).id, :include => :comments_with_include).comments_with_include.to_a
362
+ assert_no_queries do
363
+ author_comments.first.post.title
364
+ end
365
+ end
366
+
367
+ def test_eager_with_has_many_and_limit
368
+ posts = Post.find(:all, :order => 'posts.id asc', :include => [ :author, :comments ], :limit => 2)
369
+ assert_equal 2, posts.size
370
+ assert_equal 3, posts.inject(0) { |sum, post| sum += post.comments.size }
371
+ end
372
+
373
+ def test_eager_with_has_many_and_limit_and_conditions
374
+ if current_adapter?(:OpenBaseAdapter)
375
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "FETCHBLOB(posts.body) = 'hello'", :order => "posts.id")
376
+ else
377
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.body = 'hello'", :order => "posts.id")
378
+ end
379
+ assert_equal 2, posts.size
380
+ assert_equal [4,5], posts.collect { |p| p.id }
381
+ end
382
+
383
+ def test_eager_with_has_many_and_limit_and_conditions_array
384
+ if current_adapter?(:OpenBaseAdapter)
385
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "FETCHBLOB(posts.body) = ?", 'hello' ], :order => "posts.id")
386
+ else
387
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "posts.body = ?", 'hello' ], :order => "posts.id")
388
+ end
389
+ assert_equal 2, posts.size
390
+ assert_equal [4,5], posts.collect { |p| p.id }
391
+ end
392
+
393
+ def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
394
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
395
+ assert_equal 2, posts.size
396
+
397
+ count = Post.count(:include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
398
+ assert_equal count, posts.size
399
+ end
400
+
401
+ def test_eager_with_has_many_and_limit_and_high_offset
402
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
403
+ assert_equal 0, posts.size
404
+ end
405
+
406
+ def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
407
+ assert_queries(1) do
408
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
409
+ :conditions => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ])
410
+ assert_equal 0, posts.size
411
+ end
412
+ end
413
+
414
+ def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
415
+ assert_queries(1) do
416
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
417
+ :conditions => { 'authors.name' => 'David', 'comments.body' => 'go crazy' })
418
+ assert_equal 0, posts.size
419
+ end
420
+ end
421
+
422
+ def test_count_eager_with_has_many_and_limit_and_high_offset
423
+ posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
424
+ assert_equal 0, posts
425
+ end
426
+
427
+ def test_eager_with_has_many_and_limit_with_no_results
428
+ posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'")
429
+ assert_equal 0, posts.size
430
+ end
431
+
432
+ def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
433
+ author = authors(:david)
434
+ author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
435
+ assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null')
436
+ end
437
+
438
+ def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
439
+ person = people(:michael)
440
+ person_posts_without_comments = person.posts.select { |post| post.comments.blank? }
441
+ assert_equal person_posts_without_comments.size, person.posts_with_no_comments.count
442
+ end
443
+
444
+ def test_eager_with_has_and_belongs_to_many_and_limit
445
+ posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3)
446
+ assert_equal 3, posts.size
447
+ assert_equal 2, posts[0].categories.size
448
+ assert_equal 1, posts[1].categories.size
449
+ assert_equal 0, posts[2].categories.size
450
+ assert posts[0].categories.include?(categories(:technology))
451
+ assert posts[1].categories.include?(categories(:general))
452
+ end
453
+
454
+ def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
455
+ posts = authors(:david).posts.find(:all,
456
+ :include => :comments,
457
+ :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
458
+ :limit => 2
459
+ )
460
+ assert_equal 2, posts.size
461
+
462
+ count = Post.count(
463
+ :include => [ :comments, :author ],
464
+ :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
465
+ :limit => 2
466
+ )
467
+ assert_equal count, posts.size
468
+ end
469
+
470
+ def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
471
+ posts = nil
472
+ Post.with_scope(:find => {
473
+ :include => :comments,
474
+ :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'"
475
+ }) do
476
+ posts = authors(:david).posts.find(:all, :limit => 2)
477
+ assert_equal 2, posts.size
478
+ end
479
+
480
+ Post.with_scope(:find => {
481
+ :include => [ :comments, :author ],
482
+ :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')"
483
+ }) do
484
+ count = Post.count(:limit => 2)
485
+ assert_equal count, posts.size
486
+ end
487
+ end
488
+
489
+ def test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the_eagers
490
+ Post.with_scope(:find => { :conditions => "1=1" }) do
491
+ posts = authors(:david).posts.find(:all,
492
+ :include => :comments,
493
+ :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
494
+ :limit => 2
495
+ )
496
+ assert_equal 2, posts.size
497
+
498
+ count = Post.count(
499
+ :include => [ :comments, :author ],
500
+ :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
501
+ :limit => 2
502
+ )
503
+ assert_equal count, posts.size
504
+ end
505
+ end
506
+
507
+ def test_eager_with_scoped_order_using_association_limiting_without_explicit_scope
508
+ posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :order => 'posts.id DESC', :limit => 2)
509
+ posts_with_scoped_order = Post.with_scope(:find => {:order => 'posts.id DESC'}) do
510
+ Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :limit => 2)
511
+ end
512
+ assert_equal posts_with_explicit_order, posts_with_scoped_order
513
+ end
514
+
515
+ def test_eager_association_loading_with_habtm
516
+ posts = Post.find(:all, :include => :categories, :order => "posts.id")
517
+ assert_equal 2, posts[0].categories.size
518
+ assert_equal 1, posts[1].categories.size
519
+ assert_equal 0, posts[2].categories.size
520
+ assert posts[0].categories.include?(categories(:technology))
521
+ assert posts[1].categories.include?(categories(:general))
522
+ end
523
+
524
+ def test_eager_with_inheritance
525
+ posts = SpecialPost.find(:all, :include => [ :comments ])
526
+ end
527
+
528
+ def test_eager_has_one_with_association_inheritance
529
+ post = Post.find(4, :include => [ :very_special_comment ])
530
+ assert_equal "VerySpecialComment", post.very_special_comment.class.to_s
531
+ end
532
+
533
+ def test_eager_has_many_with_association_inheritance
534
+ post = Post.find(4, :include => [ :special_comments ])
535
+ post.special_comments.each do |special_comment|
536
+ assert_equal "SpecialComment", special_comment.class.to_s
537
+ end
538
+ end
539
+
540
+ def test_eager_habtm_with_association_inheritance
541
+ post = Post.find(6, :include => [ :special_categories ])
542
+ assert_equal 1, post.special_categories.size
543
+ post.special_categories.each do |special_category|
544
+ assert_equal "SpecialCategory", special_category.class.to_s
545
+ end
546
+ end
547
+
548
+ def test_eager_with_has_one_dependent_does_not_destroy_dependent
549
+ assert_not_nil companies(:first_firm).account
550
+ f = Firm.find(:first, :include => :account,
551
+ :conditions => ["companies.name = ?", "37signals"])
552
+ assert_not_nil f.account
553
+ assert_equal companies(:first_firm, :reload).account, f.account
554
+ end
555
+
556
+ def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size
557
+ author = authors(:david)
558
+ posts_with_no_comments = author.posts.select { |post| post.comments.blank? }
559
+ assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size
560
+ assert_equal posts_with_no_comments, author.posts_with_no_comments
561
+ end
562
+
563
+ def test_eager_with_invalid_association_reference
564
+ assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
565
+ post = Post.find(6, :include=> :monkeys )
566
+ }
567
+ assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
568
+ post = Post.find(6, :include=>[ :monkeys ])
569
+ }
570
+ assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
571
+ post = Post.find(6, :include=>[ 'monkeys' ])
572
+ }
573
+ assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
574
+ post = Post.find(6, :include=>[ :monkeys, :elephants ])
575
+ }
576
+ end
577
+
578
+ def find_all_ordered(className, include=nil)
579
+ className.find(:all, :order=>"#{className.table_name}.#{className.primary_key}", :include=>include)
580
+ end
581
+
582
+ def test_limited_eager_with_order
583
+ assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title)', :limit => 2, :offset => 1)
584
+ assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1)
585
+ end
586
+
587
+ def test_limited_eager_with_multiple_order_columns
588
+ assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title), posts.id', :limit => 2, :offset => 1)
589
+ assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1)
590
+ end
591
+
592
+ def test_preload_with_interpolation
593
+ assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions
594
+ end
595
+
596
+ def test_polymorphic_type_condition
597
+ post = Post.find(posts(:thinking).id, :include => :taggings)
598
+ assert post.taggings.include?(taggings(:thinking_general))
599
+ post = SpecialPost.find(posts(:thinking).id, :include => :taggings)
600
+ assert post.taggings.include?(taggings(:thinking_general))
601
+ end
602
+
603
+ def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm
604
+ # Eager includes of has many and habtm associations aren't necessarily sorted in the same way
605
+ def assert_equal_after_sort(item1, item2, item3 = nil)
606
+ assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id})
607
+ assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3
608
+ end
609
+ # Test regular association, association with conditions, association with
610
+ # STI, and association with conditions assured not to be true
611
+ post_types = [:posts, :other_posts, :special_posts]
612
+ # test both has_many and has_and_belongs_to_many
613
+ [Author, Category].each do |className|
614
+ d1 = find_all_ordered(className)
615
+ # test including all post types at once
616
+ d2 = find_all_ordered(className, post_types)
617
+ d1.each_index do |i|
618
+ assert_equal(d1[i], d2[i])
619
+ assert_equal_after_sort(d1[i].posts, d2[i].posts)
620
+ post_types[1..-1].each do |post_type|
621
+ # test including post_types together
622
+ d3 = find_all_ordered(className, [:posts, post_type])
623
+ assert_equal(d1[i], d3[i])
624
+ assert_equal_after_sort(d1[i].posts, d3[i].posts)
625
+ assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type))
626
+ end
627
+ end
628
+ end
629
+ end
630
+
631
+ def test_eager_with_multiple_associations_with_same_table_has_one
632
+ d1 = find_all_ordered(Firm)
633
+ d2 = find_all_ordered(Firm, :account)
634
+ d1.each_index do |i|
635
+ assert_equal(d1[i], d2[i])
636
+ assert_equal(d1[i].account, d2[i].account)
637
+ end
638
+ end
639
+
640
+ def test_eager_with_multiple_associations_with_same_table_belongs_to
641
+ firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition]
642
+ d1 = find_all_ordered(Client)
643
+ d2 = find_all_ordered(Client, firm_types)
644
+ d1.each_index do |i|
645
+ assert_equal(d1[i], d2[i])
646
+ firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) }
647
+ end
648
+ end
649
+ def test_eager_with_valid_association_as_string_not_symbol
650
+ assert_nothing_raised { Post.find(:all, :include => 'comments') }
651
+ end
652
+
653
+ def test_eager_with_floating_point_numbers
654
+ assert_queries(2) do
655
+ # Before changes, the floating point numbers will be interpreted as table names and will cause this to run in one query
656
+ Comment.find :all, :conditions => "123.456 = 123.456", :include => :post
657
+ end
658
+ end
659
+
660
+ def test_preconfigured_includes_with_belongs_to
661
+ author = posts(:welcome).author_with_posts
662
+ assert_no_queries {assert_equal 5, author.posts.size}
663
+ end
664
+
665
+ def test_preconfigured_includes_with_has_one
666
+ comment = posts(:sti_comments).very_special_comment_with_post
667
+ assert_no_queries {assert_equal posts(:sti_comments), comment.post}
668
+ end
669
+
670
+ def test_preconfigured_includes_with_has_many
671
+ posts = authors(:david).posts_with_comments
672
+ one = posts.detect { |p| p.id == 1 }
673
+ assert_no_queries do
674
+ assert_equal 5, posts.size
675
+ assert_equal 2, one.comments.size
676
+ end
677
+ end
678
+
679
+ def test_preconfigured_includes_with_habtm
680
+ posts = authors(:david).posts_with_categories
681
+ one = posts.detect { |p| p.id == 1 }
682
+ assert_no_queries do
683
+ assert_equal 5, posts.size
684
+ assert_equal 2, one.categories.size
685
+ end
686
+ end
687
+
688
+ def test_preconfigured_includes_with_has_many_and_habtm
689
+ posts = authors(:david).posts_with_comments_and_categories
690
+ one = posts.detect { |p| p.id == 1 }
691
+ assert_no_queries do
692
+ assert_equal 5, posts.size
693
+ assert_equal 2, one.comments.size
694
+ assert_equal 2, one.categories.size
695
+ end
696
+ end
697
+
698
+ def test_count_with_include
699
+ if current_adapter?(:SybaseAdapter)
700
+ assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "len(comments.body) > 15")
701
+ elsif current_adapter?(:OpenBaseAdapter)
702
+ assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(FETCHBLOB(comments.body)) > 15")
703
+ else
704
+ assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15")
705
+ end
706
+ end
707
+
708
+ def test_load_with_sti_sharing_association
709
+ assert_queries(2) do #should not do 1 query per subclass
710
+ Comment.find :all, :include => :post
711
+ end
712
+ end
713
+
714
+ def test_conditions_on_join_table_with_include_and_limit
715
+ assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size
716
+ end
717
+
718
+ def test_order_on_join_table_with_include_and_limit
719
+ assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
720
+ end
721
+
722
+ def test_eager_loading_with_order_on_joined_table_preloads
723
+ posts = assert_queries(2) do
724
+ Post.find(:all, :joins => :comments, :include => :author, :order => 'comments.id DESC')
725
+ end
726
+ assert_equal posts(:eager_other), posts[0]
727
+ assert_equal authors(:mary), assert_no_queries { posts[0].author}
728
+ end
729
+
730
+ def test_eager_loading_with_conditions_on_joined_table_preloads
731
+ posts = assert_queries(2) do
732
+ Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
733
+ end
734
+ assert_equal [posts(:welcome)], posts
735
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
736
+
737
+ posts = assert_queries(2) do
738
+ Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
739
+ end
740
+ assert_equal [posts(:welcome)], posts
741
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
742
+
743
+ posts = assert_queries(2) do
744
+ Post.find(:all, :include => :author, :joins => {:taggings => :tag}, :conditions => "tags.name = 'General'", :order => 'posts.id')
745
+ end
746
+ assert_equal posts(:welcome, :thinking), posts
747
+
748
+ posts = assert_queries(2) do
749
+ Post.find(:all, :include => :author, :joins => {:taggings => {:tag => :taggings}}, :conditions => "taggings_tags.super_tag_id=2", :order => 'posts.id')
750
+ end
751
+ assert_equal posts(:welcome, :thinking), posts
752
+
753
+ end
754
+
755
+ def test_eager_loading_with_conditions_on_string_joined_table_preloads
756
+ posts = assert_queries(2) do
757
+ Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
758
+ end
759
+ assert_equal [posts(:welcome)], posts
760
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
761
+
762
+ posts = assert_queries(2) do
763
+ Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
764
+ end
765
+ assert_equal [posts(:welcome)], posts
766
+ assert_equal authors(:david), assert_no_queries { posts[0].author}
767
+
768
+ end
769
+
770
+ def test_eager_loading_with_select_on_joined_table_preloads
771
+ posts = assert_queries(2) do
772
+ Post.find(:all, :select => 'posts.*, authors.name as author_name', :include => :comments, :joins => :author, :order => 'posts.id')
773
+ end
774
+ assert_equal 'David', posts[0].author_name
775
+ assert_equal posts(:welcome).comments, assert_no_queries { posts[0].comments}
776
+ end
777
+
778
+ def test_eager_loading_with_conditions_on_join_model_preloads
779
+ authors = assert_queries(2) do
780
+ Author.find(:all, :include => :author_address, :joins => :comments, :conditions => "posts.title like 'Welcome%'")
781
+ end
782
+ assert_equal authors(:david), authors[0]
783
+ assert_equal author_addresses(:david_address), authors[0].author_address
784
+ end
785
+
786
+ def test_preload_belongs_to_uses_exclusive_scope
787
+ people = Person.males.find(:all, :include => :primary_contact)
788
+ assert_not_equal people.length, 0
789
+ people.each do |person|
790
+ assert_no_queries {assert_not_nil person.primary_contact}
791
+ assert_equal Person.find(person.id).primary_contact, person.primary_contact
792
+ end
793
+ end
794
+
795
+ def test_preload_has_many_uses_exclusive_scope
796
+ people = Person.males.find :all, :include => :agents
797
+ people.each do |person|
798
+ assert_equal Person.find(person.id).agents, person.agents
799
+ end
800
+ end
801
+
802
+ def test_preload_has_many_using_primary_key
803
+ expected = Firm.find(:first).clients_using_primary_key.to_a
804
+ firm = Firm.find :first, :include => :clients_using_primary_key
805
+ assert_no_queries do
806
+ assert_equal expected, firm.clients_using_primary_key
807
+ end
808
+ end
809
+
810
+ def test_include_has_many_using_primary_key
811
+ expected = Firm.find(1).clients_using_primary_key.sort_by &:name
812
+ firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name'
813
+ assert_no_queries do
814
+ assert_equal expected, firm.clients_using_primary_key
815
+ end
816
+ end
817
+
818
+ def test_preload_has_one_using_primary_key
819
+ expected = Firm.find(:first).account_using_primary_key
820
+ firm = Firm.find :first, :include => :account_using_primary_key
821
+ assert_no_queries do
822
+ assert_equal expected, firm.account_using_primary_key
823
+ end
824
+ end
825
+
826
+ def test_include_has_one_using_primary_key
827
+ expected = Firm.find(1).account_using_primary_key
828
+ firm = Firm.find(:all, :include => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1}
829
+ assert_no_queries do
830
+ assert_equal expected, firm.account_using_primary_key
831
+ end
832
+ end
833
+
834
+ end