belongs_to_associations_test.rb 28.5 KB
Newer Older
1
require 'cases/helper'
2 3 4 5 6 7 8 9 10 11 12
require 'models/developer'
require 'models/project'
require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/computer'
require 'models/post'
require 'models/author'
require 'models/tag'
require 'models/tagging'
require 'models/comment'
13 14
require 'models/sponsor'
require 'models/member'
15
require 'models/essay'
16
require 'models/toy'
17 18
require 'models/invoice'
require 'models/line_item'
19 20
require 'models/column'
require 'models/record'
21 22 23

class BelongsToAssociationsTest < ActiveRecord::TestCase
  fixtures :accounts, :companies, :developers, :projects, :topics,
24
           :developers_projects, :computers, :authors, :author_addresses,
25
           :posts, :tags, :taggings, :comments, :sponsors, :members
26 27

  def test_belongs_to
28 29 30
    firm = Client.find(3).firm
    assert_not_nil firm
    assert_equal companies(:first_firm).name, firm.name
31 32
  end

33 34 35 36 37 38 39
  def test_belongs_to_does_not_use_order_by
    ActiveRecord::SQLCounter.clear_log
    Client.find(3).firm
  ensure
    assert ActiveRecord::SQLCounter.log_all.all? { |sql| /order by/i !~ sql }, 'ORDER BY was used in the query'
  end

40 41 42 43 44
  def test_belongs_to_with_primary_key
    client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
    assert_equal companies(:first_firm).name, client.firm_with_primary_key.name
  end

45 46
  def test_belongs_to_with_primary_key_joins_on_correct_column
    sql = Client.joins(:firm_with_primary_key).to_sql
47
    if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
48 49
      assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
      assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
50 51 52 53
    elsif current_adapter?(:OracleAdapter)
      # on Oracle aliases are truncated to 30 characters and are quoted in uppercase
      assert_no_match(/"firm_with_primary_keys_compani"\."id"/i, sql)
      assert_match(/"firm_with_primary_keys_compani"\."name"/i, sql)
E
Emilio Tagua 已提交
54
    else
55 56
      assert_no_match(/"firm_with_primary_keys_companies"\."id"/, sql)
      assert_match(/"firm_with_primary_keys_companies"\."name"/, sql)
E
Emilio Tagua 已提交
57
    end
58 59
  end

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
  def test_proxy_assignment
    account = Account.find(1)
    assert_nothing_raised { account.firm = account.firm }
  end

  def test_type_mismatch
    assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
    assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
  end

  def test_natural_assignment
    apple = Firm.create("name" => "Apple")
    citibank = Account.create("credit_limit" => 10)
    citibank.firm = apple
    assert_equal apple.id, citibank.firm_id
  end

77 78 79 80 81 82 83
  def test_id_assignment
    apple = Firm.create("name" => "Apple")
    citibank = Account.create("credit_limit" => 10)
    citibank.firm_id = apple
    assert_nil citibank.firm_id
  end

84 85 86 87 88 89 90
  def test_natural_assignment_with_primary_key
    apple = Firm.create("name" => "Apple")
    citibank = Client.create("name" => "Primary key client")
    citibank.firm_with_primary_key = apple
    assert_equal apple.name, citibank.firm_name
  end

91
  def test_eager_loading_with_primary_key
A
Aaron Patterson 已提交
92 93
    Firm.create("name" => "Apple")
    Client.create("name" => "Citibank", :firm_name => "Apple")
94
    citibank_result = Client.all.merge!(:where => {:name => "Citibank"}, :includes => :firm_with_primary_key).first
95
    assert citibank_result.association_cache.key?(:firm_with_primary_key)
96 97
  end

98 99 100
  def test_eager_loading_with_primary_key_as_symbol
    Firm.create("name" => "Apple")
    Client.create("name" => "Citibank", :firm_name => "Apple")
101
    citibank_result = Client.all.merge!(:where => {:name => "Citibank"}, :includes => :firm_with_primary_key_symbols).first
102
    assert citibank_result.association_cache.key?(:firm_with_primary_key_symbols)
103 104
  end

