【问题标题】:Rails activemodel & actionmailer contact me form returns no route matches [POST]Rails activemodel 和 actionmailer 联系我表单返回没有匹配的路线 [POST]
【发布时间】:2017-01-22 05:36:08
【问题描述】:

我正在尝试使用 activemodel 创建一个“联系我”表单,以避免生成不必要的表格。当我提交联系表单时,rails 返回错误No route matches [POST] "/contact/new",尽管有以下路线

config/routes.rb

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

rake routes 返回以下...

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

控制器/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/contact_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

models/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

views/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 %>

【问题讨论】:

    标签: ruby-on-rails forms actionmailer activemodel


    【解决方案1】:

    声明资源时应使用复数形式:

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

    这符合 RESTful 理念,即您正在对资源集合进行操作。

    您的表单应该发布到contacts_path 而不是new_contacts_pathnewedit 操作响应 GET 并仅在 rails 中呈现表单。

    事实上,您可以将记录传递给form_for 并使用约定优于配置:

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

    这将自动路由到contacts_path。您很少需要在 rails 中手动设置表单的 URL。

    【讨论】:

    • 如果你真的想拥有一个单一的资源,请改用resource 宏。它会生成正确的路线名称。
    【解决方案2】:

    您将表单提交给new_contact_path(/contact/new),其方法是GET,而不是POST。默认情况下,form_for 构造一个将method 设置为post 的表单。

    因此,当您提交时,rails 正在寻找 new_contact_path 和不存在的 POST 动词,因此没有路线匹配。

    form_for 中删除url 选项。

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

    Rails 会处理要提交的 url,表单将提交给contacts_path(/contacts)

    要使上述代码正常工作,您的路由定义应如下所示:

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

    【讨论】:

      猜你喜欢
      • 2011-10-06
      • 2013-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多