2017-01-22 3 views
0

J'essaye de créer un formulaire de 'contact me' avec activemodel pour éviter de générer des tables inutiles. Quand je soumets le formulaire de contact, rails renvoie l'erreur No route matches [POST] "/contact/new", malgré les routes suivantesRails activemodel & actionmailer contactez-moi le formulaire ne renvoie aucun itinéraire [POST]

config/routes.rb

resources :contact, only: [:new, :create] 

rake routes renvoie les éléments suivants ...

contact_index POST /contact(.:format)      contact#create 
    new_contact GET /contact/new(.:format)     contact#new 

contrôleur/contact_controller .rb

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 

mailers/cont act_mailer.rb

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 

modèles/contact.rb

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 

vues/Contact/new.html.erb

<%= 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 %> 

Répondre

1

Lors de la déclaration de ressources, vous devez utiliser la forme plurielle:

resources :contacts, only: [:new, :create] 

Cela va avec l'idée RESTful que vous opérez sur une collection de ressources.

Votre formulaire doit afficher contacts_path et non new_contacts_path. Les actions new et edit répondent à GET et restituent simplement des formulaires dans des rails.

En fait, vous pouvez tout simplement passer l'enregistrement à form_for et convention d'utilisation sur la configuration:

<%= form_for(@contact) %> 
    # ... 
<% end %> 

Cette acheminera automatiquement à contacts_path. Vous avez rarement besoin de définir manuellement l'URL d'un formulaire dans les rails.

+0

Si vous voulez vraiment avoir une ressource singulière, utilisez plutôt la macro 'resource'. Il génère les noms de route corrects. – max

1

Vous soumettez le formulaire à new_contact_path (/contact/new) dont la méthode est GET et non POST. Par défaut, form_for construit un formulaire avec method défini sur post. Donc, lorsque vous soumettez, rails recherche new_contact_path avec POST verbe qui n'existe pas et donc, aucun itinéraire correspond. Supprimer l'option url de form_for.

<%= form_for @contact do |f| %> 
    # form elements 
<% end %> 

Rails se chargeront de l'URL pour soumettre, le formulaire sera soumis à contacts_path (/contacts)

Pour le code ci-dessus pour travailler, la définition de votre itinéraire doit ressembler à ce qui suit:

resources :contacts, only: [:new, :create]