105 106 107 108 109 110 111 112 113
  def test_creating_the_belonging_object
    citibank = Account.create("credit_limit" => 10)
    apple    = citibank.create_firm("name" => "Apple")
    assert_equal apple, citibank.firm
    citibank.save
    citibank.reload
    assert_equal apple, citibank.firm
  end

114 115 116 117 118 119 120 121 122
  def test_creating_the_belonging_object_with_primary_key
    client = Client.create(:name => "Primary key client")
    apple  = client.create_firm_with_primary_key("name" => "Apple")
    assert_equal apple, client.firm_with_primary_key
    client.save
    client.reload
    assert_equal apple, client.firm_with_primary_key
  end

123 124 125 126 127 128 129
  def test_building_the_belonging_object
    citibank = Account.create("credit_limit" => 10)
    apple    = citibank.build_firm("name" => "Apple")
    citibank.save
    assert_equal apple.id, citibank.firm_id
  end

130 131 132
  def test_building_the_belonging_object_with_implicit_sti_base_class
    account = Account.new
    company = account.build_firm
133
    assert_kind_of Company, company, "Expected #{company.class} to be a Company"
134 135 136 137 138
  end

  def test_building_the_belonging_object_with_explicit_sti_base_class
    account = Account.new
    company = account.build_firm(:type => "Company")
139
    assert_kind_of Company, company, "Expected #{company.class} to be a Company"
140 141 142 143 144
  end

  def test_building_the_belonging_object_with_sti_subclass
    account = Account.new
    company = account.build_firm(:type => "Firm")
145
    assert_kind_of Firm, company, "Expected #{company.class} to be a Firm"
146 147 148 149 150 151 152 153 154 155 156 157
  end

  def test_building_the_belonging_object_with_an_invalid_type
    account = Account.new
    assert_raise(ActiveRecord::SubclassNotFound) { account.build_firm(:type => "InvalidType") }
  end

  def test_building_the_belonging_object_with_an_unrelated_type
    account = Account.new
    assert_raise(ActiveRecord::SubclassNotFound) { account.build_firm(:type => "Account") }
  end

158 159 160 161 162 163 164
  def test_building_the_belonging_object_with_primary_key
    client = Client.create(:name => "Primary key client")
    apple  = client.build_firm_with_primary_key("name" => "Apple")
    client.save
    assert_equal apple.name, client.firm_name
  end

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
  def test_create!
    client  = Client.create!(:name => "Jimmy")
    account = client.create_account!(:credit_limit => 10)
    assert_equal account, client.account
    assert account.persisted?
    client.save
    client.reload
    assert_equal account, client.account
  end

  def test_failing_create!
    client  = Client.create!(:name => "Jimmy")
    assert_raise(ActiveRecord::RecordInvalid) { client.create_account! }
    assert_not_nil client.account
    assert client.account.new_record?
  end

182 183 184 185 186 187 188 189
  def test_natural_assignment_to_nil
    client = Client.find(3)
    client.firm = nil
    client.save
    assert_nil client.firm(true)
    assert_nil client.client_of
  end

190 191 192 193 194 195 196 197
  def test_natural_assignment_to_nil_with_primary_key
    client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
    client.firm_with_primary_key = nil
    client.save
    assert_nil client.firm_with_primary_key(true)
    assert_nil client.client_of
  end

198 199 200 201 202 203 204 205 206 207
  def test_with_different_class_name
    assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
    assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
  end

  def test_with_condition
    assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
    assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
  end

208 209 210 211 212 213 214 215 216
  def test_polymorphic_association_class
    sponsor = Sponsor.new
    assert_nil sponsor.association(:sponsorable).send(:klass)

    sponsor.sponsorable_type = '' # the column doesn't have to be declared NOT NULL
    assert_nil sponsor.association(:sponsorable).send(:klass)

    sponsor.sponsorable = Member.new :name => "Bert"
    assert_equal Member, sponsor.association(:sponsorable).send(:klass)
217
    assert_equal "members", sponsor.association(:sponsorable).aliased_table_name
218 219
  end

