0

I've been trying to enter nested attributes into my database but I can't manage to get it working.

I have these parameters:

def domain_register_whois_contact_parameters
  params.require(:domain).permit( whois_contacts_attributes: [:id, :first_name, :last_name, :street, :number, :postal_code, :city, :phone_number, :email_address, :company_type_id, :company_kvk, :company_name, :country_id])
end

These the input params:

{"utf8"=>"✓",
 "authenticity_token"=>"P4WTxAHKLgeRUQq60JvD/uMjo0s2BdMtqlBr1B6Z2hQ=",
 "domain"=>{"domain_name"=>"test.com",
 "whois_contacts_attributes"=>{"0"=>{"first_name"=>"Edward",
 "last_name"=>"Doe",
 "street"=>"Broadway",
 "number"=>"1",
 "postal_code"=>"1234AB",
 "city"=>"Amsterdam",
 "country_id"=>"205",
 "phone_number"=>"316123465",
 "email_address"=>"email@email.com",
 "company_name"=>"",
 "company_kvk"=>"",
 "company_type_id"=>""}},
 "nameserver_first"=>"ns1.dns.com",
 "nameserver_second"=>"ns2.dns.com"},
 "commit"=>"Register domain"}

I'm getting errors like this: param not found: whois_contacts_attributes

Have Googled lots of examples, but it doesn't work.

In my model I have:

accepts_nested_attributes_for :whois_contacts

And my view:

<%= f.simple_fields_for :whois_contacts, @domain.whois_contacts.new do |wc| %>
    <%= wc.input :first_name, input_html: { placeholder: "John" } %>
    <%= wc.input :last_name, input_html: { placeholder: "Doe" } %>

    <%= wc.input :street, input_html: { placeholder: "Main street" } %>
    <%= wc.input :number, input_html: { placeholder: "1" } %>
    <%= wc.input :postal_code, input_html: { placeholder: "1234AB" } %>
    <%= wc.input :city, input_html: { placeholder: "Amsterdam" } %>

    <div class="form-group select required domain_country_country_name">
        <label class="select required form-label" for="domain_country_country_name">
            <abbr title="required">*</abbr> Country
        </label>
        <div class="controls">
            <%= wc.collection_select :country_id, Country.all, :id, :full_name, {}, {:class=>'select required form-control'} %>
        </div>
    </div>

    <%= wc.input :phone_number, input_html: { placeholder: "0612345678" } %>
    <%= wc.input :email_address, input_html: { placeholder: "doe@johndoe.com" } %>

    <h3>Company information</h3>
    <%= wc.input :company_name, hint: 'If you have a company, please enter the company name.', input_html: { placeholder: "Doe Inc." } %>
    <%= wc.input :company_kvk, hint: 'Enter Chamber of Commerce (Kvk) number', input_html: { placeholder: "12345678" } %>

    <div class="form-group select required domain_company_company_name">
        <label class="select required form-label" for="domain_company_companyname">
            <abbr title="required">*</abbr> Company
        </label>
        <div class="controls">
            <%= wc.collection_select :company_type_id, CompanyType.all, :id, :full_name, {}, {:class=>'select required form-control'} %>
        </div>
    </div>
<% end %>
edwardmp
  • 6,339
  • 5
  • 50
  • 77
  • I'm going to go out on a limb and blame your params. I really like the whitelisting of params that Rails 4 moved to, but they could have made the interface for the whitelisting more user friendly. I have dug into it, answered questions about it, and I STILL don't truly understand how it works. Take a look at the answer I gave here: http://stackoverflow.com/questions/19189602/unpermitted-parameters-for-dynamic-forms-in-rails-4/19194274#19194274 I think your problem is the opposite though. You are coding for an array in the `permit` statement but you are getting nested hashes in your params. – Beartech Dec 09 '13 at 03:24
  • I'm thinking `"whois_contacts_attributes"=>{"0"=>{"first_name"=>"Edward",` should be returning as something more like: `"whois_contacts_attributes"=> {"first_name"=>"Edward",...`. This points out my second weakness, the simple_fields_for API. It's a bit of a black box for me so I don't really understand how to get the params I want out of it. Can you do a controller action for that form that just prints out the params the form is returning, in a view? That's how I hunted down some of these params mysteries in the past. – Beartech Dec 09 '13 at 03:35

