join_model_test.rb 24.5 KB
Newer Older
1
require "cases/helper"
J
Jeremy Kemper 已提交
2 3 4 5 6 7 8 9 10 11 12 13
require 'models/tag'
require 'models/tagging'
require 'models/post'
require 'models/item'
require 'models/comment'
require 'models/author'
require 'models/category'
require 'models/categorization'
require 'models/vertex'
require 'models/edge'
require 'models/book'
require 'models/citation'
14

15
class AssociationsJoinModelTest < ActiveRecord::TestCase
16
  self.use_transactional_fixtures = false
17
  fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books
18 19

  def test_has_many
20
    assert authors(:david).categories.include?(categories(:general))
21
  end
22

23
  def test_has_many_inherited
24
    assert authors(:mary).categories.include?(categories(:sti_test))
25
  end
26

27
  def test_inherited_has_many
28 29 30 31 32 33
    assert categories(:sti_test).authors.include?(authors(:mary))
  end

  def test_has_many_uniq_through_join_model
    assert_equal 2, authors(:mary).categorized_posts.size
    assert_equal 1, authors(:mary).unique_categorized_posts.size
34
  end
J
Jeremy Kemper 已提交
35

36 37 38 39 40 41 42 43
  def test_has_many_uniq_through_count
    author = authors(:mary)
    assert !authors(:mary).unique_categorized_posts.loaded?
    assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
    assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
    assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, :conditions => "title is NULL") }
    assert !authors(:mary).unique_categorized_posts.loaded?
  end
J
Jeremy Kemper 已提交
44

45
  def test_polymorphic_has_many
46
    assert posts(:welcome).taggings.include?(taggings(:welcome_general))
47
  end
48

49 50 51
  def test_polymorphic_has_one
    assert_equal taggings(:welcome_general), posts(:welcome).tagging
  end
52

53
  def test_polymorphic_belongs_to
54 55
    assert_equal posts(:welcome), posts(:welcome).taggings.first.taggable
  end
56 57

  def test_polymorphic_has_many_going_through_join_model
58 59 60 61
    assert_equal tags(:general), tag = posts(:welcome).tags.first
    assert_no_queries do
      tag.tagging
    end
62
  end
63

R
Rick Olson 已提交
64 65 66 67 68
  def test_count_polymorphic_has_many
    assert_equal 1, posts(:welcome).taggings.count
    assert_equal 1, posts(:welcome).tags.count
  end

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
  def test_polymorphic_has_many_going_through_join_model_with_find
    assert_equal tags(:general), tag = posts(:welcome).tags.find(:first)
    assert_no_queries do
      tag.tagging
    end
  end

  def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection
    assert_equal tags(:general), tag = posts(:welcome).funky_tags.first
    assert_no_queries do
      tag.tagging
    end
  end

  def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find
    assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first)
    assert_no_queries do
      tag.tagging
    end
  end

90 91 92 93 94 95 96 97 98 99 100
  def test_polymorphic_has_many_going_through_join_model_with_disabled_include
    assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
    assert_queries 1 do
      tag.tagging
    end
  end

  def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
    assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
    tag.author_id
  end
101

102 103 104 105 106
  def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
    assert_equal tags(:misc), taggings(:welcome_general).super_tag
    assert_equal tags(:misc), posts(:welcome).super_tags.first
  end

107 108 109
  def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class
    post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body'
    assert_instance_of SubStiPost, post
J
Jeremy Kemper 已提交
110

111 112 113 114
    tagging = tags(:misc).taggings.create(:taggable => post)
    assert_equal "SubStiPost", tagging.taggable_type
  end

115 116 117
  def test_polymorphic_has_many_going_through_join_model_with_inheritance
    assert_equal tags(:general), posts(:thinking).tags.first
  end
118 119 120 121 122

  def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name
    assert_equal tags(:general), posts(:thinking).funky_tags.first
  end

