Froze rails gems
[depot.git] / vendor / rails / activerecord / test / cases / associations / eager_test.rb
1 require "cases/helper"
2 require 'models/post'
3 require 'models/tagging'
4 require 'models/comment'
5 require 'models/author'
6 require 'models/category'
7 require 'models/company'
8 require 'models/person'
9 require 'models/reader'
10 require 'models/owner'
11 require 'models/pet'
12 require 'models/reference'
13 require 'models/job'
14 require 'models/subscriber'
15 require 'models/subscription'
16 require 'models/book'
17 require 'models/developer'
18 require 'models/project'
19
20 class EagerAssociationTest < ActiveRecord::TestCase
21 fixtures :posts, :comments, :authors, :author_addresses, :categories, :categories_posts,
22 :companies, :accounts, :tags, :taggings, :people, :readers,
23 :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
24 :developers, :projects, :developers_projects
25
26 def test_loading_with_one_association
27 posts = Post.find(:all, :include => :comments)
28 post = posts.find { |p| p.id == 1 }
29 assert_equal 2, post.comments.size
30 assert post.comments.include?(comments(:greetings))
31
32 post = Post.find(:first, :include => :comments, :conditions => "posts.title = 'Welcome to the weblog'")
33 assert_equal 2, post.comments.size
34 assert post.comments.include?(comments(:greetings))
35
36 posts = Post.find(:all, :include => :last_comment)
37 post = posts.find { |p| p.id == 1 }
38 assert_equal Post.find(1).last_comment, post.last_comment
39 end
40
41 def test_loading_with_one_association_with_non_preload
42 posts = Post.find(:all, :include => :last_comment, :order => 'comments.id DESC')
43 post = posts.find { |p| p.id == 1 }
44 assert_equal Post.find(1).last_comment, post.last_comment
45 end
46
47 def test_loading_conditions_with_or
48 posts = authors(:david).posts.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'")
49 assert_nil posts.detect { |p| p.author_id != authors(:david).id },
50 "expected to find only david's posts"
51 end
52
53 def test_with_ordering
54 list = Post.find(:all, :include => :comments, :order => "posts.id DESC")
55 [:eager_other, :sti_habtm, :sti_post_and_comments, :sti_comments,
56 :authorless, :thinking, :welcome
57 ].each_with_index do |post, index|
58 assert_equal posts(post), list[index]
59 end
60 end
61
62 def test_with_two_tables_in_from_without_getting_double_quoted
63 posts = Post.find(:all,
64 :select => "posts.*",
65 :from => "authors, posts",
66 :include => :comments,
67 :conditions => "posts.author_id = authors.id",
68 :order => "posts.id"
69 )
70
71 assert_equal 2, posts.first.comments.size
72 end
73
74 def test_loading_with_multiple_associations
75 posts = Post.find(:all, :include => [ :comments, :author, :categories ], :order => "posts.id")
76 assert_equal 2, posts.first.comments.size
77 assert_equal 2, posts.first.categories.size
78 assert posts.first.comments.include?(comments(:greetings))
79 end
80
81 def test_duplicate_middle_objects
82 comments = Comment.find :all, :conditions => 'post_id = 1', :include => [:post => :author]
83 assert_no_queries do
84 comments.each {|comment| comment.post.author.name}
85 end
86 end
87
88 def test_including_duplicate_objects_from_belongs_to
89 popular_post = Post.create!(:title => 'foo', :body => "I like cars!")
90 comment = popular_post.comments.create!(:body => "lol")
91 popular_post.readers.create!(:person => people(:michael))
92 popular_post.readers.create!(:person => people(:david))
93
94 readers = Reader.find(:all, :conditions => ["post_id = ?", popular_post.id],
95 :include => {:post => :comments})
96 readers.each do |reader|
97 assert_equal [comment], reader.post.comments
98 end
99 end
100
101 def test_including_duplicate_objects_from_has_many
102 car_post = Post.create!(:title => 'foo', :body => "I like cars!")
103 car_post.categories << categories(:general)
104 car_post.categories << categories(:technology)
105
106 comment = car_post.comments.create!(:body => "hmm")
107 categories = Category.find(:all, :conditions => ["posts.id=?", car_post.id],
108 :include => {:posts => :comments})
109 categories.each do |category|
110 assert_equal [comment], category.posts[0].comments
111 end
112 end
113
114 def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
115 author_id = authors(:david).id
116 author = assert_queries(3) { Author.find(author_id, :include => {:posts_with_comments => :comments}) } # find the author, then find the posts, then find the comments
117 author.posts_with_comments.each do |post_with_comments|
118 assert_equal post_with_comments.comments.length, post_with_comments.comments.count
119 assert_equal nil, post_with_comments.comments.uniq!
120 end
121 end
122
123 def test_finding_with_includes_on_has_one_assocation_with_same_include_includes_only_once
124 author = authors(:david)
125 post = author.post_about_thinking_with_last_comment
126 last_comment = post.last_comment
127 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
128 assert_no_queries do
129 assert_equal post, author.post_about_thinking_with_last_comment
130 assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
131 end
132 end
133
134 def test_finding_with_includes_on_belongs_to_association_with_same_include_includes_only_once
135 post = posts(:welcome)
136 author = post.author
137 author_address = author.author_address
138 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
139 assert_no_queries do
140 assert_equal author, post.author_with_address
141 assert_equal author_address, post.author_with_address.author_address
142 end
143 end
144
145 def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
146 post = posts(:welcome)
147 post.update_attributes!(:author => nil)
148 post = assert_queries(2) { 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 address
149 assert_no_queries do
150 assert_equal nil, post.author_with_address
151 end
152 end
153
154 def test_loading_from_an_association
155 posts = authors(:david).posts.find(:all, :include => :comments, :order => "posts.id")
156 assert_equal 2, posts.first.comments.size
157 end
158
159 def test_loading_from_an_association_that_has_a_hash_of_conditions
160 assert_nothing_raised do
161 Author.find(:all, :include => :hello_posts_with_hash_conditions)
162 end
163 assert !Author.find(authors(:david).id, :include => :hello_posts_with_hash_conditions).hello_posts.empty?
164 end
165
166 def test_loading_with_no_associations
167 assert_nil Post.find(posts(:authorless).id, :include => :author).author
168 end
169
170 def test_nested_loading_with_no_associations
171 assert_nothing_raised do
172 Post.find(posts(:authorless).id, :include => {:author => :author_addresss})
173 end
174 end
175
176 def test_eager_association_loading_with_belongs_to_and_foreign_keys
177 pets = Pet.find(:all, :include => :owner)
178 assert_equal 3, pets.length
179 end
180
181 def test_eager_association_loading_with_belongs_to
182 comments = Comment.find(:all, :include => :post)
183 assert_equal 10, comments.length
184 titles = comments.map { |c| c.post.title }
185 assert titles.include?(posts(:welcome).title)
186 assert titles.include?(posts(:sti_post_and_comments).title)
187 end
188
189 def test_eager_association_loading_with_belongs_to_and_limit
190 comments = Comment.find(:all, :include => :post, :limit => 5, :order => 'comments.id')
191 assert_equal 5, comments.length
192 assert_equal [1,2,3,5,6], comments.collect { |c| c.id }
193 end
194
195 def test_eager_association_loading_with_belongs_to_and_limit_and_conditions
196 comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :order => 'comments.id')
197 assert_equal 3, comments.length
198 assert_equal [5,6,7], comments.collect { |c| c.id }
199 end
200
201 def test_eager_association_loading_with_belongs_to_and_limit_and_offset
202 comments = Comment.find(:all, :include => :post, :limit => 3, :offset => 2, :order => 'comments.id')
203 assert_equal 3, comments.length
204 assert_equal [3,5,6], comments.collect { |c| c.id }
205 end
206
207 def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions
208 comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id')
209 assert_equal 3, comments.length
210 assert_equal [6,7,8], comments.collect { |c| c.id }
211 end
212
213 def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array
214 comments = Comment.find(:all, :include => :post, :conditions => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id')
215 assert_equal 3, comments.length
216 assert_equal [6,7,8], comments.collect { |c| c.id }
217 end
218
219 def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
220 assert_nothing_raised do
221 Comment.find(:all, :include => :post, :conditions => ['posts.id = ?',4])
222 end
223 end
224
225 def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
226 quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
227 assert_nothing_raised do
228 Comment.find(:all, :include => :post, :conditions => ["#{quoted_posts_id} = ?",4])
229 end
230 end
231
232 def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
233 assert_nothing_raised do
234 Comment.find(:all, :include => :post, :order => 'posts.id')
235 end
236 end
237
238 def test_eager_association_loading_with_belongs_to_and_order_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, :order => quoted_posts_id)
242 end
243 end
244
245 def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations
246 posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :order => 'posts.id')
247 assert_equal 1, posts.length
248 assert_equal [1], posts.collect { |p| p.id }
249 end
250
251 def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations
252 posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id')
253 assert_equal 1, posts.length
254 assert_equal [2], posts.collect { |p| p.id }
255 end
256
257 def test_eager_association_loading_with_belongs_to_inferred_foreign_key_from_association_name
258 author_favorite = AuthorFavorite.find(:first, :include => :favorite_author)
259 assert_equal authors(:mary), assert_no_queries { author_favorite.favorite_author }
260 end
261
262 def test_eager_load_belongs_to_quotes_table_and_column_names
263 job = Job.find jobs(:unicyclist).id, :include => :ideal_reference
264 references(:michael_unicyclist)
265 assert_no_queries{ assert_equal references(:michael_unicyclist), job.ideal_reference}
266 end
267
268 def test_eager_load_has_one_quotes_table_and_column_names
269 michael = Person.find(people(:michael), :include => :favourite_reference)
270 references(:michael_unicyclist)
271 assert_no_queries{ assert_equal references(:michael_unicyclist), michael.favourite_reference}
272 end
273
274 def test_eager_load_has_many_quotes_table_and_column_names
275 michael = Person.find(people(:michael), :include => :references)
276 references(:michael_magician,:michael_unicyclist)
277 assert_no_queries{ assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) }
278 end
279
280 def test_eager_load_has_many_through_quotes_table_and_column_names
281 michael = Person.find(people(:michael), :include => :jobs)
282 jobs(:magician, :unicyclist)
283 assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
284 end
285
286 def test_eager_load_has_many_with_string_keys
287 subscriptions = subscriptions(:webster_awdr, :webster_rfr)
288 subscriber =Subscriber.find(subscribers(:second).id, :include => :subscriptions)
289 assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
290 end
291
292 def test_eager_load_has_many_through_with_string_keys
293 books = books(:awdr, :rfr)
294 subscriber = Subscriber.find(subscribers(:second).id, :include => :books)
295 assert_equal books, subscriber.books.sort_by(&:id)
296 end
297
298 def test_eager_load_belongs_to_with_string_keys
299 subscriber = subscribers(:second)
300 subscription = Subscription.find(subscriptions(:webster_awdr).id, :include => :subscriber)
301 assert_equal subscriber, subscription.subscriber
302 end
303
304 def test_eager_association_loading_with_explicit_join
305 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')
306 assert_equal 1, posts.length
307 end
308
309 def test_eager_with_has_many_through
310 posts_with_comments = people(:michael).posts.find(:all, :include => :comments, :order => 'posts.id')
311 posts_with_author = people(:michael).posts.find(:all, :include => :author, :order => 'posts.id')
312 posts_with_comments_and_author = people(:michael).posts.find(:all, :include => [ :comments, :author ], :order => 'posts.id')
313 assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum += post.comments.size }
314 assert_equal authors(:david), assert_no_queries { posts_with_author.first.author }
315 assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
316 end
317
318 def test_eager_with_has_many_through_a_belongs_to_association
319 author = authors(:mary)
320 post = Post.create!(:author => author, :title => "TITLE", :body => "BODY")
321 author.author_favorites.create(:favorite_author_id => 1)
322 author.author_favorites.create(:favorite_author_id => 2)
323 posts_with_author_favorites = author.posts.find(:all, :include => :author_favorites)
324 assert_no_queries { posts_with_author_favorites.first.author_favorites.first.author_id }
325 end
326
327 def test_eager_with_has_many_through_an_sti_join_model
328 author = Author.find(:first, :include => :special_post_comments, :order => 'authors.id')
329 assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }
330 end
331
332 def test_eager_with_has_many_through_an_sti_join_model_with_conditions_on_both
333 author = Author.find(:first, :include => :special_nonexistant_post_comments, :order => 'authors.id')
334 assert_equal [], author.special_nonexistant_post_comments
335 end
336
337 def test_eager_with_has_many_through_join_model_with_conditions
338 assert_equal Author.find(:first, :include => :hello_post_comments,
339 :order => 'authors.id').hello_post_comments.sort_by(&:id),
340 Author.find(:first, :order => 'authors.id').hello_post_comments.sort_by(&:id)
341 end
342
343 def test_eager_with_has_many_through_join_model_with_conditions_on_top_level
344 assert_equal comments(:more_greetings), Author.find(authors(:david).id, :include => :comments_with_order_and_conditions).comments_with_order_and_conditions.first
345 end
346
347 def test_eager_with_has_many_through_join_model_with_include
348 author_comments = Author.find(authors(:david).id, :include => :comments_with_include).comments_with_include.to_a
349 assert_no_queries do
350 author_comments.first.post.title
351 end
352 end
353
354 def test_eager_with_has_many_and_limit
355 posts = Post.find(:all, :order => 'posts.id asc', :include => [ :author, :comments ], :limit => 2)
356 assert_equal 2, posts.size
357 assert_equal 3, posts.inject(0) { |sum, post| sum += post.comments.size }
358 end
359
360 def test_eager_with_has_many_and_limit_and_conditions
361 if current_adapter?(:OpenBaseAdapter)
362 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "FETCHBLOB(posts.body) = 'hello'", :order => "posts.id")
363 else
364 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.body = 'hello'", :order => "posts.id")
365 end
366 assert_equal 2, posts.size
367 assert_equal [4,5], posts.collect { |p| p.id }
368 end
369
370 def test_eager_with_has_many_and_limit_and_conditions_array
371 if current_adapter?(:OpenBaseAdapter)
372 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "FETCHBLOB(posts.body) = ?", 'hello' ], :order => "posts.id")
373 else
374 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "posts.body = ?", 'hello' ], :order => "posts.id")
375 end
376 assert_equal 2, posts.size
377 assert_equal [4,5], posts.collect { |p| p.id }
378 end
379
380 def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
381 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
382 assert_equal 2, posts.size
383
384 count = Post.count(:include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
385 assert_equal count, posts.size
386 end
387
388 def test_eager_with_has_many_and_limit_ond_high_offset
389 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
390 assert_equal 0, posts.size
391 end
392
393 def test_count_eager_with_has_many_and_limit_ond_high_offset
394 posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
395 assert_equal 0, posts
396 end
397
398 def test_eager_with_has_many_and_limit_with_no_results
399 posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'")
400 assert_equal 0, posts.size
401 end
402
403 def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
404 author = authors(:david)
405 author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
406 assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null')
407 end
408
409 def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
410 person = people(:michael)
411 person_posts_without_comments = person.posts.select { |post| post.comments.blank? }
412 assert_equal person_posts_without_comments.size, person.posts_with_no_comments.count
413 end
414
415 def test_eager_with_has_and_belongs_to_many_and_limit
416 posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3)
417 assert_equal 3, posts.size
418 assert_equal 2, posts[0].categories.size
419 assert_equal 1, posts[1].categories.size
420 assert_equal 0, posts[2].categories.size
421 assert posts[0].categories.include?(categories(:technology))
422 assert posts[1].categories.include?(categories(:general))
423 end
424
425 def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
426 posts = authors(:david).posts.find(:all,
427 :include => :comments,
428 :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
429 :limit => 2
430 )
431 assert_equal 2, posts.size
432
433 count = Post.count(
434 :include => [ :comments, :author ],
435 :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
436 :limit => 2
437 )
438 assert_equal count, posts.size
439 end
440
441 def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
442 posts = nil
443 Post.with_scope(:find => {
444 :include => :comments,
445 :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'"
446 }) do
447 posts = authors(:david).posts.find(:all, :limit => 2)
448 assert_equal 2, posts.size
449 end
450
451 Post.with_scope(:find => {
452 :include => [ :comments, :author ],
453 :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')"
454 }) do
455 count = Post.count(:limit => 2)
456 assert_equal count, posts.size
457 end
458 end
459
460 def test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the_eagers
461 Post.with_scope(:find => { :conditions => "1=1" }) do
462 posts = authors(:david).posts.find(:all,
463 :include => :comments,
464 :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
465 :limit => 2
466 )
467 assert_equal 2, posts.size
468
469 count = Post.count(
470 :include => [ :comments, :author ],
471 :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
472 :limit => 2
473 )
474 assert_equal count, posts.size
475 end
476 end
477
478 def test_eager_with_scoped_order_using_association_limiting_without_explicit_scope
479 posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :order => 'posts.id DESC', :limit => 2)
480 posts_with_scoped_order = Post.with_scope(:find => {:order => 'posts.id DESC'}) do
481 Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :limit => 2)
482 end
483 assert_equal posts_with_explicit_order, posts_with_scoped_order
484 end
485
486 def test_eager_association_loading_with_habtm
487 posts = Post.find(:all, :include => :categories, :order => "posts.id")
488 assert_equal 2, posts[0].categories.size
489 assert_equal 1, posts[1].categories.size
490 assert_equal 0, posts[2].categories.size
491 assert posts[0].categories.include?(categories(:technology))
492 assert posts[1].categories.include?(categories(:general))
493 end
494
495 def test_eager_with_inheritance
496 posts = SpecialPost.find(:all, :include => [ :comments ])
497 end
498
499 def test_eager_has_one_with_association_inheritance
500 post = Post.find(4, :include => [ :very_special_comment ])
501 assert_equal "VerySpecialComment", post.very_special_comment.class.to_s
502 end
503
504 def test_eager_has_many_with_association_inheritance
505 post = Post.find(4, :include => [ :special_comments ])
506 post.special_comments.each do |special_comment|
507 assert_equal "SpecialComment", special_comment.class.to_s
508 end
509 end
510
511 def test_eager_habtm_with_association_inheritance
512 post = Post.find(6, :include => [ :special_categories ])
513 assert_equal 1, post.special_categories.size
514 post.special_categories.each do |special_category|
515 assert_equal "SpecialCategory", special_category.class.to_s
516 end
517 end
518
519 def test_eager_with_has_one_dependent_does_not_destroy_dependent
520 assert_not_nil companies(:first_firm).account
521 f = Firm.find(:first, :include => :account,
522 :conditions => ["companies.name = ?", "37signals"])
523 assert_not_nil f.account
524 assert_equal companies(:first_firm, :reload).account, f.account
525 end
526
527 def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size
528 author = authors(:david)
529 posts_with_no_comments = author.posts.select { |post| post.comments.blank? }
530 assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size
531 assert_equal posts_with_no_comments, author.posts_with_no_comments
532 end
533
534 def test_eager_with_invalid_association_reference
535 assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
536 post = Post.find(6, :include=> :monkeys )
537 }
538 assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
539 post = Post.find(6, :include=>[ :monkeys ])
540 }
541 assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
542 post = Post.find(6, :include=>[ 'monkeys' ])
543 }
544 assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
545 post = Post.find(6, :include=>[ :monkeys, :elephants ])
546 }
547 end
548
549 def find_all_ordered(className, include=nil)
550 className.find(:all, :order=>"#{className.table_name}.#{className.primary_key}", :include=>include)
551 end
552
553 def test_limited_eager_with_order
554 assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title)', :limit => 2, :offset => 1)
555 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)
556 end
557
558 def test_limited_eager_with_multiple_order_columns
559 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)
560 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)
561 end
562
563 def test_preload_with_interpolation
564 assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions
565 end
566
567 def test_polymorphic_type_condition
568 post = Post.find(posts(:thinking).id, :include => :taggings)
569 assert post.taggings.include?(taggings(:thinking_general))
570 post = SpecialPost.find(posts(:thinking).id, :include => :taggings)
571 assert post.taggings.include?(taggings(:thinking_general))
572 end
573
574 def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm
575 # Eager includes of has many and habtm associations aren't necessarily sorted in the same way
576 def assert_equal_after_sort(item1, item2, item3 = nil)
577 assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id})
578 assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3
579 end
580 # Test regular association, association with conditions, association with
581 # STI, and association with conditions assured not to be true
582 post_types = [:posts, :other_posts, :special_posts]
583 # test both has_many and has_and_belongs_to_many
584 [Author, Category].each do |className|
585 d1 = find_all_ordered(className)
586 # test including all post types at once
587 d2 = find_all_ordered(className, post_types)
588 d1.each_index do |i|
589 assert_equal(d1[i], d2[i])
590 assert_equal_after_sort(d1[i].posts, d2[i].posts)
591 post_types[1..-1].each do |post_type|
592 # test including post_types together
593 d3 = find_all_ordered(className, [:posts, post_type])
594 assert_equal(d1[i], d3[i])
595 assert_equal_after_sort(d1[i].posts, d3[i].posts)
596 assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type))
597 end
598 end
599 end
600 end
601
602 def test_eager_with_multiple_associations_with_same_table_has_one
603 d1 = find_all_ordered(Firm)
604 d2 = find_all_ordered(Firm, :account)
605 d1.each_index do |i|
606 assert_equal(d1[i], d2[i])
607 assert_equal(d1[i].account, d2[i].account)
608 end
609 end
610
611 def test_eager_with_multiple_associations_with_same_table_belongs_to
612 firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition]
613 d1 = find_all_ordered(Client)
614 d2 = find_all_ordered(Client, firm_types)
615 d1.each_index do |i|
616 assert_equal(d1[i], d2[i])
617 firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) }
618 end
619 end
620 def test_eager_with_valid_association_as_string_not_symbol
621 assert_nothing_raised { Post.find(:all, :include => 'comments') }
622 end
623
624 def test_eager_with_floating_point_numbers
625 assert_queries(2) do
626 # Before changes, the floating point numbers will be interpreted as table names and will cause this to run in one query
627 Comment.find :all, :conditions => "123.456 = 123.456", :include => :post
628 end
629 end
630
631 def test_preconfigured_includes_with_belongs_to
632 author = posts(:welcome).author_with_posts
633 assert_no_queries {assert_equal 5, author.posts.size}
634 end
635
636 def test_preconfigured_includes_with_has_one
637 comment = posts(:sti_comments).very_special_comment_with_post
638 assert_no_queries {assert_equal posts(:sti_comments), comment.post}
639 end
640
641 def test_preconfigured_includes_with_has_many
642 posts = authors(:david).posts_with_comments
643 one = posts.detect { |p| p.id == 1 }
644 assert_no_queries do
645 assert_equal 5, posts.size
646 assert_equal 2, one.comments.size
647 end
648 end
649
650 def test_preconfigured_includes_with_habtm
651 posts = authors(:david).posts_with_categories
652 one = posts.detect { |p| p.id == 1 }
653 assert_no_queries do
654 assert_equal 5, posts.size
655 assert_equal 2, one.categories.size
656 end
657 end
658
659 def test_preconfigured_includes_with_has_many_and_habtm
660 posts = authors(:david).posts_with_comments_and_categories
661 one = posts.detect { |p| p.id == 1 }
662 assert_no_queries do
663 assert_equal 5, posts.size
664 assert_equal 2, one.comments.size
665 assert_equal 2, one.categories.size
666 end
667 end
668
669 def test_count_with_include
670 if current_adapter?(:SybaseAdapter)
671 assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "len(comments.body) > 15")
672 elsif current_adapter?(:OpenBaseAdapter)
673 assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(FETCHBLOB(comments.body)) > 15")
674 else
675 assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15")
676 end
677 end
678
679 def test_load_with_sti_sharing_association
680 assert_queries(2) do #should not do 1 query per subclass
681 Comment.find :all, :include => :post
682 end
683 end
684
685 def test_conditions_on_join_table_with_include_and_limit
686 assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size
687 end
688
689 def test_order_on_join_table_with_include_and_limit
690 assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
691 end
692 end