Pranav Ganorkar
Pranav Ganorkar

Reputation: 45

Rails: Nested form for many-to-one relation

I have two models: Interview and Interviewee.

There is a many to one relation between Interview and Interviewee.

I want to be able to add a new Interviewee when creating a new Interview using /interviews/new route. If the Interviewee was already present, the newly created interview should be linked to it.

In other words, I want to create a nested form for "belongs_to" relation. Precisely, creating a parent or linking to an existing one using the form for it's child. Here is my code:

interview.rb

class Interview < ApplicationRecord
 belongs_to :interviewee, inverse_of: :interviews
 has_many :meetings
 has_many :interviewers, through: :meetings
 accepts_nested_attributes_for :interviewee
 accepts_nested_attributes_for :interviewers
end

interviewee.rb

class Interviewee < ApplicationRecord
 has_many :interviews, inverse_of: :interviewee
end

Interviews Controller

class InterviewsController < ApplicationController
    def index
        @interviews = Interview.all
    end

    def new
        @interview = Interview.new
        #2.times {@interview.interviewers.build}
        @interview.interviewers.build
        #@interview.interviewee.build
    end

    def create
        #render plain: params[:interview].inspect
        @interview = Interview.new(interview_params)

        @interview.save
        redirect_to @interview
    end

    private
        def interview_params
            params.require(:interview).permit(
                :title, :date, :start_time, :end_time,
                interviewee_attributes: [:id, :email],
                interviewers_attributes: [:id, :email]
            )
        end
end

interview - new.html.erb

<h1>Schedule a New Interview</h1>

<%= form_for @interview, url: interviews_path do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :date %><br>
    <%= f.date_field :date %>
  </p>

  <p>
    <%= f.label :start_time %><br>
    <%= f.time_field :start_time %>
  </p>

  <p>
    <%= f.label :end_time %><br>
    <%= f.time_field :end_time %>
  </p>

  <%= f.fields_for :interviewee do |interviewee| %>
    <p>
        Interviewee Email:<br>
        <%= interviewee.text_field :email %>
    </p>
  <% end %>

  <%= f.fields_for :interviewers do |interviewer| %>
    <p>
        Interviewer Emails:<br>
        <%= interviewer.text_area :email %>
    </p>
  <% end %>

  <p>
    <%= f.submit %>
  </p>
<% end %>

For some reason, the email textbox for Interviewee is not shown in the view. At the same time, textbox for Interviewers (many to many with Interview) is shown. Can anyone shed some light on this ? I couldn't find out about how to do this in the official Rails "Form-helpers" guide.

Upvotes: 2

Views: 638

Answers (1)

Pavan
Pavan

Reputation: 33552

For some reason, the email textbox for Interviewee is not shown in the view.

You need to build the nested object in the new method.

def new
  @interview = Interview.new
  #2.times {@interview.interviewers.build}
  @interview.interviewers.build
  @interview.build_interviewee #here
end

so that @interview will contain attributes of nested association and then those will be available for the form builder

Alternatively, you can also do it like below

<%= f.fields_for :interviewee, @interview.build_interviewee do |interviewee| %>

Upvotes: 2

Related Questions