123 124 125
  def test_polymorphic_has_many_create_model_with_inheritance
    post = posts(:thinking)
    assert_instance_of SpecialPost, post
J
Jeremy Kemper 已提交
126

127 128 129
    tagging = tags(:misc).taggings.create(:taggable => post)
    assert_equal "Post", tagging.taggable_type
  end
130 131 132 133 134 135

  def test_polymorphic_has_one_create_model_with_inheritance
    tagging = tags(:misc).create_tagging(:taggable => posts(:thinking))
    assert_equal "Post", tagging.taggable_type
  end

136 137 138 139 140 141 142 143 144 145 146 147 148
  def test_set_polymorphic_has_many
    tagging = tags(:misc).taggings.create
    posts(:thinking).taggings << tagging
    assert_equal "Post", tagging.taggable_type
  end

  def test_set_polymorphic_has_one
    tagging = tags(:misc).taggings.create
    posts(:thinking).tagging = tagging
    assert_equal "Post", tagging.taggable_type
  end

  def test_create_polymorphic_has_many_with_scope
149 150
    old_count = posts(:welcome).taggings.count
    tagging = posts(:welcome).taggings.create(:tag => tags(:misc))
151
    assert_equal "Post", tagging.taggable_type
152
    assert_equal old_count+1, posts(:welcome).taggings.count
153
  end
J
Jeremy Kemper 已提交
154

155 156 157 158 159 160
  def test_create_bang_polymorphic_with_has_many_scope
    old_count = posts(:welcome).taggings.count
    tagging = posts(:welcome).taggings.create!(:tag => tags(:misc))
    assert_equal "Post", tagging.taggable_type
    assert_equal old_count+1, posts(:welcome).taggings.count
  end
161 162

  def test_create_polymorphic_has_one_with_scope
163 164
    old_count = Tagging.count
    tagging = posts(:welcome).tagging.create(:tag => tags(:misc))
165
    assert_equal "Post", tagging.taggable_type
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
    assert_equal old_count+1, Tagging.count
  end

  def test_delete_polymorphic_has_many_with_delete_all
    assert_equal 1, posts(:welcome).taggings.count
    posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDeleteAll'
    post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)

    old_count = Tagging.count
    post.destroy
    assert_equal old_count-1, Tagging.count
    assert_equal 0, posts(:welcome).taggings.count
  end

  def test_delete_polymorphic_has_many_with_destroy
    assert_equal 1, posts(:welcome).taggings.count
    posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDestroy'
    post = find_post_with_dependency(1, :has_many, :taggings, :destroy)

    old_count = Tagging.count
    post.destroy
    assert_equal old_count-1, Tagging.count
    assert_equal 0, posts(:welcome).taggings.count
  end

  def test_delete_polymorphic_has_many_with_nullify
    assert_equal 1, posts(:welcome).taggings.count
    posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyNullify'
    post = find_post_with_dependency(1, :has_many, :taggings, :nullify)

    old_count = Tagging.count
    post.destroy
    assert_equal old_count, Tagging.count
    assert_equal 0, posts(:welcome).taggings.count
  end

  def test_delete_polymorphic_has_one_with_destroy
    assert posts(:welcome).tagging
    posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneDestroy'
    post = find_post_with_dependency(1, :has_one, :tagging, :destroy)

    old_count = Tagging.count
    post.destroy
    assert_equal old_count-1, Tagging.count
    assert_nil posts(:welcome).tagging(true)
  end

  def test_delete_polymorphic_has_one_with_nullify
    assert posts(:welcome).tagging
    posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneNullify'
    post = find_post_with_dependency(1, :has_one, :tagging, :nullify)

    old_count = Tagging.count
    post.destroy
    assert_equal old_count, Tagging.count
    assert_nil posts(:welcome).tagging(true)
222 223
  end

224
  def test_has_many_with_piggyback
225
    assert_equal "2", categories(:sti_test).authors.first.post_id.to_s
