在 Hartl 的教程中添加联系表单

Posted

技术标签:

【中文标题】在 Hartl 的教程中添加联系表单【英文标题】:Add a contact form to Hartl's tutorial 【发布时间】:2015-06-23 11:30:35 【问题描述】:

我正在按照 Hartl 的教程学习 Rails,并对它进行自己的调整。现在,我想扩展它并添加一个发送电子邮件的联系表格。教程中不包含这些内容,但在第 10 章结束时,我们学会了使用 mailer 方法,并且我们已经在 Heroku 上配置了 SendGrid。

我已经在路线中设置了视图,并认为它需要以下额外步骤:

1) 终端。 rails 生成邮件 ContactForm

2) 在 app/mailers/contactform.rb 中:

def send_contactform_email(visitor)
  @visitor = visitor
  mail( :to => myemail@example.com, :from => visitor.email, :subject => 'Contact form' )
end

3) app/views/contactform_mailer/(邮件信息的视图)例如:

<h1>Website contact form</h1>
<p>On <$= ... %> <%= "#@visitor.name (#@visitor.email sent the following message:" %></p>
<p><%= @visitor.message %></p>

4) app\controllers\static_pages_controller (或其他位置?)

  # Sends contact form email.
  def send_contact_form_email
    ContactFormMailer.send_contactform_email(visitor).deliver_now
    redirect_to contact_path, notice: 'Message sent'
  end

5) app\views\static_pages\contact.html.erb (我不确定第一行,我是否也应该在 routes.rb 中做一些事情?我猜这第一行必须告诉执行第 4 步中的方法,这不会像现在这样工作。)

<%= form_for(:static_pages, url: contactform_path) do |f| %>
  <i class="pt-row-icon glyphicon glyphicon-user"></i> <%= f.label :name %>
  <%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>

  <i class="pt-row-icon glyphicon glyphicon-envelope"></i> <%= f.label :email %>
  <%= f.email_field :email, placeholder: 'Email', class: 'form-control' %>

  <i class="pt-row-icon glyphicon glyphicon-envelope"></i> <%= f.label :message %>
  <%= f.text_area :message, placeholder: 'Your message…', class: 'form-control' %>

  <%= f.submit "Send", class: "btn btn-primary" %>
<% end %>

我认为这还不是 100% 正确,尤其是粗体部分。你有什么想法?


更新,版本 2: 我已尝试按照 Ven 的建议进行更新,现在代码如下。据我了解的想法是

def contact 中的控制器设置@message 变量。 form_for 知道它应该用 params[:message] 填充这个变量。 控制器采用 form_for 中的值并将它们传递给邮件程序。 邮件程序使用邮件程序视图来设计要发送的消息。 邮件程序将其发送回发送消息的控制器。

1) 应用/控制器/static_pages_controller.rb

class StaticPagesController < ApplicationController
before_action :valid_email?, only: [:send_message_email]

  # Shows the contact form page
  def contact
    @message = message(message_params)
  end

  # Sends the message.
  def send_message_email
    @message = message(message_params)
    if @message.valid?
      MessageMailer.new_message(@message).deliver_now
      redirect_to contact_path, notice: "Your messages has been sent."
    else
      flash[:alert] = "An error occurred while delivering this message."
      render :new
    end
  end    

  private

    def message_params
      params.require(:message).require(:name, :email, :content)
    end

    def valid_email?(email)
      VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
      email.present? && (email =~ VALID_EMAIL_REGEX)
    end
end

2) app\views\static_pages\contact.html.erb 中的联系表:

<%= form_for(message: params[:message], url: contact_path) do |f| %>
  <%= f.label :name %> <%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>
  <%= f.label :email %> <%= f.email_field :email, placeholder: 'Email', class: 'form-control' %>
  <%= f.label :content %> <%= f.text_area :content, placeholder: 'Your message…', class: 'form-control' %>
  <%= f.submit "Send", class: "btn btn-primary" %>
<% end %>

3) Routes.rb

  get 'contact'           => 'static_pages#contact',  as: 'contact'
  post 'contact'          => 'static_pages#send_message_email'