220 221 222 223 224 225 226 227 228
  def test_with_polymorphic_and_condition
    sponsor = Sponsor.create
    member = Member.create :name => "Bert"
    sponsor.sponsorable = member

    assert_equal member, sponsor.sponsorable
    assert_nil sponsor.sponsorable_with_conditions
  end

229
  def test_with_select
J
Jon Leighton 已提交
230
    assert_equal 1, Company.find(2).firm_with_select.attributes.size
231
    assert_equal 1, Company.all.merge!(:includes => :firm_with_select ).find(2).firm_with_select.attributes.size
232 233
  end

234 235
  def test_belongs_to_counter
    debate = Topic.create("title" => "debate")
236
    assert_equal 0, debate.read_attribute("replies_count"), "No replies yet"
237 238

    trash = debate.replies.create("title" => "blah!", "content" => "world around!")
239
    assert_equal 1, Topic.find(debate.id).read_attribute("replies_count"), "First reply created"
240 241

    trash.destroy
242
    assert_equal 0, Topic.find(debate.id).read_attribute("replies_count"), "First reply deleted"
243 244 245
  end

  def test_belongs_to_counter_with_assigning_nil
246 247
    post = Post.find(1)
    comment = Comment.find(1)
248

249 250
    assert_equal post.id, comment.post_id
    assert_equal 2, Post.find(post.id).comments.size
251

252
    comment.post = nil
253

254
    assert_equal 1, Post.find(post.id).comments.size
255 256
  end

257 258 259 260 261 262 263 264 265
  def test_belongs_to_with_primary_key_counter
    debate  = Topic.create("title" => "debate")
    debate2 = Topic.create("title" => "debate2")
    reply   = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate")

    assert_equal 1, debate.reload.replies_count
    assert_equal 0, debate2.reload.replies_count

    reply.topic_with_primary_key = debate2
266

267 268
    assert_equal 0, debate.reload.replies_count
    assert_equal 1, debate2.reload.replies_count
269 270 271

    reply.topic_with_primary_key = nil

272 273
    assert_equal 0, debate.reload.replies_count
    assert_equal 0, debate2.reload.replies_count
274 275
  end

276
  def test_belongs_to_counter_with_reassigning
277 278 279 280
    topic1 = Topic.create("title" => "t1")
    topic2 = Topic.create("title" => "t2")
    reply1 = Reply.new("title" => "r1", "content" => "r1")
    reply1.topic = topic1
281

282 283 284
    assert reply1.save
    assert_equal 1, Topic.find(topic1.id).replies.size
    assert_equal 0, Topic.find(topic2.id).replies.size
285

286
    reply1.topic = Topic.find(topic2.id)
287

288
    assert_no_queries do
289
      reply1.topic = topic2
290 291
    end

292 293 294
    assert reply1.save
    assert_equal 0, Topic.find(topic1.id).replies.size
    assert_equal 1, Topic.find(topic2.id).replies.size
295

296
    reply1.topic = nil
297

298 299
    assert_equal 0, Topic.find(topic1.id).replies.size
    assert_equal 0, Topic.find(topic2.id).replies.size
300

301
    reply1.topic = topic1
302

303 304
    assert_equal 1, Topic.find(topic1.id).replies.size
    assert_equal 0, Topic.find(topic2.id).replies.size
305

306
    reply1.destroy
307

308 309
    assert_equal 0, Topic.find(topic1.id).replies.size
    assert_equal 0, Topic.find(topic2.id).replies.size
310 311
  end

312
  def test_belongs_to_reassign_with_namespaced_models_and_counters
313 314 315 316
    topic1 = Web::Topic.create("title" => "t1")
    topic2 = Web::Topic.create("title" => "t2")
    reply1 = Web::Reply.new("title" => "r1", "content" => "r1")
    reply1.topic = topic1
317

318 319 320
    assert reply1.save
    assert_equal 1, Web::Topic.find(topic1.id).replies.size
    assert_equal 0, Web::Topic.find(topic2.id).replies.size
321

322
    reply1.topic = Web::Topic.find(topic2.id)
323

324 325 326
    assert reply1.save
    assert_equal 0, Web::Topic.find(topic1.id).replies.size
    assert_equal 1, Web::Topic.find(topic2.id).replies.size