226
  end
227 228 229 230 231 232 233 234 235 236

  def test_include_has_many_through
    posts              = Post.find(:all, :order => 'posts.id')
    posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id')
    assert_equal posts.length, posts_with_authors.length
    posts.length.times do |i|
      assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length }
    end
  end

237 238 239 240 241 242 243
  def test_include_polymorphic_has_one
    post    = Post.find_by_id(posts(:welcome).id, :include => :tagging)
    tagging = taggings(:welcome_general)
    assert_no_queries do
      assert_equal tagging, post.tagging
    end
  end
J
Jeremy Kemper 已提交
244

245 246 247 248 249 250 251
  def test_include_polymorphic_has_one_defined_in_abstract_parent
    item    = Item.find_by_id(items(:dvd).id, :include => :tagging)
    tagging = taggings(:godfather)
    assert_no_queries do
      assert_equal tagging, item.tagging
    end
  end
J
Jeremy Kemper 已提交
252

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  def test_include_polymorphic_has_many_through
    posts           = Post.find(:all, :order => 'posts.id')
    posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
    assert_equal posts.length, posts_with_tags.length
    posts.length.times do |i|
      assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
    end
  end

  def test_include_polymorphic_has_many
    posts               = Post.find(:all, :order => 'posts.id')
    posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
    assert_equal posts.length, posts_with_taggings.length
    posts.length.times do |i|
      assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
    end
  end

271 272 273
  def test_has_many_find_all
    assert_equal [categories(:general)], authors(:david).categories.find(:all)
  end
J
Jeremy Kemper 已提交
274

275 276 277
  def test_has_many_find_first
    assert_equal categories(:general), authors(:david).categories.find(:first)
  end
278 279 280 281

  def test_has_many_with_hash_conditions
    assert_equal categories(:general), authors(:david).categories_like_general.find(:first)
  end
J
Jeremy Kemper 已提交
282

283 284 285 286
  def test_has_many_find_conditions
    assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'")
    assert_equal nil, authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'")
  end
287

288
  def test_has_many_class_methods_called_by_method_missing
289
    assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
290
    assert_equal nil, authors(:david).categories.find_by_name('Technology')
291
  end
292

293 294 295 296 297
  def test_has_many_array_methods_called_by_method_missing
    assert true, authors(:david).categories.any? { |category| category.name == 'General' }
    assert_nothing_raised { authors(:david).categories.sort }
  end

298 299 300 301
  def test_has_many_going_through_join_model_with_custom_foreign_key
    assert_equal [], posts(:thinking).authors
    assert_equal [authors(:mary)], posts(:authorless).authors
  end
302 303 304 305 306 307 308 309
  
  def test_both_scoped_and_explicit_joins_should_be_respected
    assert_nothing_raised do
      Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
        Post.find :all, :select => "comments.id, authors.id", :joins => "left outer join authors on authors.id = posts.author_id"
      end
    end
  end
310 311 312 313 314 315 316 317

  def test_belongs_to_polymorphic_with_counter_cache
    assert_equal 0, posts(:welcome)[:taggings_count]
    tagging = posts(:welcome).taggings.create(:tag => tags(:general))
    assert_equal 1, posts(:welcome, :reload)[:taggings_count]
    tagging.destroy
    assert posts(:welcome, :reload)[:taggings_count].zero?
  end
318

319
  def test_unavailable_through_reflection
320
    assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
321 322
  end

323 324 325 326 327
  def test_has_many_through_join_model_with_conditions
    assert_equal [], posts(:welcome).invalid_taggings
    assert_equal [], posts(:welcome).invalid_tags
  end

328
  def test_has_many_polymorphic
329
    assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicError do
330
      assert_equal posts(:welcome, :thinking), tags(:general).taggables
331
    end
332
    assert_raise ActiveRecord::EagerLoadPolymorphicError do
333
      assert_equal posts(:welcome, :thinking), tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
