#はじめに
転職活動用ポートフォリオ作成中です。今回、ユーザーからのお問い合わせ機能を実装したため、備忘録及び復習のため記述します。
##環境
Ruby on Rails'6.0.0'
Ruby'2.6.5'
##①ルーティングの記述
resource :contacts, only: [:new, :create] do
get "/thanks" => "contacts#thanks"
end
今回は、ユーザーがお問い合わせを送信後、「お問い合わせいただきありがとうございました!」のようなページを表示させる流れです。
##②モデルの記述
rails g model contactコマンドでモデルを作成後、マイグレーションファイルの記述などを行っていきます。
class CreateContacts < ActiveRecord::Migration[6.0]
def change
create_table :contacts do |t|
t.string :name, null: false
t.string :email, null: false
t.text :content, null: false
t.timestamps
end
end
end
今回は、名前・返信用のメールアドレス・お問い合わせ内容を指定しました。その後、rails db:migrateコマンドを実行します。
class Contact < ApplicationRecord
validates :name, :email, :content, presence: true
end
名前・メールアドレス・お問い合わせ内容が空では保存できないようにバリデーションを設定します。
##③ActionMailerの設定
今回はユーザーからお問い合わせが送信されると、内容が管理者へメールで届くような機能にしたいと思います。そこでActionMailerを使用しました。
まず、rails g mailer ContactMailerコマンドを実行します。すると以下のファイルが生成されるためお問い合わせが来たら管理者へメールを送信する記述をしていきます。
class ContactMailer < ApplicationMailer
def contact_mail(contact)
@contact = contact
mail to: '(管理者のメールアドレス)@gmail.com', subject: '(メールのタイトル)'
end
end
続いては新たにviewファイルが生成されているため、メールの本文を記述していきます。
<p>ユーザーネーム:<%= @contact.name %></p>
<p>メールアドレス:<%= @contact.email %></p>
<p>お問い合わせ内容:<%= @contact.content %></p>
##④コントローラーの記述
それではコントローラーの記述をしていきます。
class ContactsController < ApplicationController
def new
@contact = Contact.new
end
def create
@contact = Contact.new(contact_params)
if @contact.save
ContactMailer.contact_mail(@contact).deliver
redirect_to thanks_contacts_path
else
render :new
end
end
def thanks
end
private
def contact_params
params.require(:contact).permit(:name, :email, :content)
end
end
これにより、createアクションが呼び出され、お問い合わせが正常に保存されると、メール送信処理も走り出すように設定できました。
##⑤viewの記述
お問い合わせのviewファイルの記述をしていきます。
<div class="container">
<div class="row">
<div class="offset-sm-2 col-sm-8 offset-sm-2">
<%= form_with model: @contact, local: true do |f| %>
<h5 class='form-header-text text-center'><i class="far fa-paper-plane fa-2x my-orange"></i> お問い合わせ</h5>
<%= render 'layouts/error_messages', model: f.object %>
<div class="form-group">
<div class='form-text-wrap'>
<label class="form-text" for="name">お名前</label>
<span class="badge badge-danger">必須</span>
</div>
<div class='input-name-wrap'>
<%= f.text_field :name, class:"input-name", id:"name", placeholder:"例) 田中太郎" %>
</div>
</div>
<div class="form-group">
<div class='form-text-wrap'>
<label class="form-text" for="email">メールアドレス</label>
<span class="badge badge-danger">必須</span>
</div>
<%= f.email_field :email, class:"input-default", id:"email", placeholder:"PC・携帯どちらでも可", autofocus: true %>
</div>
<div class="form-group">
<div class='form-text-wrap'>
<label class="form-text" for="content">内容</label>
<span class="badge badge-danger">必須</span>
</div>
<%= f.text_area :content, class:"article-input-default", id:"content", autofocus: true %>
</div>
<div class='contact-btn text-center'>
<%= f.submit "送信する" ,class:"btn btn-outline-danger w-50" %>
</div>
<% end %>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="offset-sm-2 col-sm-8 offset-sm-2">
<h5 class='header-text text-center'><i class="far fa-smile fa-lg my-orange"></i> お問い合わせありがとうございました</h5>
<%= link_to 'トップページへ戻る', root_path %>
</div>
</div>
</div>
##⑥Gmailの設定
最後に今回アドレスで使用するGmailの設定を行いました。
(中略)
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
domain: 'gmail.com',
port: 587,
user_name: '(管理者のメールアドレス)@gmail.com',
password: ENV["GMAIL_KEY"],
authentication: 'plain',
enable_starttls_auto: true
}
(中略)
すでに他の設定も記述されているかと思うので、間に記述しました。
GmailのパスワードはGitHub上に上がってしまっては、大変なことになってしまうので、環境変数を設定します。設定する方法は様々あると思いますが、私はvimコマンドを使用して「.zshrc」ファイルに設定しました。
% vim ~/.zshrc
上記のコマンドでファイルを開き、insertモードにしてから記述していきます。
(中略)
export GMAIL_KEY = "Gmailのパスワード"
(中略)
こちらで設定が完了しました!
##⑦テストコードの実装
おまけとしてRspecを使用してテストコードも実装しました。
#####FactoryBot
FactoryBot.define do
factory :contact do
name { Faker::Name.name }
email { Faker::Internet.email }
content { Faker::Lorem.sentence }
end
end
#####単体テストコード
require 'rails_helper'
RSpec.describe Contact, type: :model do
before do
@contact = FactoryBot.build(:contact)
end
describe 'お問い合わせの送信' do
context 'お問い合わせが送信できる場合' do
it '全ての要素が存在すれば投稿できる' do
expect(@contact).to be_valid
end
end
context 'お問い合わせが送信できない場合' do
it 'nameが空では送信できない' do
@contact.name = nil
@contact.valid?
expect(@contact.errors.full_messages).to include('お名前を入力してください')
end
it 'emailが空では送信できない' do
@contact.email = nil
@contact.valid?
expect(@contact.errors.full_messages).to include('メールアドレスを入力してください')
end
it 'contentが空では送信できない' do
@contact.content = nil
@contact.valid?
expect(@contact.errors.full_messages).to include('お問い合わせ内容を入力してください')
end
end
end
end
#####結合テストコード
require 'rails_helper'
RSpec.describe 'お問い合わせ送信', type: :system do
before do
@contact = FactoryBot.build(:contact)
end
context 'お問い合わせの送信ができるとき' do
it '正しい情報を入力すれば、お問い合わせを送信できる' do
visit root_path
expect(page).to have_content('お問い合わせ')
visit new_contacts_path
fill_in 'お名前', with: @contact.name
fill_in 'メールアドレス', with: @contact.email
fill_in '内容', with: @contact.content
expect do
find('input[name="commit"]').click
end.to change { Contact.count }.by(1)
expect(current_path).to eq thanks_contacts_path
click_link 'トップページへ戻る'
expect(current_path).to eq root_path
end
end
context 'お問い合わせの送信ができないとき' do
it '正しい情報を入力しなければ、お問い合わせは送信できない' do
visit root_path
expect(page).to have_content('お問い合わせ')
visit new_contacts_path
fill_in 'お名前', with: ''
fill_in 'メールアドレス', with: ''
fill_in '内容', with: ''
expect do
find('input[name="commit"]').click
end.to change { Contact.count }.by(0)
expect(current_path).to eq contacts_path
end
end
end
#終わりに
https://qiita.com/mmdrdr/items/9c5dd4ca886f034fb0ef
https://qiita.com/hirotakasasaki/items/ec2ca5c611ed69b5e85e
上記の記事を参考にさせていただきました。ありがとうございました。
メール送信のテストもしてみたいと思うので、調べてみます!!
誤っている点ありましたらご指摘ください。