327 328
  end

329 330 331 332 333 334 335 336 337
  def test_belongs_to_counter_after_save
    topic = Topic.create!(:title => "monday night")
    topic.replies.create!(:title => "re: monday night", :content => "football")
    assert_equal 1, Topic.find(topic.id)[:replies_count]

    topic.save!
    assert_equal 1, Topic.find(topic.id)[:replies_count]
  end

338 339 340 341 342 343 344
  def test_belongs_to_with_touch_option_on_touch
    line_item = LineItem.create!
    Invoice.create!(line_items: [line_item])

    assert_queries(1) { line_item.touch }
  end

345
  def test_belongs_to_with_touch_option_on_touch_without_updated_at_attributes
R
Rafael Mendonça França 已提交
346
    assert_not LineItem.column_names.include?("updated_at")
347 348 349 350 351 352

    line_item = LineItem.create!
    invoice = Invoice.create!(line_items: [line_item])
    initial = invoice.updated_at
    line_item.touch

R
Rafael Mendonça França 已提交
353
    assert_not_equal initial, invoice.reload.updated_at
354 355
  end

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
  def test_belongs_to_with_touch_option_on_touch_and_removed_parent
    line_item = LineItem.create!
    Invoice.create!(line_items: [line_item])

    line_item.invoice = nil

    assert_queries(2) { line_item.touch }
  end

  def test_belongs_to_with_touch_option_on_update
    line_item = LineItem.create!
    Invoice.create!(line_items: [line_item])

    assert_queries(2) { line_item.update amount: 10 }
  end

372 373 374 375 376 377 378
  def test_belongs_to_with_touch_option_on_empty_update
    line_item = LineItem.create!
    Invoice.create!(line_items: [line_item])

    assert_queries(0) { line_item.save }
  end

379 380 381 382 383 384 385
  def test_belongs_to_with_touch_option_on_destroy
    line_item = LineItem.create!
    Invoice.create!(line_items: [line_item])

    assert_queries(2) { line_item.destroy }
  end

386 387 388 389 390 391 392 393
  def test_belongs_to_with_touch_option_on_destroy_with_destroyed_parent
    line_item = LineItem.create!
    invoice   = Invoice.create!(line_items: [line_item])
    invoice.destroy

    assert_queries(1) { line_item.destroy }
  end

394 395 396 397 398 399 400 401 402
  def test_belongs_to_with_touch_option_on_touch_and_reassigned_parent
    line_item = LineItem.create!
    Invoice.create!(line_items: [line_item])

    line_item.invoice = Invoice.create!

    assert_queries(3) { line_item.touch }
  end

403 404 405
  def test_belongs_to_counter_after_update
    topic = Topic.create!(title: "37s")
    topic.replies.create!(title: "re: 37s", content: "rails")
406 407
    assert_equal 1, Topic.find(topic.id)[:replies_count]

408
    topic.update(title: "37signals")
409 410 411
    assert_equal 1, Topic.find(topic.id)[:replies_count]
  end

412
  def test_belongs_to_counter_when_update_columns
G
ganesh 已提交
413 414 415 416
    topic = Topic.create!(:title => "37s")
    topic.replies.create!(:title => "re: 37s", :content => "rails")
    assert_equal 1, Topic.find(topic.id)[:replies_count]

V
Vipul A M 已提交
417
    topic.update_columns(content: "rails is wonderful")
G
ganesh 已提交
418 419 420
    assert_equal 1, Topic.find(topic.id)[:replies_count]
  end

421 422 423 424
  def test_assignment_before_child_saved
    final_cut = Client.new("name" => "Final Cut")
    firm = Firm.find(1)
    final_cut.firm = firm
425
    assert !final_cut.persisted?
426
    assert final_cut.save
427 428
    assert final_cut.persisted?
    assert firm.persisted?
429 430 431 432
    assert_equal firm, final_cut.firm
    assert_equal firm, final_cut.firm(true)
  end

433 434 435 436
  def test_assignment_before_child_saved_with_primary_key
    final_cut = Client.new("name" => "Final Cut")
    firm = Firm.find(1)
    final_cut.firm_with_primary_key = firm