334 335
    end
  end
J
Jeremy Kemper 已提交
336

337
  def test_has_many_polymorphic_with_source_type
338
    assert_equal posts(:welcome, :thinking), tags(:general).tagged_posts
339 340 341 342
  end

  def test_eager_has_many_polymorphic_with_source_type
    tag_with_include = Tag.find(tags(:general).id, :include => :tagged_posts)
343
    desired = posts(:welcome, :thinking)
344 345 346
    assert_no_queries do
      assert_equal desired, tag_with_include.tagged_posts
    end
347
    assert_equal 5, tag_with_include.taggings.length
348
  end
349

350
  def test_has_many_through_has_many_find_all
351
    assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
352 353
  end

354 355 356 357
  def test_has_many_through_has_many_find_all_with_custom_class
    assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first
  end

358
  def test_has_many_through_has_many_find_first
359
    assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id')
360 361 362
  end

  def test_has_many_through_has_many_find_conditions
363 364
    options = { :conditions => "comments.#{QUOTED_TYPE}='SpecialComment'", :order => 'comments.id' }
    assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, options)
365 366 367 368 369 370
  end

  def test_has_many_through_has_many_find_by_id
    assert_equal comments(:more_greetings), authors(:david).comments.find(2)
  end

371 372 373 374 375
  def test_has_many_through_polymorphic_has_one
    assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tagging }
  end

  def test_has_many_through_polymorphic_has_many
376
    assert_equal taggings(:welcome_general, :thinking_general), authors(:david).taggings.uniq.sort_by { |t| t.id }
377 378
  end

379
  def test_include_has_many_through_polymorphic_has_many
380
    author            = Author.find_by_id(authors(:david).id, :include => :taggings)
381
    expected_taggings = taggings(:welcome_general, :thinking_general)
382 383 384 385 386
    assert_no_queries do
      assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
    end
  end

387 388 389 390 391 392 393 394
  def test_has_many_through_has_many_through
    assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags }
  end

  def test_has_many_through_habtm
    assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories }
  end

395 396 397 398 399 400 401
  def test_eager_load_has_many_through_has_many
    author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
    SpecialComment.new; VerySpecialComment.new
    assert_no_queries do
      assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id)
    end
  end
J
Jeremy Kemper 已提交
402

403 404 405 406 407 408
  def test_eager_load_has_many_through_has_many_with_conditions
    post = Post.find(:first, :include => :invalid_tags)
    assert_no_queries do
      post.invalid_tags
    end
  end
409

410 411 412 413 414 415 416
  def test_eager_belongs_to_and_has_one_not_singularized
    assert_nothing_raised do
      Author.find(:first, :include => :author_address)
      AuthorAddress.find(:first, :include => :author)
    end
  end

417 418 419 420 421 422 423 424
  def test_self_referential_has_many_through
    assert_equal [authors(:mary)], authors(:david).favorite_authors
    assert_equal [],               authors(:mary).favorite_authors
  end

  def test_add_to_self_referential_has_many_through
    new_author = Author.create(:name => "Bob")
    authors(:david).author_favorites.create :favorite_author => new_author
R
Rick Olson 已提交
425
    assert_equal new_author, authors(:david).reload.favorite_authors.first
426
  end
J
Jeremy Kemper 已提交
427

428 429 430 431 432
  def test_has_many_through_uses_conditions_specified_on_the_has_many_association
    author = Author.find(:first)
    assert !author.comments.blank?
    assert author.nonexistant_comments.blank?
  end
433

434 435 436 437
  def test_has_many_through_uses_correct_attributes
    assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"]
  end

438 439 440 441
  def test_raise_error_when_adding_new_record_to_has_many_through
    assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).tags << tags(:general).clone }
    assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).clone.tags << tags(:general) }
    assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).tags.build }
442
    assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).tags.new }
443
  end
444 445

  def test_create_associate_when_adding_to_has_many_through
