Ruby(Ruby on Rails)使って、お問い合わせ機能を作った際に多少詰まったりしたのでメモ代わりとして備忘録残しておきます。
またこれから機能実装する人、プログラミング初心者に向けても書いてるので是非参考になればと。
参考にした資料
以下参考にした資料等です。今回機能実装に向けて何個か資料を参考にして完成させました。参照元の資料にはほんと感謝です。
Action mailer参考資料1→ほぼこの資料がベースです。ただある程度Rails触ったことある人向けに書かれてる印象で、ファイル作成のコマンド実行など一切ないのと、paramsの受取エラーやSMTPのエラーなど、記事通りに行かない点がありました。でもこの記事のおかげで完成したのでとても感謝してます!
Action mailer参考資料2→有名なスクールさんですね。最初この記事を参考にしてたのですが、メーラーでの確認のところが自分的に微妙だったのでSMTPの設定のところだけ最終的には参考にしました。
環境変数の参考資料→機能とは実際には関係ないのですが、セキュリティ面と今後も使える技術なので導入しました。
プロジェクトの作成
プロジェクトを作成します。今回プロジェクト名は問合せ機能のテストアプリなのでinquiryTestAppとします。
rails new inquiryTestApp
create
create README.md
create Rakefile
・
・
・
<中略>
・
・
・
└─ yargs@12.0.5
✨ Done in 5.58s.
Webpacker successfully installed 🎉 🍰
「successfully」が出ればOK。
必要なファイルの生成
次に、作業Dirに移動しコントローラなどを作成します。
cd inquiryTestApp
rails g controller inquiry index confirm thanks
「rails g controller」の後ろ3つの引数について。
Viewを作成してます。(任意のファイル名を指定できます。)以下各Viewの説明。
・index→問合せ画面(初期表示画面)
・confirm→問合せ確認画面
・thanks→問合せ完了通知画面
Running via Spring preloader in process 1987
create app/controllers/inquiry_controller.rb
route get 'inquiry/index'
get 'inquiry/confirm'
get 'inquiry/thanks'
invoke erb
create app/views/inquiry
create app/views/inquiry/index.html.erb
create app/views/inquiry/confirm.html.erb
create app/views/inquiry/thanks.html.erb
invoke test_unit
create test/controllers/inquiry_controller_test.rb
invoke helper
create app/helpers/inquiry_helper.rb
invoke test_unit
invoke assets
invoke scss
create app/assets/stylesheets/inquiry.scss
中段あたり、View(html.erb)が3つcreateされてることが分かる。
次にmailer作成。今回初めて知ったのですが、Active Mailerと言う機能が標準搭載してあるらしくcontrollerやmodel同様railsコマンドでファイル作成することができます。手動で作成してもいいのですがせっかくなので今回はコマンド使っていきます。
rails g mailer inquiry
以下出力結果。いろいろと作成されているが、今回は1行目の「inquiry_mailer.rb」のみをいじっていく。
create app/mailers/inquiry_mailer.rb
invoke erb
create app/views/inquiry_mailer
invoke test_unit
create test/mailers/inquiry_mailer_test.rb
create test/mailers/previews/inquiry_mailer_preview.rb
次にmodelの作成。
通常はコマンド(rails g model)を使うのですが、今回はDBを使わないので(model/inquiry.rb)を手動にて作成(Linuxコマンド使います!)。railsコマンドを使うとmigrateファイルとかを作成してしまい消すのが面倒・・・
touch app/models/inquiry.rb
コマンド実行後、VSCodeのフォルダーツリーが以下のようになってればOK。

