2
votes

I'm making a basic form in rails and for some reason when I make the form the action is blank and consequently I get the routing error "No route matches [POST] "/contacts/new"

Here is the view code:

<%= form_for  :contact,  :url => {:action => "create"} , html: { class: "contact-form"} do |f| %>

  <div class="form-group col-md-12 col-sm-12 col-xs-12">
    <h4>Choose your option below</h4>
     <%= f.label :option, class: 'sr-only' %>
     <%= f.select :option, options_for_select(["I would like to reserve a place for myself", "I would like Better Place for ashes I currently possess", "I would like Better Place for ashes currently at a funeral home", "I operate a funeral home and would like to know more"]), {}, multiple: false, class: "form-control" %><br />
  </div>
  <div>
    <h4>Please provide us with some details</h4>
  </div>

  <div class="col-md-6 col-sm-6 col-xs-12 form-group">
    <%= f.label :name, class: 'sr-only' %>
    <%= f.text_field :name, placeholder: "Your name", class: 'form-control', style: "height: 40px;" %><br />
  </div>

  <div class="col-md-6 col-sm-6 col-xs-12 form-group">
    <%= f.label :email, class: 'sr-only' %>
    <%= f.text_field :email, placeholder: "Your email", class: 'form-control', style: "height: 40px;" %><br />
  </div>

  <div class="col-md-6 col-sm-6 col-xs-12 form-group">
    <%= f.label :phone, class: 'sr-only' %>
    <%= f.text_field :phone, placeholder: "Your phone", class: 'form-control', style: "height: 40px;" %><br />
  </div>

  <div class="col-md-12 col-sm-12 col-xs-12 form-group">
    <%= f.label :comments, class: 'sr-only' %>
    <%= f.text_area :comments, placeholder: "Enter any comments or questions here", class: "form-control",:rows => "6" %>
  </div>

  <div class="col-md-12 col-sm-12 col-xs-12 form-group">
    <%= f.submit 'Submit Details', class: 'btn btn-block btn-cta btn-cta-primary'  %>
  </div>  
<% end %>

And here is the resulting form in html:

<form id="contact-form" class="contact-form" method="post" action=""> 

When I run rake routes the correct route (contacts_path) appears:

     pages_home GET  /pages/home(.:format)    pages#home
         root GET  /                        pages#home
  pages_about GET  /pages/about(.:format)   pages#about
pages_options GET  /pages/options(.:format) pages#options
    pages_faq GET  /pages/faq(.:format)     pages#faq
     contacts POST /contacts(.:format)      contacts#create
  new_contact GET  /contacts/new(.:format)  contacts#new

And when I submit the form it's trying to POST to the new action instead of the create action so I get: No route matches [POST] "/contacts/new"

My question is why is the form action being left blank when the appropriate route exists and what can I do to fix it?

Thanks!

Edited to show controller below:

    class ContactsController < ApplicationController

  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(contact_params)
    @option = params[:contact][:option]
    @name = params[:contact][:name]
    @email = params[:contact][:email]
    @phone = params[:contact][:phone]
    @comments = params[:contact][:comments]

    if @contact.save
      redirect_to new_contact_path, :notice => "Thanks for contacting us! We'll be in touch shortly."
    else
        render new_contact_path
        flash[:notice] = "Oops. Please enter the correct information and try again."
    end
  end

  private

  def contact_params
    params.require(:contact).permit(:option, :name, :phone, :email, :comments)
  end

end
2
What does your controller look like for #new and #create?Beartech
Also, when you are viewing the form, what address is in the address bar? I think this might be due to non-standard routes, so Rails is making assumptions that aren't true. You could try setting the POST route to post 'new_contact' => 'contacts#create'Beartech
The controller looks like:rails_newbie
Controller looks like: code def new @contact = Contact.new end def create @contact = Contact.new(contact_params) @option = params[:contact][:option] @name = params[:contact][:name] @email = params[:contact][:email] @phone = params[:contact][:phone] @comments = params[:contact][:comments] if @contact.save redirect_to new_contact_path, :notice => "Thanks for contacting us! We'll be in touch shortly." else render new_contact_path flash[:notice] = "Oops. Please enter the correct information and try again." end endrails_newbie
Don't put code that large in comments. Edit your answer with the above code in a readable format.Beartech

2 Answers

1
votes

You should be using the form_for as the following:

form_for @contact, url: contacts_path, html: { class: "contact-form"} do |f|
  #                ^^^^^^^^^^^^^^^^^^ this is optional, see @nathanvda's comment

Where @contact is a variable set in your controller's action like this:

@contact = Contact.new
# you can eventually pre-fill some attributes here:
# @contact = Contact.new(user_id: current_user.id, important: false)

This is tricky: form_for is accepting a URL helper to know where to submit the form, in your case /contacts. You will say "but it is the address of the index action!" I will answer "yes but the form_for is using a request as POST and not GET)

0
votes

The standard/easy solution, imho, is to write it the following way instead:

<%= form_for @contact, html: { class: "contact-form"} do |f| %>

And in your new action, set

@contact = Contact.new

Using the symbol can also work, but I think you will have to write it as follows:

<%= form_for :contact, :url => contacts_path, method: :post, html: { class: "contact-form"} do |f| %>

But using the instance variable is imho the preferred way.