はじめに
お問合せフォームをActionMailerを使って実装する方法を調べ、実装した。
完成予想図
以下のようなものを作る。
①お問合せフォームの作成
②確認画面の作成
③送信後、ホームへリダイレクト
④メールで確認
前提
No | 項目 | 内容 |
---|---|---|
1 | OS | Mac |
2 | Ruby | 2.6.3 |
3 | rails | 6.0.4 |
実装
上記の内容を参考にした。
modelの作成
名前、メールアドレス、問い合わせ内容というカラムのあるモデルを作成する。
# モデル名はcontactなどそれぞれ好きなものを作成すること
$ rails g model staticpage name:string email:string content:text
以下のマイグレーションファイルも作成されたことを確認する。
class CreateStaticpages < ActiveRecord::Migration[6.0]
def change
create_table :staticpages do |t|
t.string :name
t.string :email
t.text :content
t.timestamps
end
end
end
モデルにバリデーションを設定
下記の内容でバリデーションをかける。
・名前、メールアドレス、内容が空欄でないこと
・名前、メールアドレス、内容の文字数制限
・メールアドレスの正規表現の制限
入力画面で上記のことを守れていないと、エラーが起きる。
class Staticpage < ApplicationRecord
validates(:name, presence: true, length: { maximum: 50 })
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates(:email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: true)
validates :content, presence: true, length: { maximum: 500 }
end
routesの設定
ルーティングの設定をする。
下図のような流れで動作するようにする。
postリクエストで、入力情報を次のステップに送ることで、それぞれの画面で情報を取り扱っていく。
get '/contact', to: 'staticpages#contact'
post '/confirm', to: 'staticpages#confirm', as: 'confirm'
post '/back', to: 'staticpages#back' , as: 'back'
resources :staticpages, only: [:create]
controllerの設定
先ほどの図を実現するため、コントローラーの設定をする。
def contact
@contact = Staticpage.new
end
# contactアクションから入力内容を受け取り、
# 送信ボタンを押されたらcreateアクションを実行します。
def confirm
@contact = Staticpage.new(contact_params)
# if @contact.invalid?
# render :contact
# end
end
# 入力内容に誤りがあった場合、
# 入力内容を保持したまま前のページに戻るのが当たり前になっているかと思いますが、
# backアクションを定義することで可能となります。
def back
@contact = Staticpage.new(contact_params)
render :contact
end
# 実際に送信するアクションになります。
# ここで初めて入力内容を保存します。
# セキュリティーのためにも一定時間で入力内容の削除を行ってもいいかもしれません。
def create
@contact = Staticpage.new(contact_params)
if @contact.save
UserMailer.contact(@contact).deliver_now
flash[:success] = "お問合せが送信されました。"
redirect_to root_url
else
render :contact
end
end
private
def contact_params
self.params.require(:staticpage).permit(:name, :email, :content)
end
end
お問合せテンプレートの作成
お問合せフォームのテンプレートを作成する。
モデルの設定でバリデーションをかけているので、エラーを表示する部分も追加している。
<h1>Contact</h1>
<p>
コンタクトページです。<br>
お問合せの際は下記より、お願いします。
</p>
<%= form_with(model: @contact, local: true, url: confirm_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, 'お名前' %>
<%= f.text_field :name, class: 'form-control', autofocus: true %>
<%= f.label :email, 'メールアドレス' %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :content, 'お問合せ内容' %>
<%= f.text_area :content, class: 'form-control long-content' %>
<%= f.submit '入力内容を確認する', class: "btn btn-primary" %>
<% end %>
エラーメッセージのパーシャルも確認する。
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
確認画面テンプレートを作成
入力した内容を確認し、下記を選択することができるテンプレートを作成する。
・OKなら送信
・修正したいなら情報を保持したまま戻る
<h1>確認画面</h1>
<%# 入力した内容を表示する。OKなら送信する。 %>
<%= form_with(model: @contact, local: true) do |f| %>
<%= f.label :name, 'お名前' %>
<div class="confirm"><%= params[:staticpage][:name] %></div>
<%= f.hidden_field :name %>
<%= f.label :email, 'メールアドレス' %>
<div class="confirm"><%= params[:staticpage][:email] %></div>
<%= f.hidden_field :email %>
<%= f.label :content, 'お問合せ内容' %>
<div class="confirm"><%= params[:staticpage][:content] %></div>
<%= f.hidden_field :content %>
<div><%= f.submit '入力内容を送信する', class: "btn btn-primary" %></div>
<% end %>
<%# 入力内容を修正したいなら、back_pathに送信すると、情報保持してお問合せフォームに戻る。 %>
<%= form_with(model: @contact, local: true, url: back_path) do |f| %>
<%= f.hidden_field :name %>
<%= f.hidden_field :email %>
<%= f.hidden_field :content %>
<div><%= f.submit '入力画面に戻る', class: "btn btn-primary" %></div>
<% end %>
上の送信をすると、デフォルトでcreateアクションが実行される(メールが送信される。)。
下の送信をすると、url: back_pathによりbackアクションが実行される。(お問い合わせフォームをレンダリングする。)。下図再掲。
mailerの設定
まだ、mailerの設定をしていないため、deliver_nowが発火せず、メールが送信されない。設定していく。
class UserMailer < ApplicationMailer
def contact(contact)
@contact = contact
mail from: contact.email, to: ENV['GMAIL_USER'], subject: "【糖質村】お客様からのお問合せ"
# => デフォルトでapp/views/user_mailer/contact.html.erb もしくは、app/views/user_mailer/contact.text.erbのテンプレートを探しにいく。
end
end
引数contactに、お問合せフォームで入力された内容を代入し、保持する。
このデータを次のメールテンプレートで使用する。
メールテンプレートの作成
メールテンプレートを作成し、お問合せを受けた内容をメール本文に記載されるよう設定する。
<h1><%= @contact.name %> 様 からお問い合わせがありました。</h1>
<p>【Mail】: <%= @contact.email %></p>
<p>【お問い合わせ内容】</p>
<span style="white-space: pre-wrap;"><%= @contact.content %></span>
<%= @contact.name %> 様 からお問い合わせがありました。
【Mail】: <%= @contact.email %>
【お問い合わせ内容】
<%= @contact.content %>
環境変数の設定
最後に環境変数の設定をしていく。これをしないと、その環境でmailerを使えない。
以前もActionMailerを使っていたため、環境変数は特に今回いじっていないが一応記載する。
config.action_mailer.asset_host = 'http://localhost:3000'
config.action_mailer.raise_delivery_errors = true
host = 'localhost:3000'
config.action_mailer.default_url_options = { host: host, protocol: 'http' }
config.action_mailer.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:port => 587,
:address => 'smtp.gmail.com',
:user_name => ENV['GMAIL_USER'],
:password => ENV['GMAIL_PASS'], # Googleが発行する、16桁のアプリケーションパスワード
:domain => 'gmail.com',
:authentication => :plain, # 'plain'と書く記事もあり
:enable_starttls_auto => true
}
# 環境変数
export GMAIL_USER='使用するemail'
export GMAIL_PASS='上記メールのpassword' # アプリパスワード
おわりに
これで、全ての設定を完了し、お問合せ内容がメールで確認できるようになった。