Rails 4: form_for with nested model

1.4k views Asked by At

I have three models: Client, Car, and ParkingRate. Client has many cars, and car has many parking_rates. I have a form on the client page that creates a car associated with that client. What I don't know how to do is to add a field for parking_rate to that form, so that when a car is created for that client, a parking rate is also created for that car.

My code looks like:

client.rb

class Client < ActiveRecord::Base
  has_many :cars, dependent: destroy
end

car.rb

class Car < ActiveRecord::Base
  belongs_to :client
  has_many :parking_rates
end

parking_rate.rb

class ParkingRate < ActiveRecord::Base
  belongs_to :car
end

On the client page (client/:id), I have a form to create a car associated with that client, like this:

views/clients/show.html.erb:

<h1>Client information</h1>
... client info ...
<%= render 'cars/form' %>

views/cars/_form.html.erb:

<%= form_for([@client, @client.cars.build]) do |f| %>
  <p>
    <%= f.label :vehicle_id_number %><br>
    <%= f.text_field :vehicle_id_number %>
  </p>
  <p>
    <%= f.label :enter_date %><br>
    <%= f.text_field :enter_date %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

The Clients and Cars controllers look like this:

clients_controller.rb:

class ClientsController < ApplicationController

def new
  @client = Client.new
end

def create
  @client = Client.new(client_params)
  if @client.save
    redirect_to @client
  else
    render 'new'
  end
end

def show
  @client = Client.find(params[:id])
end

def index
  @clients = Client.all
end

def edit
  @client = Client.find(params[:id])
end

def update
  @client = Client.find(params[:id])

  if @client.update(client_params)
    redirect_to @client
  else
    render 'edit'
  end
end

def destroy
  @client = Client.find(params[:id])
  @client.destroy

  redirect_to clients_path
end

private
  def client_params
    params.require(:client).permit(:first_name, :last_name)
  end
end

cars_controller.rb:

class CarsController < ApplicationController

def create
  @client = Client.find(params[:client_id])
  @car = @client.cars.create(car_params)
  @parking_rate = @car.parking_rates.create(rate_params)
  redirect_to client_path(@client)
end

def show
  @client = Client.find(params[:client_id])
  @car = Car.find(params[:id])
end

def edit
  @client = Client.find(params[:client_id])
  @car = Car.find(params[:id])
end

def update
  @client = Client.find(params[:client_id])
  @car = Car.find(params[:id])
  @car.update(car_params)

  redirect_to client_path(@client)
end

def destroy
  @client = Client.find(params[:client_id])
  @car = @client.cars.find(params[:id])
  @car.destroy
  redirect_to client_path(@client)
end

private
  def car_params
    params.require(:car).permit(:vehicle_id_number, :enter_date, :rate)
  end

  def rate_params
    params.require(:parking_rate).permit(:rate)
  end
end

With this I am able to add cars to a given client, but I would also like to add a parking_rate to a car on the same form. So right when I create a car using this form, I want to create an associated parking rate. The form_for helper uses a [@client, @client.comments.build] as the model object, so I am not sure how to reference the parking_rate model in the same form. I think the solution is to use a fields_for helper, what would be the model reference for that, and what would I need to add to the cars and client controllers?

1

There are 1 answers

0
ewi On

In client.rb, add the line

accepts_nested_attributes_for :cars