437
    assert !final_cut.persisted?
438
    assert final_cut.save
439 440
    assert final_cut.persisted?
    assert firm.persisted?
441 442 443 444
    assert_equal firm, final_cut.firm_with_primary_key
    assert_equal firm, final_cut.firm_with_primary_key(true)
  end

445
  def test_new_record_with_foreign_key_but_no_object
446
    client = Client.new("firm_id" => 1)
447
    # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
448
    assert_equal Firm.all.merge!(:order => "id").first, client.firm_with_basic_id
449 450
  end

451 452 453 454
  def test_setting_foreign_key_after_nil_target_loaded
    client = Client.new
    client.firm_with_basic_id
    client.firm_id = 1
455

456 457 458 459 460 461 462 463 464 465
    assert_equal companies(:first_firm), client.firm_with_basic_id
  end

  def test_polymorphic_setting_foreign_key_after_nil_target_loaded
    sponsor = Sponsor.new
    sponsor.sponsorable
    sponsor.sponsorable_id = 1
    sponsor.sponsorable_type = "Member"

    assert_equal members(:groucho), sponsor.sponsorable
466 467
  end

468 469
  def test_dont_find_target_when_foreign_key_is_null
    tagging = taggings(:thinking_general)
P
Paul Nikitochkin 已提交
470
    assert_queries(0) { tagging.super_tag }
471 472
  end

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
  def test_field_name_same_as_foreign_key
    computer = Computer.find(1)
    assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
  end

  def test_counter_cache
    topic = Topic.create :title => "Zoom-zoom-zoom"
    assert_equal 0, topic[:replies_count]

    reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
    reply.topic = topic

    assert_equal 1, topic.reload[:replies_count]
    assert_equal 1, topic.replies.size

    topic[:replies_count] = 15
    assert_equal 15, topic.replies.size
  end

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
  def test_counter_cache_double_destroy
    topic = Topic.create :title => "Zoom-zoom-zoom"

    5.times do
      topic.replies.create(:title => "re: zoom", :content => "speedy quick!")
    end

    assert_equal 5, topic.reload[:replies_count]
    assert_equal 5, topic.replies.size

    reply = topic.replies.first

    reply.destroy
    assert_equal 4, topic.reload[:replies_count]

    reply.destroy
    assert_equal 4, topic.reload[:replies_count]
    assert_equal 4, topic.replies.size
  end

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
  def test_concurrent_counter_cache_double_destroy
    topic = Topic.create :title => "Zoom-zoom-zoom"

    5.times do
      topic.replies.create(:title => "re: zoom", :content => "speedy quick!")
    end

    assert_equal 5, topic.reload[:replies_count]
    assert_equal 5, topic.replies.size

    reply = topic.replies.first
    reply_clone = Reply.find(reply.id)

    reply.destroy
    assert_equal 4, topic.reload[:replies_count]

    reply_clone.destroy
    assert_equal 4, topic.reload[:replies_count]
    assert_equal 4, topic.replies.size
  end

533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
  def test_custom_counter_cache
    reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
    assert_equal 0, reply[:replies_count]

    silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
    silly.reply = reply

    assert_equal 1, reply.reload[:replies_count]
    assert_equal 1, reply.replies.size

    reply[:replies_count] = 17
    assert_equal 17, reply.replies.size
  end

  def test_association_assignment_sticks
548
    post = Post.first
549

550
    author1, author2 = Author.all.merge!(:limit => 2).to_a
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
    assert_not_nil author1
    assert_not_nil author2

    # make sure the association is loaded
    post.author

    # set the association by id, directly
    post.author_id = author2.id

    # save and reload
    post.save!
    post.reload

    # the author id of the post should be the id we set
    assert_equal post.author_id, author2.id
  end

  def test_cant_save_readonly_association
    assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
    assert companies(:first_client).readonly_firm.readonly?
  end
572

