Search code examples
ruby-on-railsformsmail-form

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


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: 'myemail@gmail.com',
      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]

Solution

  • 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.