module NestedAttributesOnACollectionAssociationTests

Public Instance Methods

test_can_use_symbols_as_object_identifier() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 825
def test_can_use_symbols_as_object_identifier
  @pirate.attributes = { parrots_attributes: { foo: { name: "Lovely Day" }, bar: { name: "Blown Away" } } }
  assert_nothing_raised { @pirate.save! }
end
test_numeric_column_changes_from_zero_to_no_empty_string() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 830
def test_numeric_column_changes_from_zero_to_no_empty_string
  Man.accepts_nested_attributes_for(:interests)

  repair_validations(Interest) do
    Interest.validates_numericality_of(:zine_id)
    man = Man.create(name: "John")
    interest = man.interests.create(topic: "bar", zine_id: 0)
    assert interest.save
    assert !man.update(interests_attributes: { id: interest.id, zine_id: "foo" })
  end
end
test_should_also_work_with_a_HashWithIndifferentAccess() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 620
def test_should_also_work_with_a_HashWithIndifferentAccess
  @pirate.send(association_setter, ActiveSupport::HashWithIndifferentAccess.new("foo" => ActiveSupport::HashWithIndifferentAccess.new(id: @child_1.id, name: "Grace OMalley")))
  @pirate.save
  assert_equal "Grace OMalley", @child_1.reload.name
end
test_should_automatically_build_new_associated_models_for_each_entry_in_a_hash_where_the_id_is_missing() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 702
def test_should_automatically_build_new_associated_models_for_each_entry_in_a_hash_where_the_id_is_missing
  @pirate.send(@association_name).destroy_all
  @pirate.reload.attributes = {
    association_getter => { "foo" => { name: "Grace OMalley" }, "bar" => { name: "Privateers Greed" } }
  }

  assert !@pirate.send(@association_name).first.persisted?
  assert_equal "Grace OMalley", @pirate.send(@association_name).first.name

  assert !@pirate.send(@association_name).last.persisted?
  assert_equal "Privateers Greed", @pirate.send(@association_name).last.name
end
test_should_automatically_enable_autosave_on_the_association() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 804
def test_should_automatically_enable_autosave_on_the_association
  assert Pirate.reflect_on_association(@association_name).options[:autosave]
end
test_should_be_possible_to_destroy_a_record() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 775
def test_should_be_possible_to_destroy_a_record
  ["1", 1, "true", true].each do |true_variable|
    record = @pirate.reload.send(@association_name).create!(name: "Grace OMalley")
    @pirate.send(association_setter,
      @alternate_params[association_getter].merge("baz" => { :id => record.id, "_destroy" => true_variable })
    )

    assert_difference("@pirate.send(@association_name).count", -1) do
      @pirate.save
    end
  end
end
test_should_define_an_attribute_writer_method_for_the_association() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 589
def test_should_define_an_attribute_writer_method_for_the_association
  assert_respond_to @pirate, association_setter
end
test_should_ignore_new_associated_records_if_a_reject_if_proc_returns_false() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 734
def test_should_ignore_new_associated_records_if_a_reject_if_proc_returns_false
  @alternate_params[association_getter]["baz"] = {}
  assert_no_difference("@pirate.send(@association_name).count") do
    @pirate.attributes = @alternate_params
  end
end
test_should_ignore_new_associated_records_with_truthy_destroy_attribute() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 721
def test_should_ignore_new_associated_records_with_truthy_destroy_attribute
  @pirate.send(@association_name).destroy_all
  @pirate.reload.attributes = {
    association_getter => {
      "foo" => { name: "Grace OMalley" },
      "bar" => { :name => "Privateers Greed", "_destroy" => "1" }
    }
  }

  assert_equal 1, @pirate.send(@association_name).length
  assert_equal "Grace OMalley", @pirate.send(@association_name).first.name
end
test_should_not_assign_destroy_key_to_a_record() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 715
def test_should_not_assign_destroy_key_to_a_record
  assert_nothing_raised do
    @pirate.send(association_setter, "foo" => { "_destroy" => "0" })
  end
