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

时间:2015-04-16 20:21:33

标签: ruby-on-rails ruby-on-rails-4 railstutorial.org sendgrid mailer

我通过遵循Hartl的教程并对其进行自我调整来学习Rails。现在,我想扩展它并添加一个发送电子邮件的联系表单。这不包含在本教程中,但是在第10章结束时,我们学会了使用邮件程序方法,并且我们已经在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)App / controllers / 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)App / 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)没有任何区别。

1 个答案:

答案 0 :(得分:2)

  

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

这似乎是正确的,如果this是该应用的github回购。


def send_contact_form_email

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


ContactFormMailer.send_contactform_email(visitor).deliver_now

然后,继续:您传递给邮件的是&#34;访客&#34;。没有这样的变数。 您可能希望从params哈希(包含GET和POST请求的参数)中访问某些内容,并使用与表单相同的密钥(form_for(:visitor ... =&gt; params[:visitor](所以你想改变那个:static_pages)。

<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在同一&#34;等级&#34;作为: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次。