Rails has_many :through nested form

has-many-through, nested-forms, ruby-on-rails

Solution

Ok, this little bugger of a question stumped me for a few hours, so I'm going to post my working solution on here in hopes it shaves some time for peeps. This is for Rails 4.0 and Ruby 2.0. This also overcame a "symbol to integer conversion" issue I had.

Models:

class Patient < ActiveRecord::Base 
  has_many :appointments
  has_many :physicians, through: :appointments
  accepts_nested_attributes_for :appointments
end 
   
class Appointment < ActiveRecord::Base
  belongs_to :physician 
  belongs_to :patient
  accepts_nested_attributes_for :physician
end

class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, through: :appointments
end

Controller:

# patients_controller.rb
def new
  @patient= Patient.new 
  @appointments = @patient.appointments.build
  @physician = @appointments.build_physician 
end

def create
  Patient.new(patient_params)
end


def patient_params
   params.require(:patient).permit(:id, appointments_attributes: [:id, :appointment_time, physician_attributes: [:id ] )
end

View

<% form_for(@patient) do |patient_form| %>
  <%= patient_form.error_messages %>
  <p>
    <%= patient_form.label :name, "Patient Name" %>
    <%= patient_form.text_field :name %>
  </p>

  <% patient_form.fields_for :appointments do |appointment_form| %>
    <p>
      <%= appointment_form.label :appointment_date, "Appointment Date" %>
      <%= appointment_form.date_field :appointment_date %>
    </p>

    <% appointment_form.fields_for :physician do |physician_form| %>
      <p>
        <%= physician_form.label :name, "Physician Name" %>
        <%= physician_form.text_field :name %>
      </p>
    <% end %>
  <% end %>

  <p>
    <%= patient_form.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', patients_path %>

Problem

I have just jumped into `has_many :through` association. I'm trying to implement the ability to save data for all 3 tables (`Physician`, `Patient` and association table) through a single form. My migrations: ``` class CreatePhysicians < ActiveRecord::Migration def self.up create_table :physicians do |t| t.string :name t.timestamps end end end class CreatePatients < ActiveRecord::Migration def self.up create_table :patients do |t| t.string :name t.timestamps end end end class CreateAppointments < ActiveRecord::Migration def self.up create_table :appointments do |t| t.integer :physician_id t.integer :patient_id t.date :appointment_date t.timestamps end end end ``` My models: ``` class Patient < ActiveRecord::Base has_many :appointments has_many :physicians, :through => :appointments accepts_nested_attributes_for :appointments accepts_nested_attributes_for :physicians end class Physician < ActiveRecord::Base has_many :appointments has_many :patients, :through => :appointments accepts_nested_attributes_for :patients accepts_nested_attributes_for :appointments end class Appointment < ActiveRecord::Base belongs_to :physician belongs_to :patient end ``` My controller: ``` def new @patient = Patient.new @patient.physicians.build @patient.appointments.build end ``` My view (`new.html.rb`): ``` <% form_for(@patient) do |patient_form| %> <%= patient_form.error_messages %> <p> <%= patient_form.label :name, "Patient Name" %> <%= patient_form.text_field :name %> </p> <% patient_form.fields_for :physicians do |physician_form| %> <p> <%= physician_form.label :name, "Physician Name" %> <%= physician_form.text_field :name %> </p> <% end %> <p> <%= patient_form.submit 'Create' %> </p> <% end %> <%= link_to 'Back', patients_path %> ``` I'm able to create a new `Patient`, `Physician` and associated record for an `Appointment`, but now I want to have field for `appointment_date` too in form. Where should I place fields for `Appointment`s and what changes are required in my controller? I tried googling and tried this, but got stuck in some or other error implementing it.

Original source

Related problems