446 447
    count = posts(:thinking).tags.count
    push = Tag.create!(:name => 'pushme')
448 449 450 451 452 453 454 455 456
    post_thinking = posts(:thinking)
    assert_nothing_raised { post_thinking.tags << push }
    assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
                message = "Expected a Tag in tags collection, got #{wrong.class}.")
    assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
                message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
    assert_equal(count + 1, post_thinking.tags.size)
    assert_equal(count + 1, post_thinking.tags(true).size)

457
    assert_kind_of Tag, post_thinking.tags.create!(:name => 'foo')
458 459 460 461 462 463 464 465 466 467 468 469 470 471
    assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
                message = "Expected a Tag in tags collection, got #{wrong.class}.")
    assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
                message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
    assert_equal(count + 2, post_thinking.tags.size)
    assert_equal(count + 2, post_thinking.tags(true).size)

    assert_nothing_raised { post_thinking.tags.concat(Tag.create!(:name => 'abc'), Tag.create!(:name => 'def')) }
    assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
                message = "Expected a Tag in tags collection, got #{wrong.class}.")
    assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
                message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
    assert_equal(count + 4, post_thinking.tags.size)
    assert_equal(count + 4, post_thinking.tags(true).size)
472 473 474

    # Raises if the wrong reflection name is used to set the Edge belongs_to
    assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
475 476
  end

477 478 479 480 481 482
  def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded
    author = authors(:david)
    assert_equal 9, author.comments.size
    assert !author.comments.loaded?
  end

483 484 485 486 487 488 489 490 491
  uses_mocha('has_many_through_collection_size_uses_counter_cache_if_it_exists') do
    def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
      author = authors(:david)
      author.stubs(:read_attribute).with('comments_count').returns(100)
      assert_equal 100, author.comments.size
      assert !author.comments.loaded?
    end
  end

492 493 494 495 496 497 498 499 500
  def test_adding_junk_to_has_many_through_should_raise_type_mismatch
    assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags << "Uhh what now?" }
  end

  def test_adding_to_has_many_through_should_return_self
    tags = posts(:thinking).tags
    assert_equal tags, posts(:thinking).tags.push(tags(:general))
  end

501 502 503 504 505 506 507 508 509 510 511 512 513 514
  def test_delete_associate_when_deleting_from_has_many_through_with_nonstandard_id
    count = books(:awdr).references.count
    references_before = books(:awdr).references
    book = Book.create!(:name => 'Getting Real')
    book_awdr = books(:awdr)
    book_awdr.references << book
    assert_equal(count + 1, book_awdr.references(true).size)

    assert_nothing_raised { book_awdr.references.delete(book) }
    assert_equal(count, book_awdr.references.size)
    assert_equal(count, book_awdr.references(true).size)
    assert_equal(references_before.sort, book_awdr.references.sort)
  end

515 516 517 518 519 520
  def test_delete_associate_when_deleting_from_has_many_through
    count = posts(:thinking).tags.count
    tags_before = posts(:thinking).tags
    tag = Tag.create!(:name => 'doomed')
    post_thinking = posts(:thinking)
    post_thinking.tags << tag
521
    assert_equal(count + 1, post_thinking.taggings(true).size)
522 523
    assert_equal(count + 1, post_thinking.tags(true).size)

J
Jeremy Kemper 已提交
524
    assert_nothing_raised { post_thinking.tags.delete(tag) }
525 526
    assert_equal(count, post_thinking.tags.size)
    assert_equal(count, post_thinking.tags(true).size)
527
    assert_equal(count, post_thinking.taggings(true).size)
528 529 530 531 532 533 534 535 536 537 538 539 540
    assert_equal(tags_before.sort, post_thinking.tags.sort)
  end

  def test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
    count = posts(:thinking).tags.count
    tags_before = posts(:thinking).tags
    doomed = Tag.create!(:name => 'doomed')
    doomed2 = Tag.create!(:name => 'doomed2')
    quaked = Tag.create!(:name => 'quaked')
    post_thinking = posts(:thinking)
    post_thinking.tags << doomed << doomed2
    assert_equal(count + 2, post_thinking.tags(true).size)

