Mritunjay Upadhyay
Mritunjay Upadhyay

Reputation: 1094

undefined method `appointments_path' using nested resource

I have a nested resource appointments in profiles in route.rb.

resources :profiles, only: [:show, :update, :edit] do
 resources :appointments
end  

In my AppointmentsController.rb I write new method like this

   def new
    @appointment = Appointment.new
   end     

I have form for this new method in appointments/new.html.erb

   <section class="login-page border-top-blue padding-v-10">
    <section class="login-details-div bg-light-grey">

    <%= form_for(@appointment, :html => { :class => 'form-horizontal login-form-container login-form-div' }) do |f| %>

    <h1>Create New Appointments</h1>

    <div class="form-div-send-for-inlinement-icon-with-text-field">
    <span class="form-wrapper ">
        <i class="fa fa-user login-icon-white login-icon-envelop "></i>
    </span>
      <div class="label-input-div input-width">
        <label for="" class="login-label-div"></label>
        <div class="form-wrapper"><%= f.text_area :description, class:'login-icon-white', autofocus: true %></div>
      </div>

    </div>

    <div class="form-div-send-for-inlinement-icon-with-text-field">
    <span class="form-wrapper ">
        <i class="fa fa-envelope login-icon-white login-icon-envelop "></i>
    </span>
      <div class="label-input-div input-width">
        <label for="" class="login-label-div">topic</label>
        <div class="form-wrapper"><%= f.text_field :topic, class:'login-icon-white' %></div>
      </div>

    </div>

    <div class="form-div-send-for-inlinement-icon-with-text-field">
    <span class="form-wrapper ">
        <i class="fa fa-envelope login-icon-white login-icon-envelop "></i>
    </span>
      <div class="label-input-div input-width">
        <label for="" class="login-label-div">Appointment Date</label>
        <div class="form-wrapper"><%= f.date_field :appointment_date, class:'login-icon-white' %></div>
      </div>

    </div>

    <div class="form-div-send-for-inlinement-icon-with-text-field">
    <span class="form-wrapper ">
        <i class="fa fa-envelope login-icon-white login-icon-envelop "></i>
    </span>
      <div class="label-input-div input-width">
        <label for="" class="login-label-div">class hours</label>
        <div class="form-wrapper"><%= f.number_field :class_hours, class:'login-icon-white' %></div>
      </div>

    </div>



    <div class="form-group">
      <label for="" class="col-sm-offset-2 col-sm-10 col-xs-offset-2 col-xs-10 col-md-offset-1 col-md-11 login-btn-div">

        <%= f.submit "submit", :class => "login-btn" %>
      </label>
      <label for="" class="col-sm-offset-2 col-sm-10 col-xs-offset-2 col-xs-10 col-md-offset-1 col-md-11 login-btn-div">

        <%= link_to "Cancel", root_path(), :class => "login-btn" %>
      </label>
    </div>

  <% end %> 
   </section>
    </section>

I have a link tag in profiles/show.html.erb for callling this new method of AppointmentsController.rb .

      <%= link_to "book a class", new_profile_appointment_path, class: 'btn-green2' %>

I don't understand why whenever I click this link I got link in url

http://localhost:3000/profiles/3/appointments/new 

which is I need.But there is an error undefined method 'appointments_path' for #<#<Class:0x007f24ccc16bf8>:0x007f24ccc154b0>

I could not figure out my fault here.Please help.

Upvotes: 1

Views: 163

Answers (3)

Neeraj Rana
Neeraj Rana

Reputation: 452

As you are using nested resources for creating every appointment you need a profile under which your appointment will be nested. So you need to pass profile_id under which your appointment will be created as your path new_profile_appointment_path is also saying.

<%= form_for([@profile, @appointment], :html => { :class => 'form-horizontal login-form-container login-form-div' }) do |f| %>

You also need to define @profile in your method.

   def new
     @profile = Profile.find(params[:profile_id])
     @appointment = Appointment.new
   end

Upvotes: 1

SteveTurczyn
SteveTurczyn

Reputation: 36860

form_for tries to use existing paths. You don't have an appointments_path but you do have an profile_appointments_path

To use that path, just pass both objects to the form_for

<%= form_for([@profile, @appointment], :html => { :class => 'form-horizontal login-form-container login-form-div' }) do |f| %>

However, this does mean you need to create an instance variable @profile in your new method...

   def new
     @profile = Profile.find(params[:profile_id])
     @appointment = Appointment.new
   end

Upvotes: 1

lightalloy
lightalloy

Reputation: 1165

Url in your form should be smth like this:

<%= form_for [@profile, @appointment] do |f| %>
  ...
<% end %>

Upvotes: 1

Related Questions