grace
grace

Reputation: 165

Rails 5 Create Multiple Records of Same Model in One Form, Unknown Attribute Error

I need to make a form that can handle the creation of multiple records of the same model, and submit the information in a way that passes through Rails’ Strong Parameters. On the front-end, I dynamically add two new text fields for puppy name and breed and want to save them all to a form. But I'm having trouble passing the array of puppy name and breed through Strong Params; getting

unknown attribute ‘puppies’ for Puppy

I think it's something very simple I'm overlooking. Please help generate these puppies!

new.html.erb

<%= form_tag puppies_path do %>
 <%= text_field_tag “puppies[puppies][]puppy[name]” %>
 <%= text_field_tag “puppies[puppies][]puppy[breed]” %>
 <%= submit_tag “Add Puppy” %>
<% end %>

which generates these parameters

"puppies"=>{"puppies"=>[{"puppy"=>{"name"=>"ribbon", "breed"=>"poodle"}}]}

and the Strong Params in the controller

class PuppiesController < ApplicationController
  def index
    @puppies = Puppy.all
  end

  def new
  end

  def create
    puppies_array = puppies_params[:puppies].each do |puppy|
                      puppy[:puppy]
                    end
    Puppy.create(puppies_array)
  end 

  def show
    @puppy = Puppy.find(params[:id])
  end  

  private
    def puppies_params
      params.require(:puppies).permit({ 
        puppies: [
          puppy: [
            :name, 
            :breed
          ] 
        ]
      })
    end  
end

Any ideas what I’m missing?

Pseudo code of what I want to pass through:

[(name, breed), (name, breed), (name, breed)]

How can I write it correctly? I'm following this tutorial https://medium.com/@dmccoy/how-to-build-html-inputs-to-submit-an-array-of-hashes-with-a-rails-form-tag-that-work-with-strong-f70a6c03d78e

Upvotes: 1

Views: 967

Answers (2)

SteveTurczyn
SteveTurczyn

Reputation: 36880

To get to the array of attributes that you want, you can do this:

puppies_array = puppies_params[:puppies][:puppy].map{|puppy| puppy.values}

This takes the hash puppies within puppy params, and takes the array of hashes in puppy and then takes just the value part of the hashes in that array.

You'll get your pseudo-code result.

For info, note that puppy in the map block has no special significance... it just indicates the instance of the array. You could just as easily do

puppies_array = puppies_params[:puppies][:puppy].map{|some_dog| some_dog.values}

Upvotes: 0

Chirag
Chirag

Reputation: 416

You haven't added rest of your controller code, but I am assuming you are using something like: Puppy.create(puppies_params)

But since you are nesting the params in your view, you will need to use Puppy.create(puppies_params[:puppies]) to ensure you are able to pass in the correct array of name and breed into the create action.

Edit Since puppies array contains a hash with puppy key, we will need to extract those to get the final array of puppy attributes.

def create
  puppies_array = puppies_params[:puppies].collect do |puppy|
                    puppy[:puppy]
                  end
  Puppy.create(puppies_array)
end

My comment below has a shorthand for setting puppies array, you can use whichever version looks more readable and understandable to you

Upvotes: 1

Related Questions