573 574 575 576 577 578 579 580 581 582 583 584 585
  def test_test_polymorphic_assignment_foreign_key_type_string
    comment = Comment.first
    comment.author   = Author.first
    comment.resource = Member.first
    comment.save

    assert_equal Comment.all.to_a,
      Comment.includes(:author).to_a

    assert_equal Comment.all.to_a,
      Comment.includes(:resource).to_a
  end

586 587 588 589 590 591
  def test_polymorphic_assignment_foreign_type_field_updating
    # should update when assigning a saved record
    sponsor = Sponsor.new
    member = Member.create
    sponsor.sponsorable = member
    assert_equal "Member", sponsor.sponsorable_type
592

593 594 595 596 597 598
    # should update when assigning a new record
    sponsor = Sponsor.new
    member = Member.new
    sponsor.sponsorable = member
    assert_equal "Member", sponsor.sponsorable_type
  end
599 600 601 602 603 604 605 606 607 608 609 610 611 612

  def test_polymorphic_assignment_with_primary_key_foreign_type_field_updating
    # should update when assigning a saved record
    essay = Essay.new
    writer = Author.create(:name => "David")
    essay.writer = writer
    assert_equal "Author", essay.writer_type

    # should update when assigning a new record
    essay = Essay.new
    writer = Author.new
    essay.writer = writer
    assert_equal "Author", essay.writer_type
  end
613

614 615 616 617
  def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
    sponsor = Sponsor.new
    saved_member = Member.create
    new_member = Member.new
618

619 620
    sponsor.sponsorable = saved_member
    assert_equal saved_member.id, sponsor.sponsorable_id
621

622
    sponsor.sponsorable = new_member
623
    assert_nil sponsor.sponsorable_id
624
  end
625

626 627 628 629 630 631 632 633 634 635 636 637
  def test_assignment_updates_foreign_id_field_for_new_and_saved_records
    client = Client.new
    saved_firm = Firm.create :name => "Saved"
    new_firm = Firm.new

    client.firm = saved_firm
    assert_equal saved_firm.id, client.client_of

    client.firm = new_firm
    assert_nil client.client_of
  end

638 639 640 641 642 643 644 645 646
  def test_polymorphic_assignment_with_primary_key_updates_foreign_id_field_for_new_and_saved_records
    essay = Essay.new
    saved_writer = Author.create(:name => "David")
    new_writer = Author.new

    essay.writer = saved_writer
    assert_equal saved_writer.name, essay.writer_id

    essay.writer = new_writer
647
    assert_nil essay.writer_id
648 649
  end

650 651 652 653 654 655 656 657 658 659 660 661 662
  def test_polymorphic_assignment_with_nil
    essay = Essay.new
    assert_nil essay.writer_id
    assert_nil essay.writer_type

    essay.writer_id = 1
    essay.writer_type = 'Author'

    essay.writer = nil
    assert_nil essay.writer_id
    assert_nil essay.writer_type
  end

663
  def test_belongs_to_proxy_should_not_respond_to_private_methods
664 665
    assert_raise(NoMethodError) { companies(:first_firm).private_method }
    assert_raise(NoMethodError) { companies(:second_client).firm.private_method }
666 667 668 669 670 671
  end

  def test_belongs_to_proxy_should_respond_to_private_methods_via_send
    companies(:first_firm).send(:private_method)
    companies(:second_client).firm.send(:private_method)
  end
672 673 674 675 676 677

  def test_save_of_record_with_loaded_belongs_to
    @account = companies(:first_firm).account

    assert_nothing_raised do
      Account.find(@account.id).save!
678
      Account.all.merge!(:includes => :firm).find(@account.id).save!
679 680 681 682 683 684
    end

    @account.firm.delete

    assert_nothing_raised do
      Account.find(@account.id).save!
685
      Account.all.merge!(:includes => :firm).find(@account.id).save!
686 687
    end
  end
688 689

  def test_dependent_delete_and_destroy_with_belongs_to
A
Akira Matsuda 已提交
690 691
    AuthorAddress.destroyed_author_address_ids.clear

692 693 694 695 696 697 698 699
    author_address = author_addresses(:david_address)
    author_address_extra = author_addresses(:david_address_extra)
    assert_equal [], AuthorAddress.destroyed_author_address_ids

    assert_difference "AuthorAddress.count", -2 do
      authors(:david).destroy
    end