コードを書く
ここまで揃えたらいよいよコードを書いていく。
まずはmodel今回はDBを使わないので「ActiveModel」(以下2行目)を使用してます。
class Inquiry
include ActiveModel::Model
attr_accessor :name, :email, :message
validates :name, :presence => {:message => '名前を入力してください'}
validates :email, :presence => {:message => 'メールアドレスを入力してください'}
end
次にcontroller。
class InquiryController < ApplicationController
def index
# 入力画面を表示
@inquiry = Inquiry.new
render :action => 'index'
end
def confirm
# 入力値のチェック
@inquiry = Inquiry.new(params[:inquiry].permit(:name, :email, :message))
if @inquiry.valid?
# OK。確認画面を表示
render :action => 'confirm'
else
# NG。入力画面を再表示
render :action => 'index'
end
end
def thanks
# メール送信
@inquiry = Inquiry.new(params[:inquiry].permit(:name, :email, :message))
InquiryMailer.received_email(@inquiry).deliver
# 完了画面を表示
render :action => 'thanks'
end
end
controllerで記載したメソッドに沿ってViewを作成。
<%= form_for @inquiry, :url => inquiry_confirm_path do |f| %>
<div class="page-header">
<h1>お問い合わせ</h1>
</div>
<% if @inquiry.errors.any? %>
<div class="alert alert-danger" role="alert">
<strong>入力内容にエラーがあります</strong>
<ul>
<% @inquiry.errors.each do |attr, msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<table class="table">
<tr>
<th>名前<span class="text-danger">(必須)</span></th>
<td><%= f.text_field :name %></td>
</tr>
<tr>
<th>メールアドレス<span class="text-danger">(必須)</span></th>
<td><%= f.text_field :email %></td>
</tr>
<tr>
<th>お問い合わせ内容</th>
<td><%= f.text_area :message %></td>
</tr>
</table>
<%= f.submit '確認', class: 'btn btn-primary' %>
<% end %>
<div class="page-header">
<h1>お問い合わせ</h1>
</div>
<%= form_for @inquiry, :url => inquiry_thanks_path do |f| %>
<table class="table">
<tr>
<th>名前</th>
<td>
<%= f.hidden_field :name %>
<%= @inquiry.name %>
</td>
</tr>
<tr>
<th>メールアドレス</th>
<td>
<%= f.hidden_field :email %>
<%= @inquiry.email %>
</td>
</tr>
<tr>
<th>お問い合わせ内容</th>
<td>
<%= f.hidden_field :message %>
<%= simple_format(@inquiry.message) %>
</td>
</tr>
</table>
<%= f.submit '送信', :class => 'btn btn-primary' %>
<% end %>
<div class="page-header">
<h1>お問い合わせ</h1>
</div>
<p>
お問い合わせいただきありがとうございました。
</p>
作成したViewとControllerを結び付けるため、ルーティンを設定。
Rails.application.routes.draw do
root 'inquiry#index'
get 'inquiry' => 'inquiry#index' # 入力画面
post 'inquiry/confirm' => 'inquiry#confirm' # 確認画面
post 'inquiry/thanks' => 'inquiry#thanks' # 送信完了画面
end
controllerのthanksメソッドが呼ばれる、mailer class。
class InquiryMailer < ApplicationMailer
default from: "example@example.com" # 送信元アドレス
def received_email(inquiry)
@inquiry = inquiry
mail(:to => inquiry.email, :subject => 'お問い合わせを承りました')
end
end
gmail送信用の設定をする。SMTPサーバ(メールの送信用サーバ)を使える用にしてます。詳しくはこちらのサイトに説明があります。
実は以下の記述だけだとセキュリティの関係でエラーが出て送信ができない。そのためGoogleアカウント側で認証設定が必須で、その対応は後ほど紹介するのでご安心を。
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: '<gmailのメールアドレス>',
password: '<gmailのパスワード>',
authentication: 'plain',
enable_starttls_auto: true
}
最後に、メールのテンプレートを作成。ここ実は良くわかってないのだが、恐らくmailersで作成したメソッド名と紐付いててメール送信時にこのテンプレートを読み込んでるのだと思う。曖昧な表現でごめんなさい。これが会社だったら怒られるねw
Webサイトからお問い合わせがありました。
--------------------------
Name: <%= @inquiry.name %>
Email: <%= @inquiry.email %>
Message:
<%= @inquiry.message %>
--------------------------
現状このままだと、メール送信でエラーが出て送れないので、Googleの二段階認証の設定をします。
ここはちょっと長くなるので、こちらなど外部の資料を参照して下さい。
上記が出来たなら今度はアプリからのアクセスを可能にするため、アプリパスワードを設定します。手順はこちらなどを参照。
※設定したアプリパスワードは忘れずメモっておくように!
ここまで出来たら、development.rbを編集していきます。
【変更前】
password: '<gmailのパスワード>'
↓
【変更後】
password: '<Googleで設定した、アプリパスワード>'
ここまで出来ると、問合せ機能が出来ると思います。
動作確認していきましょう。serverを立ち上げ、localhost:3000にアクセスしましょう。アプリを開けば何となく使い方が分かるかと思います。
環境変数を使う
動作確認でメールを受信できる事を確認出来たら、これで機能実装は完了なのですが、1つ問題があります。Gmailアドレスとパスワードを直書きしてることです。このコードをGithubなどにあげたら全世界にアドレスとパスを公開してしまうことになるのでそれはセキュリティ上よろしくないのでこの問題を改善します。
方法は何個かあると思いますが、今回は.envという環境変数用ファイルを使う方法を取っていきます。
gemを用意する。
gem 'dotenv-rails'
インストール。
bundle install
.envファイルを作成します。(プロジェクトファイル直下)
touch .env
VSCodeのフォルダーツリーが以下のようになってればOK。
環境変数を作成していきます。
SEND_MAIL='<gmailのメールアドレス>'
SEND_MAIL_PASSWORD='<Googleで設定した、アプリパスワード>'
これで環境変数が使えるようになったので、問題のdevelopment.rbを編集していきます。
ここで言う環境変数とは上記コードの代入式の左側の変数部分の事です。
ENV['<変数>']とする事で環境変数を使うことが出来きます。
【変更前】
user_name: '<gmailのメールアドレス>',
password: '<Googleで設定した、アプリパスワード>',
↓
【変更後】
user_name: ENV['SEND_MAIL'],
password: ENV['SEND_MAIL_PASSWORD'],
最後にアップロードの制限をかけます。.gitignoreに以下を追記しましょう。
.env
これで完成しました。再度serverを立ち上げなおしてアプリの動作確認をしましょう。先程と同等の動きになるかと思います。
最後に
お疲れ様でした。少し長い記事になってしまいましたが、最後まで読んでくれた方本当にありがとうございました。きっちり問い合わせ機能について書いてる記事が無かったので誰かの助けになれば幸いです。
またこの実装自体まだまだ改善出来るところは山ほどあるので時間がある時にでも更新していこうかと思います。