4) App/views/message_mailer.text.erb(和 html.erb)

<%= @message[:name] %> <%= @message[:email] %> wrote:
<%= @message[:content] %>

5) 应用程序/mailers/message_mailer.rb

class MessageMailer < ApplicationMailer
  default to: "myemail@example.com>"

  def new_message(message)
    @message = message
    mail to: "myemail@example.com"
    mail from: @message[:email]
    mail subject: "Message from #message[:name]"
  end
end

现在,当我尝试访问服务器上的联系表单时,我收到错误消息:param is missing or the value is empty: message。它指的是params.require(:message).require(:name, :email, :content) 行。不知道我做错了什么。将其更改为 params.require(:message).permit(:name, :email, :content) 没有任何区别。

【问题讨论】:

请添加该教程的链接 www.railstutorial.org 【参考方案1】:

4) app\controllers\static_pages_controller(或其他位置?)

这似乎是正确的,如果 this 是该应用程序的 github 存储库。


def send_contact_form_email

您的控制器有一个问题:此操作将尝试发送电子邮件,无论它是用于 POST 还是 GET。您应该使用两种不同的操作,一种用于显示视图(使用 GET),另一种用于发送电子邮件(使用您创建的邮件程序类)。 (此时,您可能需要创建另一个控制器)


ContactFormMailer.send_contactform_email(visitor).deliver_now

然后,继续:传递给邮件程序的是“访问者”。没有这样的变量。 您可能希望从 params 哈希(其中包含 GET 和 POST 请求的参数)中访问某些内容,并使用与表单相同的键(form_for(:visitor ... => params[:visitor](因此您想更改 @987654328 @))。

<p>On <$= ... %> <%= "#@visitor.name (#@visitor.email sent the following message:" %></p>

由于这返回一个对象,而不是一个哈希,@visitor.email 需要在邮件中为@visitor[:email]


最后一件事:简单地使用params[:visitor] 将意味着人们可以将该字段留空。您可能想研究一下在 Rails 4 中添加的强参数(这本书似乎有些过时了?)。

最后,您需要添加能够实现这些操作的路由(一条用于 GET 请求 - 显示视图 - 一条用于 POST 请求 - 以提交表单)。


PS:

mail( :to => myemail@example.com, :from => visitor.email, :subject => 'Contact form' )

警告:在这里,您忘记引用电子邮件地址。此外,您交换了 to/from 参数。您想发送TO您的访问者电子邮件,而不是来自它。


编辑

params.require(:message).require(:name, :email, :content)

这将需要上述密钥,但 AFAIK 与 :message 处于同一“级别” - ***别。你想用permit:

params.require(:message) # require "namespace"
  .permit(:name, :email, :content) # permit keys

    @message = message(message_params)

message 函数定义在哪里?

mail to: "myemail@example.com"
mail from: @message[:email]
mail subject: "Message from #message[:name]"

这会发送 3 封不同的电子邮件,因为您调用了 mail 函数 3 次。

【讨论】:

我在matharvard.ca/posts/2014/jan/11/contact-form-in-rails-4 上找到了一个替代教程,其中创建了一个单独的模型来处理邮件消息。我没有想到,你也没有提到,但你会说这是惯例吗?在我看来,为一个简单的联系表格这样做有点“夸张”? 这取决于。许多人会希望有发送电子邮件的历史记录。在这种情况下,一个新模型可能是值得的。如果你不想这样,一个简单的联系表(如这里)可以工作:) 谢谢@Ven,我已经更新了我的问题,添加了我的新尝试,尽我所能实施您的反馈。

以上是关于在 Hartl 的教程中添加联系表单的主要内容,如果未能解决你的问题,请参考以下文章

将验证码添加到响应式引导程序联系表单

在Michael Hartl的Ruby on Rails教程中获取错误消息:MicropostsController中的NoMethodError #create,如何避免收到此消息?

如何在联系表单7提交按钮上添加多个类

在 PHP 中获取联系表 7 表单 ID

联系表单验证以防止空白电子邮件

html 添加浮动占位符标签以在焦点上联系表单7