Search code examples
ruby-on-railsnested-formsrelationshipsmodel-associations

Could not save values in Nested forms using rails 5


I am stuck up with building nested forms using Ruby on Rails. I am trying to build a form which has fields from three tables(User, Contact, Address). User table has address_id and contact_id. When user fills the details, contact details should be saved in contact table and address should be saved in address table. Both the ids should get saved in user table along with the user details. How should I proceed?

My model,

class Address < ApplicationRecord
  has_one :user
end

class Contact < ApplicationRecord
  has_one :user
end

class User < ApplicationRecord
  belongs_to :address
  belongs_to :contact 
end

My controller,

class UsersController < ApplicationController
  def new
    @user = User.new
    @user.build_contact
    @user.build_address
  end
  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end
  private
  def user_params
    params.require(:user).permit(:name, :email, contact_attributes: [:phone], address_attributes: [:street, :city])
  end
end

And my view is,

<%= form_for(user) do |f| %>
  <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
      <ul>
      <% user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %>
    <%= f.text_field :name %>
 </div>

 <div class="field">
   <%= f.label :email %>
   <%= f.text_field :email %>
 </div>

 <%= f.fields_for :contact do |c| %>
   <div class="field">
     <%= c.label :phone %>
     <%= c.text_field :phone %>
   </div>
 <% end %>

 <%= f.fields_for :address do |a| %>
   <div class="field">
     <%= a.label :street %>
     <%= a.text_field :street %>
   </div>

   <div class="field">
     <%= a.label :city %>
     <%= a.text_field :city %>
   </div>
 <% end %>

 <div class="actions">
   <%= f.submit %>
 </div>
<% end %>

Is my approach right? Kindly please suggest. Thanks in advance.


Solution

  • You missing a couple of lines...

    class User < ApplicationRecord
      belongs_to :address
      belongs_to :contact
      accepts_nested_attributes_for :address
      accepts_nested_attributes_for :contact 
    end
    

    Also ensure you accept :id and :_delete

    params.require(:user).permit(:name, :email, contact_attributes: [:id, :phone, :_delete], address_attributes: [:id, :street, :city, :_delete]