Rails ActionController::RoutingError (No route matches [POST] "/"):

1.7k views Asked by At

rails 6.0.3

I have set up a static mail form using the gem 'mail_form'.

I know that it working correctly because I can send an email from the rails console.

The issue is on the form, when I press submit, it is coming up with a routing error.

ActionController::RoutingError (No route matches [POST] "/"):

home page form

<div class="container">
  <%= form_with model: @contact do |f| %>
    <div class="mb-3">
      <h3><%= f.label :name, class: "label" %></h3>
      <%= f.text_field :name, class: "form-control", placeholder: "Write name in here" %>
      <%= f.text_field :email, class: "form-control", placeholder: "Write email in here" %>
      <%= f.text_field :message, class: "form-control", placeholder: "Write message in here" %>
      <%= f.submit %>
    </div>
  <% end %>
</div>

routes.rb

resources :contact, only: [:create]

contact.rb

class Contact < MailForm::Base
  attribute :name, validate: true
  attribute :email, validate: true
  attribute :message
  def headers
    {
      subject: "My Contact Form",
      to: '[email protected]',
      from: %("#{name}" <#{email}>)
    }
  end
end

contact_controller.rb

class ContactController < ApplicationController
  def create
    @contact = Contact.new()
    @contact.name = params[:name]
    @contact.email = params[:email]
    @contact.message = params[:message]
    if @contact.deliver

      render json: {message: "Email sent successfully"}
      redirect_to root_path
    else
      render json: @contact.errors
    end
  end
end

What have I done wrong or what step have I missed?

edited controller

class ContactController < ApplicationController

  def create
    @contact = Contact.new(contact_params)
    if @contact.deliver
      redirect_to root_path
    else
      render json: @contact.errors
    end
  end

  private
  def contact_params
    params.require(:contact).permit(:name, :email, :message)
  end
end

edited form

<div class="container">
  <%= form_for Contact.new, url: contacts_path do |f| %>
    <div class="mb-3">
      <h3><%= f.label :name, class: "label" %></h3>
      <%= f.text_field :name, class: "form-control", placeholder: "Write name in here" %>
      <%= f.text_field :email, class: "form-control", placeholder: "Write email in here" %>
      <%= f.text_field :message, class: "form-control", placeholder: "Write message in here" %>
      <%= f.submit %>
    </div>
  <% end %>
</div>

edited routes.rb

resources :contacts, only: [:create]
2

There are 2 answers

2
max On BEST ANSWER
resources :contacts, only: [:create]

Resources should be plural.

class ContactsController < ApplicationController
  def create
    @contact = Contact.new(contact_params)
    if @contact.deliver
      # You can't both render and redirect 
      render json: { message: "Email sent successfully" }
    else
      render json: @contact.errors
    end
  end

  private
  def contact_params
    params.require(:contact)
          .permit(:name, :email, :message)
  end
end

The parameters are nested in params[:contact][:name], params[:contact][:email] etc. Use strong parameters to whitelist the parameters for mass assignment instead of acting as a human compiler.

4
stwienert On

@form cannot automatically resolve a path, I think:

 <%= form_with model: @contact do |f| %>
  • Try adding an explicit url: form_with model: @contact, url: contacts_path
  • Also make sure to make controllers always plural like @max said, if using resource or resources, otherwise sooner or later Rails gets confused from my experience. On the other hand, your contact only has one method, you can just add a manual route for that and don't rely on Rails auto naming magic:
# routes

  post "/contact"

# this should also generate a `contact_path` helper, which you can use in the