J
Jon Leighton 已提交
700
    assert_equal [], AuthorAddress.where(id: [author_address.id, author_address_extra.id])
701 702 703
    assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids
  end

704 705
  def test_belongs_to_invalid_dependent_option_raises_exception
    error = assert_raise ArgumentError do
706
      Class.new(Author).belongs_to :special_author_address, :dependent => :nullify
707
    end
708
    assert_equal error.message, 'The :dependent option must be one of [:destroy, :delete], but is :nullify'
709
  end
710 711 712 713 714

  def test_attributes_are_being_set_when_initialized_from_belongs_to_association_with_where_clause
    new_firm = accounts(:signals37).build_firm(:name => 'Apple')
    assert_equal new_firm.name, "Apple"
  end
715

716 717 718 719 720
  def test_attributes_are_set_without_error_when_initialized_from_belongs_to_association_with_array_in_where_clause
    new_account = Account.where(:credit_limit => [ 50, 60 ]).new
    assert_nil new_account.credit_limit
  end

721
  def test_reassigning_the_parent_id_updates_the_object
722
    client = companies(:second_client)
723

724 725 726 727
    client.firm
    client.firm_with_condition
    firm_proxy                = client.send(:association_instance_get, :firm)
    firm_with_condition_proxy = client.send(:association_instance_get, :firm_with_condition)
728

729 730 731 732 733 734 735 736 737 738 739
    assert !firm_proxy.stale_target?
    assert !firm_with_condition_proxy.stale_target?
    assert_equal companies(:first_firm), client.firm
    assert_equal companies(:first_firm), client.firm_with_condition

    client.client_of = companies(:another_firm).id

    assert firm_proxy.stale_target?
    assert firm_with_condition_proxy.stale_target?
    assert_equal companies(:another_firm), client.firm
    assert_equal companies(:another_firm), client.firm_with_condition
740 741 742
  end

  def test_polymorphic_reassignment_of_associated_id_updates_the_object
743 744 745 746 747 748 749
    sponsor = sponsors(:moustache_club_sponsor_for_groucho)

    sponsor.sponsorable
    proxy = sponsor.send(:association_instance_get, :sponsorable)

    assert !proxy.stale_target?
    assert_equal members(:groucho), sponsor.sponsorable
750

751
    sponsor.sponsorable_id = members(:some_other_guy).id
752

753 754
    assert proxy.stale_target?
    assert_equal members(:some_other_guy), sponsor.sponsorable
755 756 757
  end

  def test_polymorphic_reassignment_of_associated_type_updates_the_object
758
    sponsor = sponsors(:moustache_club_sponsor_for_groucho)
759

760 761
    sponsor.sponsorable
    proxy = sponsor.send(:association_instance_get, :sponsorable)
762

763 764 765 766
    assert !proxy.stale_target?
    assert_equal members(:groucho), sponsor.sponsorable

    sponsor.sponsorable_type = 'Firm'
767

768 769 770
    assert proxy.stale_target?
    assert_equal companies(:first_firm), sponsor.sponsorable
  end
771 772 773

  def test_reloading_association_with_key_change
    client = companies(:second_client)
774
    firm = client.association(:firm)
775 776

    client.firm = companies(:another_firm)
777 778
    firm.reload
    assert_equal companies(:another_firm), firm.target
779 780

    client.client_of = companies(:first_firm).id
781 782
    firm.reload
    assert_equal companies(:first_firm), firm.target
783
  end
784 785

  def test_polymorphic_counter_cache
786 787 788
    tagging = taggings(:welcome_general)
    post    = posts(:welcome)
    comment = comments(:greetings)
789

790
    assert_difference lambda { post.reload.taggings_count }, -1 do
