def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
      options = self.nested_attributes_options[association_name]

      unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
        raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
      end

      if options[:limit] && attributes_collection.size > options[:limit]
        raise TooManyRecords, "Maximum #{options[:limit]} records are allowed. Got #{attributes_collection.size} records instead."
      end

      if attributes_collection.is_a? Hash
        keys = attributes_collection.keys
        attributes_collection = if keys.include?('id') || keys.include?(:id)
          Array.wrap(attributes_collection)
        else
          attributes_collection.values
        end
      end

      association = association(association_name)

      existing_records = if association.loaded?
        association.target
      else
        attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
        attribute_ids.empty? ? [] : association.scoped.where(association.klass.primary_key => attribute_ids)
      end

      attributes_collection.each do |attributes|
        attributes = attributes.with_indifferent_access

        if attributes['id'].blank?
          unless reject_new_record?(association_name, attributes)
            association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
          end
        elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
          unless association.loaded? || call_reject_if(association_name, attributes)
            # Make sure we are operating on the actual object which is in the association's
            # proxy_target array (either by finding it, or adding it if not found)
            target_record = association.target.detect { |record| record == existing_record }

            if target_record
              existing_record = target_record
            else
              association.add_to_target(existing_record)
            end

          end

          if !call_reject_if(association_name, attributes)
            assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy], assignment_opts)
          end
        elsif assignment_opts[:without_protection]
          association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
        else
          raise_nested_attributes_record_not_found(association_name, attributes['id'])
        end
      end
    end
def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
      options = self.nested_attributes_options[association_name]

      unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
        raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
      end

      if options[:limit] && attributes_collection.size > options[:limit]
        raise TooManyRecords, "Maximum #{options[:limit]} records are allowed. Got #{attributes_collection.size} records instead."
      end

      if attributes_collection.is_a? Hash
        keys = attributes_collection.keys
        attributes_collection = if keys.include?('id') || keys.include?(:id)
          Array.wrap(attributes_collection)
        else
          attributes_collection.values
        end
      end

      association = association(association_name)

      existing_records = if association.loaded?
        association.target
      else
        attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
        attribute_ids.empty? ? [] : association.scoped.where(association.klass.primary_key => attribute_ids)
      end

      attributes_collection.each do |attributes|
        attributes = attributes.with_indifferent_access

        if attributes['id'].blank?
          unless reject_new_record?(association_name, attributes)
            association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
          end
        elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
          unless association.loaded? || call_reject_if(association_name, attributes)
            # Make sure we are operating on the actual object which is in the association's
            # proxy_target array (either by finding it, or adding it if not found)
            target_record = association.target.detect { |record| record == existing_record }

            if target_record
              existing_record = target_record
            else
              association.add_to_target(existing_record)
            end

          end

          if !call_reject_if(association_name, attributes)
            assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy], assignment_opts)
          end
        elsif assignment_opts[:without_protection]
          association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
        else
          raise_nested_attributes_record_not_found(association_name, attributes['id'])
        end
      end
    end
Assigns the given attributes to the collection association.

 Hashes with an <tt>:id</tt> value matching an existing associated record
 will update that record. Hashes without an <tt>:id</tt> value will build
 a new record for the association. Hashes with a matching <tt>:id</tt>
 value and a <tt>:_destroy</tt> key set to a truthy value will mark the
 matched record for destruction.

 For example:

   assign_nested_attributes_for_collection_association(:people, {
     '1' => { :id => '1', :name => 'Peter' },
     '2' => { :name => 'John' },
     '3' => { :id => '2', :_destroy => true }
   })

 Will update the name of the Person with ID 1, build a new associated
 person with the name `John', and mark the associated Person with ID 2
 for destruction.

 Also accepts an Array of attribute hashes:

   assign_nested_attributes_for_collection_association(:people, [
     { :id => '1', :name => 'Peter' },
     { :name => 'John' },
     { :id => '2', :_destroy => true }
   ])