Reputation: 163
I'm trying to create a 'contact me' form with activemodel to avoid generating needless tables. When I submit the contact form, rails returns the error No route matches [POST] "/contact/new"
, despite the following routes
resources :contact, only: [:new, :create]
rake routes
returns the following...
contact_index POST /contact(.:format) contact#create
new_contact GET /contact/new(.:format) contact#new
class ContactController < ApplicationController
def new
@contact = Contact.new
end
def create
@contact = Contact.new(params[:contact])
if @contact.valid?
ContactMailer.contact_submit(@contact).deliver
flash[:notice] = "Thank you for your email, I'll respond shortly"
redirect_to new_contact_path
else
render :new
end
end
end
class ContactMailer < ActionMailer::Base
default to: ENV[EMAIL_ADDRESS]
def contact_submit(msg)
@msg = msg
mail(from: @msg.email, name: @msg.name, message: @msg.message)
end
end
class Contact
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :message
validates_format_of :email, :with => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
validates_presence_of :message
validates_presence_of :name
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
<%= form_for @contact, url: new_contact_path do |f| %>
<div class="form-inputs">
<div class="form-group">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="form-group">
<%= f.label :email %><br>
<%= f.email_field :email %>
</div>
<div class="form-group">
<%= f.label :message %><br>
<%= f.text_area :message %>
</div>
</div>
<div class="form-actions">
<%= f.submit %>
</div>
<% end %>
Upvotes: 0
Views: 94
Reputation: 11915
You're submitting the form to new_contact_path
(/contact/new
) whose method is GET
and not POST
. By default, form_for
constructs a form with method
set to post
.
So, when you submit, rails is looking for new_contact_path
with POST
verb which doesn't exist and so, no route matches.
Remove the url
option from form_for
.
<%= form_for @contact do |f| %>
# form elements
<% end %>
Rails will take care of the url to submit, the form will be submitted to contacts_path
(/contacts
)
For the above code to work, your route definition should look like the following:
resources :contacts, only: [:new, :create]
Upvotes: 1
Reputation: 102055
When declaring resources you should use the plural form:
resources :contacts, only: [:new, :create]
This goes with the RESTful idea that you are operating on a collection of resources.
Your form should post to contacts_path
not new_contacts_path
. The new
and edit
actions respond to GET and just render forms in rails.
In fact you can just pass the record to form_for
and use convention over configuration:
<%= form_for(@contact) %>
# ...
<% end %>
This will automatically route to to contacts_path
. You seldom need to manually set the URL for a form in rails.
Upvotes: 1