Remis07
Remis07

Reputation: 377

Trying to make a form using nested attributes

I'm a beginner in rails, so I'm quite stuck with the nested attributes.

Here is an overview of what I'm looking for:

A rentalcar can create cars.(done)

Clients can reserve a car.

Clients are created with the reservation at the same time by the rentalcar.

I'm trying to make a form for reservation which will contain both the client and the reservation information, since it will be the rentalcar who fill all the information.

It's why i need to use nested attributes, but until now I'm having some difficulties. I have four models:

class Car < ActiveRecord::Base
  belongs_to :rentalcar
  has_many :photos
  has_many :reservations
end 

.

class Client < ActiveRecord::Base
 has_many :reservations
end 

.

class Reservation < ActiveRecord::Base
 belongs_to :client
 belongs_to :car
end 

.

class rentalcar < ActiveRecord::Base
 has_many :cars
 has_many :reservations
end 

The form :

<%= form_for([@car, @car.reservations.new]) do |f| %>
<div class="row">
    <div class="col-md-12 price_tag">
        <span><%= @car.price %>Dhs</span>
        <span class="pull-right">Par jour</span>
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <label>Nom</label>
        <%= f.text_field :nom, placeholder: 'Nom', class: 'form-control' %>     
    </div>
    <div class="col-md-6">
        <label>Prenom</label>
        <%= f.text_field :prenom, placeholder: 'Prenom', class: 'form-control', disabled: 'true' %>     
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <label>CIN</label>
        <%= f.text_field :cin, placeholder: 'CIN', class: 'form-control' %>     
    </div>
    <div class="col-md-6">
        <label>Age</label>
        <%= f.text_field :age, placeholder: 'Age', class: 'form-control', disabled: 'true' %>       
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <label>Ville</label>
        <%= f.text_field :ville, placeholder: 'Ville', class: 'form-control' %>     
    </div>
    <div class="col-md-6">
        <label>Télephone</label>
        <%= f.text_field :telephone, placeholder: 'Telephone', class: 'form-control', disabled: 'true' %>       
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <label>Email</label>
        <%= f.text_field :email, placeholder: 'Email', class: 'form-control' %>     
    </div>
</div>

<%= f.fields_for :reservations do |reservation_form| %>

<div class="row">
    <div class="col-md-6">
        <label>Check In</label>
        <%= reservation_form.text_field :start_date, readonly: 'true', placeholder: 'Start Date', class: 'form-control' %>      
    </div>
    <div class="col-md-6">
        <label>Check Out</label>
        <%= reservation_form.text_field :end_date, readonly: 'true', placeholder: 'End Date', class: 'form-control', disabled: 'true' %>        
    </div>
</div>

<%= reservation_form.hidden_field :car_id, value: @car.id %>
<%= reservation_form.hidden_field :price, value: @car.prix %>
<%= reservation_form.hidden_field :total, id: 'reservation_total' %>

<% end %>

<h4><span id="message"></span></h4>

<div id="preview" style="display: none">
    <table class="reservation-table" >
        <tbody>
            <tr>
                <td>Day(s)</td>
                <td><span id="reservation_days"></span></td>
            </tr>
            <tr>
                <td>Total</td>
                <td><span id="reservation_sum"></span>Dhs</td>
            </tr>
        </tbody>
    </table>
    <br>
</div>

<br>
<%= f.submit "Book Now", id:"btn_book", class: "btn btn-primary wide", disabled: 'true' %>

So the idea is to get this form after doing something like : cars/1/reservate. And we will have something like this in the controller:

def reservate
 @car = Car.find(params[:id])
 @client = Client.new
 @client.reservations.build
end 

but i dont know in which controller it should remains

Edit1 :

Indexes :

add_index "reservations", ["client_id"], name: "index_reservations_on_client_id", using: :btree 

add_index "reservations", ["car_id"], name: "index_reservations_on_car_id", using: :btree 

add_index "voitures", ["rentelcar_id"], name: "index_voitures_on_rentelcar_id", using: :btree

add_foreign_key "reservations", "clients"
add_foreign_key "reservations", "cars"
add_foreign_key "cars", "rentelcars"

Upvotes: 0

Views: 89

Answers (1)

Saad
Saad

Reputation: 1902

I believe your relationships are a bit messed up, this is how I created new relations.

class AddRelevantModels < ActiveRecord::Migration
  def change
    create_table :car_rentals do |t|
      t.string      :name
      t.timestamps  null: false
    end

    create_table :cars do |t|
      t.string      :model
      t.string      :car_number
      t.belongs_to  :car_rental, index: true, foreign_key: true
      t.timestamps  null: false
    end

    create_table :clients do |t|
      t.string      :full_name
      t.integer     :age
      t.string      :email
      t.string      :phone_number
      t.timestamps  null: false
    end

    create_table :reservations do |t|
      t.belongs_to    :car, index: true, foreign_key: true
      t.belongs_to    :client, index: true, foreign_key: true
      t.datetime      :start_date
      t.datetime      :end_date
      t.timestamps    null: false
    end
  end
end

car_rental.rb

class CarRental < ActiveRecord::Base
  has_many :cars
end

car.rb

class Car < ActiveRecord::Base
  has_many :reservations
  has_many :clients, through: :reservations
end

reservation.rb

class Reservation < ActiveRecord::Base 
  belongs_to :client
  belongs_to :car

  accepts_nested_attributes_for :client
  accepts_nested_attributes_for :car
end

client.rb

class Client < ActiveRecord::Base
  has_many :reservations
  has_many :cars, through: :reservations
end

reservations_controller.rb

class ReservationsController < ApplicationController
  def new
    @reservation = Reservation.new
    @reservation.build_client
  end

  def create
    @reversation = Reservation.new(reservation_params)

    if @reversation.save
      render :show, id: @reservation
    else
      render :new
    end
  end

  private

  def reservation_params
    params.require(:reservation)
    .permit(
      :start_date, :end_date, client_attributes: [:full_name, :age, :email, :phone_number]
    )
  end
end

reservations/new.html.erb

<h1>Reservations</h1>
<%= form_for(@reservation) do |f| %>
  <%= f.label :start_date %>
  <%= f.text_field :start_date %>
  <br>
  <%= f.label :end_date %>
  <%= f.text_field :end_date %>
  <br>
  <%= f.fields_for :client do |client_field| %>
    <%= client_field.label :full_name %>
    <%= client_field.text_field :full_name %>
    <br>  
    <%= client_field.label :age %>
    <%= client_field.text_field :age %>
    <br>   
    <%= client_field.label :email %>
    <%= client_field.text_field :email %>
    <br>
    <%= client_field.label :phone_number %>
    <%= client_field.text_field :phone_number %>
  <% end %>

  <br>
  <%= f.submit %>
<% end %>

Now if you submit the form you can see in your database that the client is also saved for the reservation.

 Reservation.first.client
  Reservation Load (0.5ms)  SELECT  "reservations".* FROM "reservations"   ORDER BY "reservations"."id" ASC LIMIT 1
  Client Load (0.4ms)  SELECT  "clients".* FROM "clients"  WHERE "clients"."id" = $1 LIMIT 1  [["id", 1]]
 => #<Client id: 1, full_name: "remis", age: 22, email: "[email protected]", phone_number: "1231331", created_at: "2016-06-13 06:28:37", updated_at: "2016-06-13 06:28:37">

Upvotes: 1

Related Questions