diff --git a/lib/mongoid/association/nested/many.rb b/lib/mongoid/association/nested/many.rb index f58503f8e0..077616f819 100644 --- a/lib/mongoid/association/nested/many.rb +++ b/lib/mongoid/association/nested/many.rb @@ -16,6 +16,9 @@ class Many # This attempts to perform 3 operations, either one of an update of # the existing association, a replacement of the association with a new # document, or a removal of the association. + # + # It raises an argument error if the attributes are not a Hash or an + # Array of key/value pairs. # # @example Build the nested attrs. # many.build(person) @@ -32,8 +35,12 @@ def build(parent, options = {}) attributes.each do |attrs| if attrs.is_a?(::Hash) process_attributes(parent, attrs.with_indifferent_access) - else + elsif attrs.is_a?(Array) && attrs.length > 1 && attrs[1].respond_to?(:with_indifferent_access) process_attributes(parent, attrs[1].with_indifferent_access) + elsif attrs.is_a?(Array) && attrs.length.even? + process_attributes(parent, Hash[*attrs].with_indifferent_access) + else + raise ArgumentError, "Attributes for nested association '#{association.name}' must be a Hash or an Array of key/value pairs." end end end diff --git a/spec/integration/associations/embeds_many_spec.rb b/spec/integration/associations/embeds_many_spec.rb index b4d9ff3623..b2d98b940d 100644 --- a/spec/integration/associations/embeds_many_spec.rb +++ b/spec/integration/associations/embeds_many_spec.rb @@ -327,4 +327,20 @@ class Comment end end end + + context "when a hash is provided instead of an array for an embeds_many association" do + let(:post) { EmbedsManySpec::Post.new(title: 'Broken post', comments: { content: 'Comment' }) } + + it "does not raise an error on initialization" do + expect { post }.to_not raise_error + end + + it "does not raise an error when accessing the association" do + expect { post.comments }.to_not raise_error + end + + it "allows building new documents on the association" do + expect(post.comments.build).to be_a EmbedsManySpec::Comment + end + end end