1

I am trying to create a new teacher for a specific school in my project and I got this error:

No route matches [POST] "/schools/3/teachers/new"

Here is my teachers_controller.rb:

class TeachersController < ApplicationController
  def new
    @teacher = Teacher.new
  end

  def create
    @teacher = Teacher.new(teacher_params)
    @teacher.save

    redirect_to school_path(school)
  end

  private

    def teacher_params
      params.require(:teacher).permit(:firstName, :lastName, :middleName)
    end
end

schools_controller.rb:

class SchoolsController < ApplicationController
  def show
    @school = School.find(params[:id])
  end

  def new
    @school = School.new
  end

  def edit
    @school = School.find(params[:id])
  end

  def update
    @school = School.find(params[:id])

    if @school.update(school_params)
      redirect_to @school
    else
      render 'edit'
    end
  end

  def index
    @schools = School.all
  end

  def create
    @school = School.new(school_params)

    if @school.save
      redirect_to schools_path
    else
      render 'new'
    end
  end

  def destroy
    @school = School.find(params[:id])
    @school.destroy

    redirect_to schools_path
  end

  private

    def school_params
      params.require(:school).permit(:name)
    end
end

routes.rb:

Rails.application.routes.draw do
  resources :schools do
    resources :teachers
  end

  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".

  # You can have the root of your site routed with "root"
  root 'welcome#index'

And teachers/new.html.erb:

<%= form_for :teacher, url: school_teachers_path(school) do |f| %>
  <p>
    <%= f.label :firstName %><br>
    <%= f.text_field :firstName %>
  </p>

  <p>
    <%= f.label :lastName %><br>
    <%= f.text_field :lastName %>
  </p>

  <p>
    <%= f.label :middleName %><br>
    <%= f.text_field :middleName %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>
K M Rakibul Islam
  • 33,760
  • 12
  • 89
  • 110
  • Do you get this error when you render the `new` page for creating a teacher? – Arslan Ali Nov 16 '15 at 05:34
  • Currently, I can see the form and fill out the information for the teacher: First name, last name, and middle name. Then, the error comes up. –  Nov 16 '15 at 05:47
  • Can you tell from where the `school` variable in `school_teachers_path(school)` coming from? – Pavan Nov 16 '15 at 06:03

3 Answers3

2

As your teacher resource is nested under the school resource, so you need to pass the school when you try to create a teacher.

Try changing your new and create actions in teachers_controller.rb to something like this:

  def new
    @school = School.find(params[:school_id])
    @teacher = @school.teachers.build
  end

  def create
    @school = School.find(params[:school_id])
    @teacher = @school.teachers.build(params[:teacher])
    @teacher.save
    redirect_to school_path(@school)
  end

And, then change your form to this:

<%= form_for([@school, @teacher]) do %>
. . .
. . .
<% end %>
K M Rakibul Islam
  • 33,760
  • 12
  • 89
  • 110
  • @Islam, thank you for your help. But, now I get this error: No route matches {:action=>"index", :controller=>"teachers", :school_id=>nil} missing required keys: [:school_id] –  Nov 16 '15 at 05:59
  • Add `school_id` to this in your controller: `params.require(:teacher).permit(:firstName, :lastName, :middleName, :school_id)`. But, still I am wondering why it's trying to route to the index action! – K M Rakibul Islam Nov 16 '15 at 06:03
  • The route expects a `school_id` as **key**. I can't see where you are passing it in your answer. – Pavan Nov 16 '15 at 06:11
  • I tried to add school_id as you said but I still get the same error. I have no idea why it is trying to route the index action because I think it is supposed to be the create action for my form. Sorry, I am learning Rails. –  Nov 16 '15 at 06:12
  • @NeverGiveUp1989 can you try my updated answer? See if `School.find(params[:school_id])` gives you the school. @Pavan, see the update. – K M Rakibul Islam Nov 16 '15 at 06:13
  • Thanks, but now, I get the error: unknown attribute 'school_id' for Teacher. –  Nov 16 '15 at 06:20
  • If your `Teacher` model belongs_to `School`, then you should also have a `school_id` in your `teachers` table in the database. If you already don't have that, add it by a migration. And, then try again. See this post http://stackoverflow.com/questions/4834809/adding-a-column-to-an-existing-table-in-a-rails-migration to see how you can add a new column to an existing table in the database through a Rails migration. – K M Rakibul Islam Nov 16 '15 at 06:21
  • Ok, I will do it and update the result here. Thank you again. Mr. Islam. –  Nov 16 '15 at 06:35
  • OK. Do that and try my latest answer (see you need to change both new and create actions). It should work now. – K M Rakibul Islam Nov 16 '15 at 06:36
  • 1
    Alright, I added the column: school_id(type: integer) to my teachers table, and it works now. However, I need to edit the line redirect_to school_path(params[:school_id]) for the create action. Otherwise, it will show me the error: undefined local variable or method `school' for #. –  Nov 16 '15 at 07:45
  • That is awesome! You are welcome and best of luck :-) – K M Rakibul Islam Nov 16 '15 at 07:45
0

Try this in your form:

<%= form_for [school, Teacher.new] do |f| %>

The path you are posting to is for the index of teachers at a school:

school_teachers GET    /schools/:school_id/teachers(.:format)   teachers#index
dewyze
  • 979
  • 1
  • 7
  • 21
0

I believe that it's a has_many belongs_to association. So you need to first change your teacher controller create action and new action.

class TeachersController < ApplicationController
 def new
  get_school
  @teacher = @school.teachers.build
 end

 def create
  get_school
  @teacher = @school.teachers.build(teacher_params)
  If @teacher.save
      redirect_to school_path(school)
  else
      render 'new'
  end

 private

  def teacher_params
    params.require(:teacher).permit(:firstName, :lastName, :middleName)
   end
 def get_school
     @school = School.find (params [:school_id])
 end
 end

Then in your form you 'll do :

  <%= form_for([@school,@teacher]) do |f| %>

Hope this will help

  • Thank you for your help, Mr. Ayoub. I am learning Rails, and definitely I will ask more questions about Rails on this site. Hopefully, experienced Rails programmers like you will help me in the future. Have a great day. –  Nov 16 '15 at 07:50