end
test_should_not_destroy_the_associated_model_until_the_parent_is_saved() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 797
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
  assert_no_difference("@pirate.send(@association_name).count") do
    @pirate.send(association_setter, @alternate_params[association_getter].merge("baz" => { :id => @child_1.id, "_destroy" => true }))
  end
  assert_difference("@pirate.send(@association_name).count", -1) { @pirate.save }
end
test_should_not_destroy_the_associated_model_with_a_non_truthy_argument() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 788
def test_should_not_destroy_the_associated_model_with_a_non_truthy_argument
  [nil, "", "0", 0, "false", false].each do |false_variable|
    @alternate_params[association_getter]["foo"]["_destroy"] = false_variable
    assert_no_difference("@pirate.send(@association_name).count") do
      @pirate.update(@alternate_params)
    end
  end
end
test_should_not_load_association_when_updating_existing_records() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 632
def test_should_not_load_association_when_updating_existing_records
  @pirate.reload
  @pirate.send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
  assert ! @pirate.send(@association_name).loaded?

  @pirate.save
  assert ! @pirate.send(@association_name).loaded?
  assert_equal "Grace OMalley", @child_1.reload.name
end
test_should_not_overwrite_unsaved_updates_when_loading_association() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 642
def test_should_not_overwrite_unsaved_updates_when_loading_association
  @pirate.reload
  @pirate.send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
  assert_equal "Grace OMalley", @pirate.send(@association_name).load_target.find { |r| r.id == @child_1.id }.name
end
test_should_not_remove_scheduled_destroys_when_loading_association() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 663
def test_should_not_remove_scheduled_destroys_when_loading_association
  @pirate.reload
  @pirate.send(association_setter, [{ id: @child_1.id, _destroy: "1" }])
  assert @pirate.send(@association_name).load_target.find { |r| r.id == @child_1.id }.marked_for_destruction?
end
test_should_preserve_order_when_not_overwriting_unsaved_updates() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 648
def test_should_preserve_order_when_not_overwriting_unsaved_updates
  @pirate.reload
  @pirate.send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
  assert_equal @child_1.id, @pirate.send(@association_name).load_target.first.id
end
test_should_raise_RecordNotFound_if_an_id_belonging_to_a_different_record_is_given() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 692
def test_should_raise_RecordNotFound_if_an_id_belonging_to_a_different_record_is_given
  other_pirate = Pirate.create! catchphrase: "Ahoy!"
  other_child = other_pirate.send(@association_name).create! name: "Buccaneers Servant"

  exception = assert_raise ActiveRecord::RecordNotFound do
    @pirate.attributes = { association_getter => [{ id: other_child.id }] }
  end
  assert_equal "Couldn't find #{@child_1.class.name} with ID=#{other_child.id} for Pirate with ID=#{@pirate.id}", exception.message
end
test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 685
def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
  exception = assert_raise ActiveRecord::RecordNotFound do
    @pirate.attributes = { association_getter => [{ id: 1234567890 }] }
  end
  assert_equal "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}", exception.message
end
test_should_raise_an_UnknownAttributeError_for_non_existing_nested_attributes_for_has_many() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 593
def test_should_raise_an_UnknownAttributeError_for_non_existing_nested_attributes_for_has_many
  exception = assert_raise ActiveModel::UnknownAttributeError do
    @pirate.parrots_attributes = [{ peg_leg: true }]
  end
  assert_equal "unknown attribute 'peg_leg' for Parrot.", exception.message
end
test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 750
def test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed
  assert_nothing_raised { @pirate.send(association_setter, {}) }
  assert_nothing_raised { @pirate.send(association_setter, Hash.new) }

  exception = assert_raise ArgumentError do
    @pirate.send(association_setter, "foo")
  end
  assert_equal %{Hash or Array expected for attribute `#{@association_name}`, got String ("foo")}, exception.message
end
test_should_refresh_saved_records_when_not_overwriting_unsaved_updates() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 654
def test_should_refresh_saved_records_when_not_overwriting_unsaved_updates
  @pirate.reload
  record = @pirate.class.reflect_on_association(@association_name).klass.new(name: "Grace OMalley")
  @pirate.send(@association_name) << record
  record.save!
  @pirate.send(@association_name).last.update!(name: "Polly")
  assert_equal "Polly", @pirate.send(@association_name).load_target.last.name
