Skip to content

Commit 44ef49c

Browse files
authored
Merge pull request rails#50804 from joshuay03/consistently-raise-an-error-for-nested-attributes-args
[Fix rails#50803] Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer
2 parents 9c3ffab + 1eab83a commit 44ef49c

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

activerecord/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
* Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer.
2+
3+
Previously, this would only raise on collection associations and produce a generic error on singular associations.
4+
5+
Now, it will raise on both collection and singular associations.
6+
7+
*Joshua Young*
8+
19
* Fix single quote escapes on default generated MySQL columns
210

311
MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.

activerecord/lib/active_record/nested_attributes.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,15 @@ def _destroy
421421
# update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
422422
# then the existing record will be marked for destruction.
423423
def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
424-
options = nested_attributes_options[association_name]
425424
if attributes.respond_to?(:permitted?)
426425
attributes = attributes.to_h
427426
end
427+
428+
unless attributes.is_a?(Hash)
429+
raise ArgumentError, "Hash expected for `#{association_name}` attributes, got #{attributes.class.name}"
430+
end
431+
432+
options = nested_attributes_options[association_name]
428433
attributes = attributes.with_indifferent_access
429434
existing_record = send(association_name)
430435

@@ -486,7 +491,7 @@ def assign_nested_attributes_for_collection_association(association_name, attrib
486491
end
487492

488493
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
489-
raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
494+
raise ArgumentError, "Hash or Array expected for `#{association_name}` attributes, got #{attributes_collection.class.name}"
490495
end
491496

492497
check_record_limit!(options[:limit], attributes_collection)

activerecord/test/cases/nested_attributes_test.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,13 @@ def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is
422422

423423
Pirate.accepts_nested_attributes_for :update_only_ship, update_only: true, allow_destroy: false
424424
end
425+
426+
def test_should_raise_an_argument_error_if_something_other_than_a_hash_is_passed_in
427+
exception = assert_raise ArgumentError do
428+
@pirate.update(ship_attributes: "foo")
429+
end
430+
assert_equal "Hash expected for `ship` attributes, got String", exception.message
431+
end
425432
end
426433

427434
class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
@@ -598,6 +605,13 @@ def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is
598605

599606
Ship.accepts_nested_attributes_for :update_only_pirate, update_only: true, allow_destroy: false
600607
end
608+
609+
def test_should_raise_an_argument_error_if_something_other_than_a_hash_is_passed_in
610+
exception = assert_raise ArgumentError do
611+
@ship.update(pirate_attributes: "foo")
612+
end
613+
assert_equal "Hash expected for `pirate` attributes, got String", exception.message
614+
end
601615
end
602616

603617
module NestedAttributesOnACollectionAssociationTests
@@ -768,7 +782,7 @@ def test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed
768782
exception = assert_raise ArgumentError do
769783
@pirate.public_send(association_setter, "foo")
770784
end
771-
assert_equal %{Hash or Array expected for attribute `#{@association_name}`, got String ("foo")}, exception.message
785+
assert_equal %{Hash or Array expected for `#{@association_name}` attributes, got String}, exception.message
772786
end
773787

774788
def test_should_work_with_update_as_well

0 commit comments

Comments
 (0)