791 792 793 794 795
      assert_difference 'comment.reload.taggings_count', +1 do
        tagging.taggable = comment
      end
    end
  end
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814

  def test_polymorphic_with_custom_foreign_type
    sponsor = sponsors(:moustache_club_sponsor_for_groucho)
    groucho = members(:groucho)
    other   = members(:some_other_guy)

    assert_equal groucho, sponsor.sponsorable
    assert_equal groucho, sponsor.thing

    sponsor.thing = other

    assert_equal other, sponsor.sponsorable
    assert_equal other, sponsor.thing

    sponsor.sponsorable = groucho

    assert_equal groucho, sponsor.sponsorable
    assert_equal groucho, sponsor.thing
  end
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835

  def test_build_with_conditions
    client = companies(:second_client)
    firm   = client.build_bob_firm

    assert_equal "Bob", firm.name
  end

  def test_create_with_conditions
    client = companies(:second_client)
    firm   = client.create_bob_firm

    assert_equal "Bob", firm.name
  end

  def test_create_bang_with_conditions
    client = companies(:second_client)
    firm   = client.create_bob_firm!

    assert_equal "Bob", firm.name
  end
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856

  def test_build_with_block
    client = Client.create(:name => 'Client Company')

    firm = client.build_firm{ |f| f.name = 'Agency Company' }
    assert_equal 'Agency Company', firm.name
  end

  def test_create_with_block
    client = Client.create(:name => 'Client Company')

    firm = client.create_firm{ |f| f.name = 'Agency Company' }
    assert_equal 'Agency Company', firm.name
  end

  def test_create_bang_with_block
    client = Client.create(:name => 'Client Company')

    firm = client.create_firm!{ |f| f.name = 'Agency Company' }
    assert_equal 'Agency Company', firm.name
  end
857 858 859 860 861 862 863 864 865 866 867 868 869 870

  def test_should_set_foreign_key_on_create_association
    client = Client.create! :name => "fuu"

    firm = client.create_firm :name => "baa"
    assert_equal firm.id, client.client_of
  end

  def test_should_set_foreign_key_on_create_association!
    client = Client.create! :name => "fuu"

    firm = client.create_firm! :name => "baa"
    assert_equal firm.id, client.client_of
  end
871 872 873 874 875 876 877 878 879

  def test_self_referential_belongs_to_with_counter_cache_assigning_nil
    comment = Comment.create! :post => posts(:thinking), :body => "fuu"
    comment.parent = nil
    comment.save!

    assert_equal nil, comment.reload.parent
    assert_equal 0, comments(:greetings).reload.children_count
  end
880

881 882 883 884 885 886 887 888 889 890 891
  def test_belongs_to_with_id_assigning
    post = posts(:welcome)
    comment = Comment.create! body: "foo", post: post
    parent = comments(:greetings)
    assert_equal 0, parent.reload.children_count
    comment.parent_id = parent.id

    comment.save!
    assert_equal 1, parent.reload.children_count
  end

892 893 894 895 896 897
  def test_polymorphic_with_custom_primary_key
    toy = Toy.create!
    sponsor = Sponsor.create!(:sponsorable => toy)

    assert_equal toy, sponsor.reload.sponsorable
  end
J
Jon Leighton 已提交
898 899 900 901 902 903 904 905 906 907 908 909

  test "stale tracking doesn't care about the type" do
    apple = Firm.create("name" => "Apple")
    citibank = Account.create("credit_limit" => 10)

    citibank.firm_id = apple.id
    citibank.firm # load it

    citibank.firm_id = apple.id.to_s

    assert !citibank.association(:firm).stale_target?
  end
910

911 912 913 914 915 916 917 918 919 920
  def test_reflect_the_most_recent_change
    author1, author2 = Author.limit(2)
    post = Post.new(:title => "foo", :body=> "bar")

    post.author    = author1
    post.author_id = author2.id

    assert post.save
    assert_equal post.author_id, author2.id
  end
921 922 923 924 925 926 927 928 929 930

  test 'dangerous association name raises ArgumentError' do
    [:errors, 'errors', :save, 'save'].each do |name|
      assert_raises(ArgumentError, "Association #{name} should not be allowed") do
        Class.new(ActiveRecord::Base) do
          belongs_to name
        end
      end
    end
  end
931

932
  test 'belongs_to works with model called Record' do
933
    record = Record.create!
934 935
    Column.create! record: record
    assert_equal 1, Column.count
936
  end
937
end