J
Jeremy Kemper 已提交
541
    assert_nothing_raised { post_thinking.tags.delete(doomed, doomed2, quaked) }
542 543 544 545 546 547 548 549
    assert_equal(count, post_thinking.tags.size)
    assert_equal(count, post_thinking.tags(true).size)
    assert_equal(tags_before.sort, post_thinking.tags.sort)
  end

  def test_deleting_junk_from_has_many_through_should_raise_type_mismatch
    assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags.delete("Uhh what now?") }
  end
550

551 552 553
  def test_has_many_through_sum_uses_calculations
    assert_nothing_raised { authors(:david).comments.sum(:post_id) }
  end
554

555 556 557 558 559 560 561 562
  def test_calculations_on_has_many_through_should_disambiguate_fields
    assert_nothing_raised { authors(:david).categories.maximum(:id) }
  end
  
  def test_calculations_on_has_many_through_should_not_disambiguate_fields_unless_necessary
    assert_nothing_raised { authors(:david).categories.maximum("categories.id") }
  end

563 564 565
  def test_has_many_through_has_many_with_sti
    assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
  end
J
Jeremy Kemper 已提交
566

567 568 569 570 571
  def test_uniq_has_many_through_should_retain_order
    comment_ids = authors(:david).comments.map(&:id)
    assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
    assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
  end
572

573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
  def test_polymorphic_has_many
    expected = taggings(:welcome_general)
    p = Post.find(posts(:welcome).id, :include => :taggings)
    assert_no_queries {assert p.taggings.include?(expected)}
    assert posts(:welcome).taggings.include?(taggings(:welcome_general))
  end

  def test_polymorphic_has_one
    expected = posts(:welcome)

    tagging  = Tagging.find(taggings(:welcome_general).id, :include => :taggable)
    assert_no_queries { assert_equal expected, tagging.taggable}
  end

  def test_polymorphic_belongs_to
    p = Post.find(posts(:welcome).id, :include => {:taggings => :taggable})
    assert_no_queries {assert_equal posts(:welcome), p.taggings.first.taggable}
  end

  def test_preload_polymorphic_has_many_through
    posts           = Post.find(:all, :order => 'posts.id')
    posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
    assert_equal posts.length, posts_with_tags.length
    posts.length.times do |i|
      assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
    end
  end

  def test_preload_polymorph_many_types
    taggings = Tagging.find :all, :include => :taggable, :conditions => ['taggable_type != ?', 'FakeModel']
    assert_no_queries do
      taggings.first.taggable.id
      taggings[1].taggable.id
    end

    taggables = taggings.map(&:taggable)
    assert taggables.include?(items(:dvd))
    assert taggables.include?(posts(:welcome))
  end

613 614 615 616 617 618
  def test_preload_nil_polymorphic_belongs_to
    assert_nothing_raised do
      taggings = Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
    end
  end

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
  def test_preload_polymorphic_has_many
    posts               = Post.find(:all, :order => 'posts.id')
    posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
    assert_equal posts.length, posts_with_taggings.length
    posts.length.times do |i|
      assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
    end
  end

  def test_belongs_to_shared_parent
    comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 1')
    assert_no_queries do
      assert_equal comments.first.post, comments[1].post
    end
  end

635 636 637 638 639 640 641 642 643 644
  private
    # create dynamic Post models to allow different dependency options
    def find_post_with_dependency(post_id, association, association_name, dependency)
      class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
      Post.find(post_id).update_attribute :type, class_name
      klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
      klass.set_table_name 'posts'
      klass.send(association, association_name, :as => :taggable, :dependent => dependency)
      klass.find(post_id)
    end
645
end