end
test_should_save_only_one_association_on_create() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 600
def test_should_save_only_one_association_on_create
  pirate = Pirate.create!(
    :catchphrase => "Arr",
    association_getter => { "foo" => { name: "Grace OMalley" } })

  assert_equal 1, pirate.reload.send(@association_name).count
end
test_should_sort_the_hash_by_the_keys_before_building_new_associated_models() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 741
def test_should_sort_the_hash_by_the_keys_before_building_new_associated_models
  attributes = {}
  attributes["123726353"] = { name: "Grace OMalley" }
  attributes["2"] = { name: "Privateers Greed" } # 2 is lower then 123726353
  @pirate.send(association_setter, attributes)

  assert_equal ["Posideons Killer", "Killer bandita Dionne", "Privateers Greed", "Grace OMalley"].to_set, @pirate.send(@association_name).map(&:name).to_set
end
test_should_take_a_hash_and_assign_the_attributes_to_the_associated_models() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 626
def test_should_take_a_hash_and_assign_the_attributes_to_the_associated_models
  @pirate.attributes = @alternate_params
  assert_equal "Grace OMalley", @pirate.send(@association_name).first.name
  assert_equal "Privateers Greed", @pirate.send(@association_name).last.name
end
test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 669
def test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models
  @child_1.stub(:id, "ABC1X") do
    @child_2.stub(:id, "ABC2X") do

      @pirate.attributes = {
        association_getter => [
          { id: @child_1.id, name: "Grace OMalley" },
          { id: @child_2.id, name: "Privateers Greed" }
        ]
      }

      assert_equal ["Grace OMalley", "Privateers Greed"], [@child_1.name, @child_2.name]
    end
  end
end
test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 608
def test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models
  @alternate_params[association_getter].stringify_keys!
  @pirate.update @alternate_params
  assert_equal ["Grace OMalley", "Privateers Greed"], [@child_1.reload.name, @child_2.reload.name]
end
test_should_take_an_array_and_assign_the_attributes_to_the_associated_models() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 614
def test_should_take_an_array_and_assign_the_attributes_to_the_associated_models
  @pirate.send(association_setter, @alternate_params[association_getter].values)
  @pirate.save
  assert_equal ["Grace OMalley", "Privateers Greed"], [@child_1.reload.name, @child_2.reload.name]
end
test_should_update_existing_records_and_add_new_ones_that_have_no_id() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 767
def test_should_update_existing_records_and_add_new_ones_that_have_no_id
  @alternate_params[association_getter]["baz"] = { name: "Buccaneers Servant" }
  assert_difference("@pirate.send(@association_name).count", +1) do
    @pirate.update @alternate_params
  end
  assert_equal ["Grace OMalley", "Privateers Greed", "Buccaneers Servant"].to_set, @pirate.reload.send(@association_name).map(&:name).to_set
end
test_should_work_with_update_as_well() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 760
def test_should_work_with_update_as_well
  @pirate.update(catchphrase: "Arr",
    association_getter => { "foo" => { id: @child_1.id, name: "Grace OMalley" } })

  assert_equal "Grace OMalley", @child_1.reload.name
end
test_validate_presence_of_parent_works_with_inverse_of() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 808
def test_validate_presence_of_parent_works_with_inverse_of
  Man.accepts_nested_attributes_for(:interests)
  assert_equal :man, Man.reflect_on_association(:interests).options[:inverse_of]
  assert_equal :interests, Interest.reflect_on_association(:man).options[:inverse_of]

  repair_validations(Interest) do
    Interest.validates_presence_of(:man)
    assert_difference "Man.count" do
      assert_difference "Interest.count", 2 do
        man = Man.create!(name: "John",
                          interests_attributes: [{ topic: "Cars" }, { topic: "Sports" }])
        assert_equal 2, man.interests.count
      end
    end
  end
end

Private Instance Methods

association_getter() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 848
def association_getter
  @association_getter ||= "#{@association_name}_attributes".to_sym
end
association_setter() click to toggle source
# File activerecord/test/cases/nested_attributes_test.rb, line 844
def association_setter
  @association_setter ||= "#{@association_name}_attributes=".to_sym
end