1 Answers1

2

There are 3 things I would do differently.

1 Build your record in the controller

def new
  @domain = Domain.new
  @domain.whois_contacts.build
end

2 Whitelist on the same method call

def domain_params
  params.require(:domain).permit(:domain_name, :nameserver_first, :nameserver_second, whois_contacts_attributes: [:id, :first_name, :last_name, :street, :number, :postal_code, :city, :phone_number, :email_address, :company_type_id, :company_kvk, :company_name, :country_id])        
end

3 Adjust the form for better build statement

<%= f.simple_fields_for :whois_contacts do |wc| %>
  <%= wc.input :first_name, input_html: { placeholder: "John" } %>
  <%= wc.input :last_name, input_html: { placeholder: "Doe" } %>

  <%= wc.input :street, input_html: { placeholder: "Main street" } %>
  <%= wc.input :number, input_html: { placeholder: "1" } %>
  <%= wc.input :postal_code, input_html: { placeholder: "1234AB" } %>
  <%= wc.input :city, input_html: { placeholder: "Amsterdam" } %>

  <div class="form-group select required domain_country_country_name">
    <label class="select required form-label" for="domain_country_country_name">
      <abbr title="required">*</abbr> Country
    </label>
    <div class="controls">
      <%= wc.collection_select :country_id, Country.all, :id, :full_name, {}, {:class=>'select required form-control'} %>
    </div>
  </div>

  <%= wc.input :phone_number, input_html: { placeholder: "0612345678" } %>
  <%= wc.input :email_address, input_html: { placeholder: "doe@johndoe.com" } %>

  <h3>Company information</h3>
  <%= wc.input :company_name, hint: 'If you have a company, please enter the company name.', input_html: { placeholder: "Doe Inc." } %>
  <%= wc.input :company_kvk, hint: 'Enter Chamber of Commerce (Kvk) number', input_html: { placeholder: "12345678" } %>

  <div class="form-group select required domain_company_company_name">
    <label class="select required form-label" for="domain_company_companyname">
      <abbr title="required">*</abbr> Company
    </label>
    <div class="controls">
      <%= wc.collection_select :company_type_id, CompanyType.all, :id, :full_name, {}, {:class=>'select required form-control'} %>
    </div>
  </div>
<% end %>
trh
  • 7,186
  • 2
  • 29
  • 41
  • Thanks for the reply. This produces the error `unknown attribute: domain_name` unfortunately – edwardmp Dec 09 '13 at 10:38
  • So i set up a dummy project with the information i have (minus the domain part of the form and the rest of your controller obviously) and I don't get that error. You can look at the differences and see if you can identify your issue (there are a few changes, company_kvm was omitted by accident, and country and company_type are using name instead of full_name so be careful with cut and paste) https://github.com/trh/rails-nested-fieldsfor-example – trh Dec 09 '13 at 14:58
  • Hey thanks for all your effort. I actually needed to build 3 times (for three types of contacts) and I now succeed. All those contacts are now created instantly which is great! Only thing left is that in the whois_contacts I have a column user_id which doesn't get set yet. I could make it a hidden field in the form but that wouldn't be good practice out of security standpoint. Any idea's? – edwardmp Dec 09 '13 at 15:09
  • I would set it in the controller when you do a create (or update as updating can potentially add new nested records) `@domain = Domain.new(domain_params.merge(user_id: current_user.id)` or something similar – trh Dec 09 '13 at 15:38
  • Yes I read that somewhere. But it is not in the domains table but in the nested attribute tabel so merge won't work that way. Fixed it for now by looping through he contacts after insert and updating it manually. – edwardmp Dec 09 '13 at 17:24