
Railsでお問い合わせフォームを作る方法
AI先生があなたの学習をサポートします。今なら無料のWeb/AI制作7講座が受講できます。 (限定100名、8月24日まで)
» 今すぐ無料講座をチェックする
Rails お問い合わせフォーム実装マニュアル
学習目標
このマニュアルを完了すると、以下ができるようになります:
- お問い合わせフォームの仕組みを理解する
- Railsのモデル・ビュー・コントローラーの連携を理解する
- フォームからデータベースへの保存処理を実装する
- メール送信機能を実装する
- バリデーション機能を実装する
- ユーザーフレンドリーな完了ページを作成する
前提知識
このマニュアルを始める前に、以下の知識があることを前提としています:
必須:
- Ruby on Railsの基本的な仕組み(MVC)
- HTMLフォームの基本
- ターミナルの基本操作
推奨:
- ActiveRecordの基本
- ERBテンプレートの基本
全体像の理解
このセクションで学ぶこと
まず最初に、これから作るお問い合わせフォームがどのような機能を持ち、どのような流れで動作するのかを理解しましょう。全体像を把握することで、各実装ステップの意味がより明確になります。
何を作るのか?
お問い合わせフォームに以下の機能を実装します:
- フォームでの情報入力 - ユーザーが名前、メールアドレス、お問い合わせ内容を入力
- データベースへの保存 - 入力された情報を安全にデータベースに保存
- お客様へのThank youメール送信 - 問い合わせ受付の確認メールを自動送信
- 管理者への通知メール送信 - 新しい問い合わせが来たことを管理者に通知
- 送信完了ページの表示 - ユーザーに送信完了を視覚的に確認してもらう
システムの流れ
実際にユーザーがフォームを送信してから完了までの流れを見てみましょう:
[ユーザー] → [フォーム入力] → [送信ボタン]
↓
[バリデーションチェック] ← ここで入力内容をチェック
↓
[データベース保存] ← 問題なければデータベースに保存
↓
[メール送信(2通)] ← お客様と管理者の両方にメール送信
↓
[完了ページ表示] ← ユーザーに完了を知らせる
Railsの仕組みとの関係
RailsのMVC(Model-View-Controller)パターンでは、以下のように役割分担されます:
フォーム送信 → Routes → Controller → Model → Database
↓
Mailer → メール送信
↓
View → 完了ページ
各コンポーネントの役割:
- Routes:どのURLがどのコントローラーのアクションを呼ぶかを決める
- Controller:リクエストを受け取り、適切な処理を行う司令塔
- Model:データベースとのやり取りとデータの検証を担当
- View:ユーザーに表示するHTMLを生成
- Mailer:メール送信の処理を担当
実装手順
このセクションでは、実際にお問い合わせフォームを構築していきます。6つのステップに分けて、順番に実装していきますので、焦らず一つずつ進めましょう。
ステップ1: モデルの作成
このステップで何をするか
まず最初にデータベースの設計を行います。お問い合わせ情報を保存するための「Inquiry(問い合わせ)」モデルを作成し、どんな情報を保存するかを定義します。また、入力された情報が正しいかどうかをチェックするバリデーション(検証)機能も追加します。
なぜこのステップが必要か: フォームから送信されたデータを保存する場所(データベースのテーブル)と、そのデータが正しい形式かどうかをチェックする仕組みが必要だからです。
1-1. Inquiryモデルの生成
bin/rails generate model Inquiry name:string company:string email:string inquiry_type:string content:text
このコマンドの詳細解説:
-
bin/rails generate model
= Railsでモデルを自動生成するコマンド -
Inquiry
= モデル名(必ず大文字で始める。単数形で書く) -
name:string
= 担当者名を保存するフィールド(文字列型) -
company:string
= 会社名を保存するフィールド(文字列型) -
email:string
= メールアドレスを保存するフィールド(文字列型) -
inquiry_type:string
= お問い合わせの種類を保存するフィールド(文字列型) -
content:text
= お問い合わせ内容を保存するフィールド(長文用のテキスト型)
実行後に何が起こるか:
-
app/models/inquiry.rb
- モデルファイルが作成される -
db/migrate/[タイムスタンプ]createinquiries.rb
- マイグレーションファイルが作成される
1-2. マイグレーションの実行
bin/rails db:migrate
このコマンドの詳細解説: マイグレーションファイルを実行して、実際にデータベースに「inquiries」テーブルを作成します。
実行後に何が起こるか:
- データベースに
inquiries
テーブルが作成される - 指定したフィールドに加えて、Railsが自動的に
id
(主キー)、createdat
(作成日時)、updatedat
(更新日時)も追加される
初心者の方への注意: 一度実行したマイグレーションは、通常は元に戻せません。もし間違えた場合は、新しいマイグレーションファイルを作成して修正します。
1-3. モデルにバリデーションを追加
ファイル: app/models/inquiry.rb
class Inquiry < ApplicationRecord
# バリデーション(入力チェック)
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true,
format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i,
message: "正しいメールアドレスを入力してください" }
validates :inquiry_type, presence: true,
inclusion: { in: ['お見積もり', 'zoomご相談', '外部パートナー依頼', 'その他'],
message: "選択肢の中から選んでください" }
validates :content, presence: true, length: { maximum: 1000 }
validates :company, length: { maximum: 100, allow_blank: true }
# お問い合わせ種類の選択肢を定数で定義
INQUIRY_TYPES = ['お見積もり', 'zoomご相談', '外部パートナー依頼', 'その他'].freeze
end
バリデーションの詳細解説:
-
presence: true
= 必須入力(空欄は許可しない) -
length: { maximum: 50 }
= 最大文字数を50文字に制限 -
format: { with: 正規表現 }
= メールアドレスの形式かどうかをチェック -
inclusion: { in: 配列 }
= 指定した選択肢の中からしか選択できない -
allowblank: true
= 空白を許可(会社名は任意項目なので) -
INQUIRYTYPES
= お問い合わせ種類の選択肢を定数として定義(後でフォームで使用)
なぜバリデーションが重要か: 悪意のあるデータや不正な形式のデータがデータベースに保存されることを防ぎ、システムの安全性を保つためです。
ステップ2: コントローラーの作成
このステップで何をするか
コントローラーは、ユーザーからのリクエストを受け取って適切な処理を行う司令塔の役割を果たします。お問い合わせフォームでは、「フォームを表示する」「送信されたデータを処理する」「完了ページを表示する」という3つのアクションが必要です。
なぜこのステップが必要か: ユーザーがフォームにアクセスしたり、データを送信したりする際の処理を定義する必要があるからです。
2-1. InquiriesControllerの生成
bin/rails generate controller Inquiries new create thank_you
このコマンドの詳細解説:
-
Inquiries
= コントローラー名(複数形で記述する) -
new
= フォーム表示用のアクション -
create
= フォーム送信処理用のアクション -
thank_you
= 完了ページ表示用のアクション
実行後に何が起こるか:
-
app/controllers/inquiries_controller.rb
- コントローラーファイルが作成される -
app/views/inquiries/
ディレクトリと各アクション用のビューファイルが作成される -
config/routes.rb
に基本的なルートが追加される
2-2. コントローラーの実装
ファイル: app/controllers/inquiries_controller.rb
class InquiriesController < ApplicationController
def new
@inquiry = Inquiry.new
end
def create
@inquiry = Inquiry.new(inquiry_params)
if @inquiry.save
# お客様にThank youメール送信
InquiryMailer.thank_you(@inquiry).deliver_now
# 管理者に通知メール送信
InquiryMailer.admin_notification(@inquiry).deliver_now
# 完了ページへリダイレクト
redirect_to thank_you_inquiries_path, notice: 'お問い合わせを受け付けました。'
else
# バリデーションエラー時はフォームを再表示
render :new, status: :unprocessable_entity
end
end
def thank_you
# 完了ページ表示(特別な処理は不要)
end
private
def inquiry_params
params.require(:inquiry).permit(:name, :company, :email, :inquiry_type, :content)
end
end
各アクションの詳細解説:
newアクション:
-
@inquiry = Inquiry.new
= 空のInquiryオブジェクトを作成 - このオブジェクトをフォームで使用します(後でビューで説明)
- @ マークは「インスタンス変数」を表し、ビューからアクセスできる変数です
createアクション:
-
inquiry_params
= 送信されたフォームデータを安全に取得 -
@inquiry.save
= データベースに保存を試行(バリデーションも自動実行) - 保存成功時:メール送信 → 完了ページへリダイレクト
- 保存失敗時:エラーメッセージ付きでフォームを再表示
inquiry_paramsメソッド(Strong Parameters):
- セキュリティ対策として、許可されたパラメータのみを受け取る仕組み
-
require(:inquiry)
= inquiry というキーが必須 -
permit(...)
= 指定したフィールドのみ許可
初心者の方への注意:
render
と redirect_to
の違いに注意してください。render
は同じリクエスト内でビューを表示し、redirect_to
は新しいリクエストを発生させます。
ステップ3: ルーティングの設定
このステップで何をするか
ルーティングは「どのURLにアクセスしたら、どのコントローラーのどのアクションを実行するか」を定義します。お問い合わせフォームでは、フォーム表示、データ送信、完了ページの3つのURLを設定します。
なぜこのステップが必要か: ユーザーがブラウザでアクセスするURLと、実際に実行される処理を結び付ける必要があるからです。
3-1. config/routes.rbの修正
ファイル: config/routes.rb
Rails.application.routes.draw do
resources :inquiries, only: [:new, :create] do
collection do
get :thank_you
end
end
# その他のルート...
end
ルーティング設定の詳細解説:
-
resources :inquiries
= RESTfulなルートを自動生成する -
only: [:new, :create]
= newとcreateアクションのルートのみを生成 -
collection do get :thankyou end
= thankyouアクション用のルートを追加
この設定により生成されるルート:
GET /inquiries/new → inquiries#new (フォーム表示)
POST /inquiries → inquiries#create (フォーム送信処理)
GET /inquiries/thank_you → inquiries#thank_you (完了ページ)
RESTfulとは: Webアプリケーションでよく使われるURL設計の規約です。リソース(この場合はInquiry)に対する操作を統一的なURLパターンで表現します。
初心者の方への注意: ルーティング設定を変更した後は、サーバーを再起動することをお勧めします。
ステップ4: メーラーの作成
このステップで何をするか
メーラーは、アプリケーションからメールを送信するための機能です。お問い合わせフォームでは、お客様への確認メールと管理者への通知メールの2種類を送信します。
なぜこのステップが必要か:
- お客様に「問い合わせを受け付けました」という安心感を与える
- 管理者に新しい問い合わせが来たことを知らせる
- ビジネス上のコミュニケーションを自動化する
4-1. InquiryMailerの生成
bin/rails generate mailer InquiryMailer thank_you
このコマンドの詳細解説:
-
InquiryMailer
= メーラー名 -
thank_you
= お客様向けメール用のメソッド名
実行後に何が起こるか:
-
app/mailers/inquirymailer.rb
- メーラーファイルが作成される -
app/views/inquirymailer/
ディレクトリとメール用のビューファイルが作成される
4-2. メーラーの実装
ファイル: app/mailers/inquiry_mailer.rb
class InquiryMailer < ApplicationMailer
default from: 'noreply@asapp-work.com'
def thank_you(inquiry)
@inquiry = inquiry
@name = inquiry.name
mail(
to: inquiry.email,
subject: 'お問い合わせありがとうございます - asapp-work'
)
end
def admin_notification(inquiry)
@inquiry = inquiry
mail(
to: 'admin@asapp-work.com', # 管理者のメールアドレス
subject: "新しいお問い合わせ: #{inquiry.inquiry_type}"
)
end
end
メーラーの詳細解説:
-
default from:
= すべてのメールの送信元アドレスを設定 -
@inquiry
= メールテンプレート内で使用する変数(インスタンス変数) -
mail()
= 実際にメールを送信するメソッド -
to:
= 送信先メールアドレス -
subject:
= メールの件名
2つのメソッドの役割:
-
thankyou
= お客様への確認メール -
adminnotification
= 管理者への通知メール
4-3. メールテンプレートの作成
お客様向けメール(HTML版): app/views/inquiry_mailer/thank_you.html.erb
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #f8f9fa; padding: 20px; text-align: center; }
.content { padding: 20px; }
.footer { background-color: #f8f9fa; padding: 10px; text-align: center; font-size: 12px; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>お問い合わせありがとうございます</h1>
</div>
<div class="content">
<p><%= @name %> 様</p>
<p>この度は、asapp-workにお問い合わせいただき、誠にありがとうございます。</p>
<p>以下の内容でお問い合わせを受け付けいたしました:</p>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 10px; font-weight: bold; width: 30%;">ご担当者様</td>
<td style="padding: 10px;"><%= @inquiry.name %></td>
</tr>
<% if @inquiry.company.present? %>
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 10px; font-weight: bold;">会社名</td>
<td style="padding: 10px;"><%= @inquiry.company %></td>
</tr>
<% end %>
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 10px; font-weight: bold;">メールアドレス</td>
<td style="padding: 10px;"><%= @inquiry.email %></td>
</tr>
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 10px; font-weight: bold;">お問い合わせ種類</td>
<td style="padding: 10px;"><%= @inquiry.inquiry_type %></td>
</tr>
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 10px; font-weight: bold;">お問い合わせ内容</td>
<td style="padding: 10px;"><%= simple_format(@inquiry.content) %></td>
</tr>
</table>
<p>内容を確認の上、2営業日以内にご連絡させていただきます。</p>
<p>何かご不明な点がございましたら、お気軽にお問い合わせください。</p>
<p>今後ともよろしくお願いいたします。</p>
</div>
<div class="footer">
<p>asapp-work.com</p>
<p>このメールは自動送信されています。</p>
</div>
</div>
</body>
</html>
メールテンプレートの詳細解説:
- HTMLメールなので、CSSスタイルを使って見た目を整えています
-
<%= @inquiry.name %>
= メーラーから渡された変数を表示 -
<% if @inquiry.company.present? %>
= 会社名が入力されている場合のみ表示 -
simple_format()
= 改行を<br>
タグに自動変換するRailsのヘルパー
なぜHTMLメールを使うか: プレーンテキストメールよりも見やすく、プロフェッショナルな印象を与えることができるからです。
ステップ5: ビューの作成
このステップで何をするか
ビューは、ユーザーが実際に目にするHTML画面を作成する部分です。お問い合わせフォームと送信完了ページの2つを作成します。フォームでは入力しやすいUI、完了ページでは安心感を与える表示を心がけます。
なぜこのステップが重要か:
- ユーザーが実際に操作する画面なので、使いやすさが重要
- エラーメッセージを適切に表示して、ユーザーの修正を手助けする
- フォーム送信後に適切なフィードバックを提供する
5-1. フォームページの作成
ファイル: app/views/inquiries/new.html.erb
<!-- お問い合わせ -->
<section class="contact" id="contact">
<div class="l-inner">
<div class="c-ttl-frame">
<h2 class="c-ttl">お問い合わせ</h2>
</div>
<p class="contact__txt">こちらからお問い合わせ頂いた方は先着で優先的にご対応いたします。<br>初回のお客様に限り、上限¥100,000 -(税別)にて制作させて頂きます。(*)<br>コーダーエンジニアの社外パートナーを募集されている企業様にも対応しております。<br>zoomでのご面談も可能ですので、お気軽にお問い合わせください。</p>
<p class="contact__txt">*制作ボリュームによりご対応できないケースがございます。</p>
<div class="contact__form c-form">
<%= form_with(model: @inquiry, local: true) do |form| %>
<% if @inquiry.errors.any? %>
<div id="error_explanation" style="color: red;">
<h2><%= pluralize(@inquiry.errors.count, "error") %> prohibited this inquiry from being saved:</h2>
<ul>
<% @inquiry.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="c-form-item">
<%= form.label :name, "ご担当者様", class: "c-form-label" %>
<%= form.text_field :name, class: "c-form-input" %>
</div>
<div class="c-form-item">
<%= form.label :company, "会社名", class: "c-form-label" %>
<%= form.text_field :company, class: "c-form-input" %>
</div>
<div class="c-form-item">
<%= form.label :email, "メールアドレス", class: "c-form-label" %>
<%= form.email_field :email, class: "c-form-input" %>
</div>
<div class="c-form-item">
<%= form.label :inquiry_type, "お問い合わせ種類", class: "c-form-label" %>
<div class="c-form-frame">
<% Inquiry::INQUIRY_TYPES.each_with_index do |type, index| %>
<div class="c-form-radio">
<%= form.radio_button :inquiry_type, type, id: "s#{index + 1}" %>
<%= form.label "inquiry_type_#{type}", type, for: "s#{index + 1}" %>
</div>
<% end %>
</div>
</div>
<div class="c-form-item">
<%= form.label :content, "お問い合わせ内容", class: "c-form-label" %>
<%= form.text_area :content, class: "c-form-input c-form-textarea" %>
</div>
<div class="c-button">
<%= form.submit "確認する" %>
</div>
<% end %>
</div>
</div>
</section>
フォーム部分の詳細解説:
form_with について:
-
form_with(model: @inquiry)
= Inquiryモデルに基づくフォームを作成 -
local: true
= Ajax通信ではなく、通常のHTTPリクエストで送信 - Railsが自動的に適切なURLとHTTPメソッドを設定してくれる
エラー表示部分:
-
@inquiry.errors.any?
= バリデーションエラーがあるかどうかを確認 -
@inquiry.errors.full_messages
= すべてのエラーメッセージを配列で取得 - エラーがある場合のみ、赤いメッセージボックスを表示
各フォーム要素:
-
form.textfield
= 一行のテキスト入力フィールド -
form.emailfield
= メール入力専用フィールド(HTML5のtype=email
) -
form.radiobutton
= ラジオボタン(複数の選択肢から1つを選ぶ) -
form.textarea
= 複数行のテキスト入力エリア
ラジオボタンの動的生成:
-
Inquiry::INQUIRYTYPES.eachwith_index
= モデルで定義した定数を使って選択肢を自動生成 - 定数を変更するだけで、フォームの選択肢も自動的に更新される
初心者の方への注意:
フォームの各入力フィールドの name
属性は、Railsが自動的に適切な形式で生成してくれます。手動で設定する必要はありません。
5-2. 完了ページの作成
ファイル: app/views/inquiries/thank_you.html.erb
<!-- お問い合わせ完了 -->
<section class="contact" id="contact">
<div class="l-inner">
<div class="c-ttl-frame">
<h2 class="c-ttl">お問い合わせ完了</h2>
</div>
<div style="text-align: center; padding: 40px 20px;">
<div style="background: #f8f9fa; padding: 30px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #28a745; margin-bottom: 20px;">✅ お問い合わせありがとうございます</h3>
<p style="font-size: 16px; line-height: 1.6; margin-bottom: 15px;">
お問い合わせを正常に受け付けました。
</p>
<p style="font-size: 14px; line-height: 1.6; margin-bottom: 15px;">
ご入力いただいたメールアドレスに確認メールをお送りしました。<br>
内容を確認の上、2営業日以内にご連絡させていただきます。
</p>
<p style="font-size: 14px; line-height: 1.6; color: #666;">
メールが届かない場合は、迷惑メールフォルダもご確認ください。
</p>
</div>
<div style="margin-top: 30px;">
<%= link_to "トップページに戻る", root_path, class: "c-button", style: "display: inline-block; background: #007bff; color: white; padding: 12px 30px; text-decoration: none; border-radius: 4px;" %>
</div>
</div>
</div>
</section>
完了ページの設計思想:
- ✅ マークで視覚的に成功を表現
- 緑色を使って「成功」のイメージを与える
- 次に何が起こるか(メール送信、返信時期)を明確に説明
- トップページに戻るリンクで、ユーザーの次の行動を案内
ステップ6: 開発環境でのメール設定
このステップで何をするか
開発環境では、実際にメールを送信せずに、送信されるメールの内容をファイルとして保存する設定を行います。これにより、開発中でも安全にメール機能をテストできます。
なぜこの設定が必要か:
- 開発中に実際にメールを送信してしまうと、テスト用のメールが実際のユーザーに届いてしまう
- メールサーバーの設定なしに、簡単にメール内容を確認できる
- 開発効率が向上する
6-1. development.rbの設定
ファイル: config/environments/development.rb
# メール設定の部分に追加
config.action_mailer.delivery_method = :file
config.action_mailer.file_settings = { location: Rails.root.join('tmp/mail') }
設定の詳細解説:
-
delivery_method = :file
= メールをファイルとして保存する設定 -
location: Rails.root.join('tmp/mail')
= 保存先ディレクトリを指定 - この設定により、実際にメールを送信する代わりに、
tmp/mail/
ディレクトリにメール内容がファイルとして保存される
6-2. メール保存ディレクトリの作成
mkdir -p tmp/mail
このコマンドの詳細解説:
-
mkdir -p
= ディレクトリを作成(既に存在する場合はエラーにならない) -
tmp/mail
= メールファイルを保存するディレクトリ
重要:メール送信について
開発環境では実際にメールは送信されません!
これは意図的な設計です。開発中に実際のメールアドレスにテストメールが送信されることを防ぐためです。
開発環境での確認方法
フォーム送信後、tmp/mail/
ディレクトリにメールファイルが保存されます:
# メールファイルの一覧を確認
ls tmp/mail/
# 特定のメールファイルの内容を確認
cat tmp/mail/[ファイル名]
ファイル名の形式:
通常、メールアドレスがファイル名になります(例:jimihen@gmail.com
)
実際にメールを送信したい場合
本格的な開発やテストで実際にメールを送信したい場合は、以下の方法があります。
方法1: Gmail SMTP設定(推奨)
Gmail を使ってメールを送信する設定です。個人の開発環境でのテストに適しています。
手順1: Gmailアプリパスワードの取得
- Googleアカウント設定 → セキュリティに移動
- 2段階認証プロセスを有効化
- アプリパスワードを生成(16桁のパスワードが生成される)
手順2: development.rbの設定変更
# config/environments/development.rb
# 先ほどの設定を以下に変更
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: 'your-email@gmail.com', # 実際のGmailアドレス
password: 'your-app-password', # アプリパスワード(通常のパスワードではない)
authentication: 'plain',
enable_starttls_auto: true
}
手順3: セキュリティのため環境変数を使用(推奨)
パスワードをコードに直接書くのは危険なので、環境変数を使用します:
# .env ファイルを作成
echo "GMAIL_USERNAME=your-email@gmail.com" >> .env
echo "GMAIL_PASSWORD=your-app-password" >> .env
# Gemfile に追加
gem 'dotenv-rails', groups: [:development, :test]
bundle install
# config/environments/development.rb
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: ENV['GMAIL_USERNAME'],
password: ENV['GMAIL_PASSWORD'],
authentication: 'plain',
enable_starttls_auto: true
}
方法2: その他のメールサービス
本格的な開発では、以下のようなメールサービスの利用を推奨します:
- SendGrid - 信頼性が高く、初期費用無料プランあり
- AWS SES - AWSを使用している場合に適している
- Mailgun - 開発者に人気の高いサービス
設定後の確認手順
- サーバーを再起動
bin/rails restart
- フォームから再送信
- 実際のメールアドレスに届くことを確認
初心者の方への注意:
- 最初は必ずファイル保存(:file)設定で始めることをお勧めします
- 実際のメール送信設定は、基本機能が完成してから行いましょう
- Gmailのアプリパスワードは、通常のパスワードとは異なる特別なパスワードです
コード詳細解説
このセクションでは、先ほど実装したコードがどのように連携して動作するかを、より深く理解していきます。RailsのMVCパターンの流れを追いながら、各コンポーネントの役割を詳しく説明します。
MVCの連携フロー
お問い合わせフォームが送信されてから完了までの、システム内部の詳しい流れを見てみましょう。
1. ユーザーがフォームを送信
POST /inquiries
ユーザーがフォームの「確認する」ボタンをクリックすると、ブラウザはPOSTリクエストを /inquiries
URLに送信します。
2. ルーティングがリクエストを受信
# config/routes.rb
resources :inquiries, only: [:new, :create]
# → InquiriesController#create にルーティング
この段階で何が起こるか:
- Railsがルーティングテーブルを確認
- POST /inquiries が InquiriesController の create アクションにマッピング
- フォームデータが params ハッシュとして渡される
3. コントローラーが処理
# app/controllers/inquiries_controller.rb
def create
@inquiry = Inquiry.new(inquiry_params) # ① パラメータからオブジェクト作成
if @inquiry.save # ② バリデーション&DB保存
InquiryMailer.thank_you(@inquiry).deliver_now # ③ メール送信
redirect_to thank_you_inquiries_path # ④ 完了ページへリダイレクト
else
render :new # ⑤ エラー時はフォーム再表示
end
end
各ステップの詳細:
① パラメータからオブジェクト作成:
-
inquiry_params
メソッドでセキュリティチェック済みのパラメータを取得 - 新しい Inquiry オブジェクトを作成(まだデータベースには保存されていない)
② バリデーション&DB保存:
-
@inquiry.save
が呼ばれると、まずバリデーションが実行される - すべてのバリデーションが通過した場合のみ、データベースに保存される
- 戻り値は成功時
true
、失敗時false
4. モデルがデータを検証・保存
# app/models/inquiry.rb
validates :name, presence: true # バリデーション実行
# → データベースの inquiries テーブルに保存
バリデーション処理の詳細:
- 各フィールドに対して定義されたバリデーションルールを順次実行
- エラーがある場合は
@inquiry.errors
オブジェクトにエラー情報を蓄積 - すべてのバリデーションが通過した場合のみ、データベース保存を実行
5. メーラーがメール送信
# app/mailers/inquiry_mailer.rb
def thank_you(inquiry)
@inquiry = inquiry # ビューで使用する変数設定
mail(to: inquiry.email, subject: '...') # メール送信
end
メール送信処理の詳細:
- メーラーのメソッドが呼ばれると、メールテンプレート(ERBファイル)が処理される
- @inquiry 変数を使って、テンプレート内に動的な内容を埋め込む
-
delivernow
で即座にメールを送信(非同期処理の場合はdeliverlater
を使用)
Strong Parameters の詳細
private
def inquiry_params
params.require(:inquiry).permit(:name, :company, :email, :inquiry_type, :content)
end
Strong Parameters が重要な理由:
セキュリティリスクの例:
もしも Strong Parameters を使わずに params[:inquiry]
をそのまま使った場合、悪意のあるユーザーが以下のようなデータを送信する可能性があります:
# 危険な例(実際のコードに書かないでください)
params[:inquiry] = {
name: "太郎",
email: "taro@example.com",
admin: true, # 管理者権限を不正に設定しようとする
created_at: 1.year.ago # 作成日時を偽装しようとする
}
Strong Parameters の動作:
-
require(:inquiry)
= inquiry というキーが存在することを確認 -
permit(...)
= 指定されたキーのみを許可し、それ以外は除外 - これにより、予期しないパラメータによる攻撃を防ぐ
バリデーションの詳細
validates :email, presence: true,
format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
バリデーション実行のタイミングと流れ:
-
@inquiry.save
または@inquiry.valid?
が呼ばれる - モデルで定義されたすべてのバリデーションルールが順次実行される
- 各バリデーションの結果が
@inquiry.errors
オブジェクトに蓄積される - エラーがない場合は
true
、エラーがある場合はfalse
を返す - エラーがある場合、データベースへの保存は実行されない
エラーメッセージの取得方法:
-
@inquiry.errors.full_messages
= すべてのエラーメッセージを配列で取得 -
@inquiry.errors[:email]
= 特定のフィールドのエラーメッセージを取得 -
@inquiry.errors.any?
= エラーがあるかどうかを真偽値で取得
カスタムバリデーションの例: ```ruby
より高度なバリデーションの例
validates :email, uniqueness: true # 重複チェック validates :content, length: { minimum: 10, maximum: 1000 } # 文字数範囲チェック validate :emaildomaincheck # カスタムバリデーション
private
def emaildomaincheck if email.present? && !email.end_with?('@example.com', '@test.com') errors.add(:email, '許可されていないドメインです') end end ```
動作確認とテスト
このセクションでは、実装したお問い合わせフォームが正しく動作するかを段階的に確認していきます。正常ケースとエラーケースの両方をテストして、想定通りに動作することを確認しましょう。
テスト前の準備
まず、実装したコードに間違いがないか、必要なファイルが揃っているかを確認しましょう。
チェックリスト:
- マイグレーションが実行済みか(
bin/rails db:migrate
) - すべてのファイルが正しい場所に配置されているか
- メール保存用ディレクトリが作成済みか(
tmp/mail/
)
テスト手順
1. サーバー起動
cd portfolio_rails
bin/rails server
サーバー起動時の確認ポイント:
- エラーメッセージが表示されていないか
- 「Listening on tcp://localhost:3000」のようなメッセージが表示されるか
- ポート3000が他のアプリケーションで使用されていないか
2. フォームアクセス
ブラウザで以下にアクセス:
http://localhost:3000/inquiries/new
期待される表示:
- お問い合わせフォームが正しく表示される
- すべての入力フィールドが表示される
- ラジオボタンの選択肢が正しく表示される
- CSSスタイルが適用されている
もしエラーが表示された場合:
- ルーティング設定を確認
- コントローラーのnewアクションを確認
- ビューファイルの存在を確認
3. 正常ケースのテスト
実際のユーザーが正しく入力した場合のテストを行います。
テスト用の入力例:
- ご担当者様: 田中太郎
- 会社名: サンプル株式会社
- メールアドレス: tanaka@example.com
- お問い合わせ種類: お見積もり
- お問い合わせ内容: ホームページ制作のお見積もりをお願いします。予算は50万円程度を考えています。納期についても相談させてください。
送信ボタンクリック後の期待される結果:
- 完了ページ(
/inquiries/thank_you
)が表示される - 「お問い合わせありがとうございます」のメッセージが表示される
-
tmp/mail/
ディレクトリにメールファイルが2つ作成される - データベースにデータが正しく保存される
4. バリデーションエラーのテスト
各種エラーケースを意図的に発生させて、適切にエラーハンドリングされるかを確認します。
テストケース1: 必須項目を空にして送信
- 名前を空欄にして送信
- メールアドレスを空欄にして送信
- お問い合わせ内容を空欄にして送信
期待される結果:
- フォームが再表示される
- エラーメッセージが赤いボックスで表示される
- 入力済みの他のフィールドの値が保持される
- データベースに保存されない
テストケース2: 不正なメールアドレスで送信
- 「invalid-email」(@マークなし)
- 「test@」(ドメイン部分なし)
- 「@example.com」(ローカル部分なし)
期待される結果:
- 「正しいメールアドレスを入力してください」のエラーメッセージ表示
- フォームが再表示される
テストケース3: 文字数制限を超えた入力
- 名前に51文字以上を入力
- お問い合わせ内容に1001文字以上を入力
期待される結果:
- 文字数制限に関するエラーメッセージが表示される
- フォームが再表示される
5. データベース確認
Railsコンソールを使って、データが正しく保存されているかを確認します。
bin/rails console
# 保存されたすべてのお問い合わせを確認
Inquiry.all
# 最新のお問い合わせを確認
Inquiry.last
# 特定の条件でお問い合わせを検索
Inquiry.where(inquiry_type: 'お見積もり')
# レコード数を確認
Inquiry.count
確認すべきポイント:
- 入力した値が正しく保存されているか
-
createdat
とupdatedat
が適切に設定されているか - バリデーションエラーが発生した場合は保存されていないか
6. メール確認
開発環境(ファイル保存)の場合:
# メールファイルの一覧を確認
ls tmp/mail/
# ファイル内容を確認(お客様向け)
cat tmp/mail/[お客様のメールアドレス]
# ファイル内容を確認(管理者向け)
cat tmp/mail/admin@asapp-work.com
期待される結果:
- 2つのメールファイルが作成される
- お客様向けメール:入力された情報が正しく表示される
- 管理者向けメール:新規お問い合わせの通知内容が表示される
- HTML形式で見やすくフォーマットされている
実際のメール送信設定の場合:
- 指定したメールアドレスに実際にメールが届く
- 迷惑メールフォルダもチェック
- メールの差出人、件名、本文が正しく表示される
エラーが発生した場合のデバッグ方法
ログの確認
tail -f log/development.log
ログで確認すべき情報:
- リクエストのパラメータ
- SQLクエリの実行結果
- エラーメッセージとスタックトレース
- メール送信の実行ログ
ブラウザの開発者ツール
確認すべき項目:
- ネットワークタブ:HTTPリクエストの詳細
- コンソールタブ:JavaScriptエラー
- 要素タブ:HTMLの構造とCSSスタイル
よくある問題と解決方法
問題1: フォームが表示されない
- ルーティング設定を確認
- コントローラーのアクション名を確認
- ビューファイルのパスを確認
問題2: 送信後にエラーページが表示される
- Strong Parametersの設定を確認
- モデルのバリデーション設定を確認
- データベースのテーブル構造を確認
問題3: メールが作成されない
- メーラーの設定を確認
- development.rbの設定を確認
- tmp/mailディレクトリの存在を確認
テスト結果の記録
テスト実行後は、結果を記録して今後の開発に活かしましょう。
記録すべき項目:
- 各テストケースの実行結果(成功/失敗)
- 発見した問題点と解決方法
- ユーザビリティの改善点
- パフォーマンスの問題
トラブルシューティング
このセクションでは、お問い合わせフォーム実装時によく遭遇するエラーと、その解決方法を詳しく説明します。エラーメッセージから原因を特定し、段階的に解決していく方法を学びましょう。
よくあるエラーと解決方法
1. No route matches [POST] "/inquiries"
エラーの意味:
POST メソッドで /inquiries
URLにアクセスしようとしたが、該当するルートが見つからない。
原因:
- routes.rb でPOSTルートが定義されていない
- ルーティングの設定に誤りがある
- サーバーの再起動が必要
解決方法:
# config/routes.rb
Rails.application.routes.draw do
resources :inquiries, only: [:new, :create] do
collection do
get :thank_you
end
end
# その他のルート...
end
確認手順:
- routes.rbファイルの内容を確認
- サーバーを再起動(Ctrl+C で停止後、
bin/rails server
で再起動) - ルートの確認:
bin/rails routes | grep inquiries
期待される出力:
new_inquiry GET /inquiries/new(.:format) inquiries#new
inquiries POST /inquiries(.:format) inquiries#create
thank_you_inquiries GET /inquiries/thank_you(.:format) inquiries#thank_you
2. undefined method 'inquiry_path'
エラーの意味:
Railsが inquiry_path
というヘルパーメソッドを見つけられない。
原因:
-
form_with(model: @inquiry)
を使っているが、対応するルートが不完全 - RESTfulルートのcreateアクションが定義されていない
解決方法:
# routes.rb で以下を確認
resources :inquiries, only: [:new, :create] # createアクションが必要
または、フォームの書き方を変更:
<!-- 特定のURLを指定する場合 -->
<%= form_with(url: inquiries_path, local: true) do |form| %>
<!-- フォーム内容 -->
<% end %>
初心者向け説明:
form_with(model: @inquiry)
を使うと、Railsは自動的に適切なURLとHTTPメソッドを決定しようとします。新しいレコードの場合は POST /inquiries
、既存レコードの編集の場合は PATCH /inquiries/:id
を使用します。
3. バリデーションエラーが表示されない
症状: フォームで不正な値を入力して送信しても、エラーメッセージが表示されない。
原因:
- ビューファイルでエラー表示のコードが記述されていない
- コントローラーで適切にエラーハンドリングされていない
解決方法:
ビューファイルの確認:
<!-- app/views/inquiries/new.html.erb -->
<%= form_with(model: @inquiry, local: true) do |form| %>
<!-- エラー表示部分を追加 -->
<% if @inquiry.errors.any? %>
<div id="error_explanation" style="color: red;">
<h2><%= pluralize(@inquiry.errors.count, "error") %> prohibited this inquiry from being saved:</h2>
<ul>
<% @inquiry.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<!-- フォームフィールド -->
<% end %>
コントローラーの確認:
# app/controllers/inquiries_controller.rb
def create
@inquiry = Inquiry.new(inquiry_params)
if @inquiry.save
# 成功時の処理
else
# エラー時は必ず render :new を使う(redirect_to ではない)
render :new, status: :unprocessable_entity
end
end
重要なポイント:
- エラー時は
render :new
を使用(redirectto
を使うとエラー情報が失われる) -
@inquiry
オブジェクトにエラー情報が保持される -
status: :unprocessableentity
で適切なHTTPステータスコードを返す
4. メールが送信されない
症状: フォーム送信は成功するが、メールが送信されない(またはファイルが作成されない)。
原因と解決方法:
原因1: メーラーの設定やメソッド名の間違い
# コントローラーで正しいメソッド名を使用
InquiryMailer.thank_you(@inquiry).deliver_now
# メーラーで正しい引数を受け取る
class InquiryMailer < ApplicationMailer
def thank_you(inquiry) # 引数名を確認
@inquiry = inquiry # インスタンス変数に代入
mail(to: inquiry.email, subject: '...')
end
end
原因2: メーラーファイルが存在しない
# メーラーファイルの存在確認
ls app/mailers/inquiry_mailer.rb
# 存在しない場合は生成
bin/rails generate mailer InquiryMailer thank_you
原因3: メールテンプレートが存在しない
# テンプレートファイルの存在確認
ls app/views/inquiry_mailer/thank_you.html.erb
# 存在しない場合は手動作成またはメーラーを再生成
原因4: 開発環境の設定問題
# config/environments/development.rb の確認
config.action_mailer.delivery_method = :file
config.action_mailer.file_settings = { location: Rails.root.join('tmp/mail') }
# tmp/mailディレクトリの存在確認
ls -la tmp/mail/
# 存在しない場合は作成
mkdir -p tmp/mail
5. Strong Parameters エラー
エラー例:
Unpermitted parameter: XXX
エラーの意味: 許可されていないパラメータが送信された。
原因:
- フォームで送信されるフィールド名と、permitで許可されているフィールド名が一致しない
- 新しいフィールドを追加したが、permitに追加し忘れた
解決方法:
# app/controllers/inquiries_controller.rb
private
def inquiry_params
params.require(:inquiry).permit(:name, :company, :email, :inquiry_type, :content)
# 新しいフィールドを追加した場合は、必ずここにも追加する
end
デバッグ方法:
# コントローラーに一時的に追加してパラメータを確認
def create
puts "Received params: #{params.inspect}"
puts "Inquiry params: #{params[:inquiry].inspect}"
# ...
end
6. メールが届かない(開発環境)
症状:
フォーム送信は成功するが、実際のメールアドレスにメールが届かない。
これは正常な動作です!
理由: 開発環境では、実際にメールを送信せずに、ファイルとして保存する設定になっています。
確認方法:
# メールファイルが作成されているか確認
ls tmp/mail/
# ファイルの内容を確認
cat tmp/mail/[ファイル名]
実際にメールを送信したい場合: 前述の「Gmail SMTP設定」を参照してください。
7. Gmail SMTP設定でのエラー
エラー例:
Net::SMTPAuthenticationError: 535-5.7.8 Username and Password not accepted
原因:
- 通常のGoogleパスワードを使用している(アプリパスワードが必要)
- 2段階認証が無効になっている
- アプリパスワードが間違っている
解決手順:
- 2段階認証の確認
- Googleアカウント設定 → セキュリティ
- 2段階認証プロセスが「オン」になっていることを確認
- アプリパスワードの生成
- セキュリティページで「アプリパスワード」を検索
- 新しいアプリパスワードを生成(16桁の文字列)
- 通常のパスワードではなく、このアプリパスワードを使用
- 設定ファイルの確認
# config/environments/development.rb
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: 'your-actual-gmail@gmail.com', # 実際のGmailアドレス
password: 'abcd efgh ijkl mnop', # 16桁のアプリパスワード(スペース含む)
authentication: 'plain',
enable_starttls_auto: true
}
デバッグの基本手順
1. エラーメッセージの詳細確認
# 開発ログの確認
tail -f log/development.log
# 特定のエラーを検索
grep -i error log/development.log
2. Railsコンソールでのデバッグ
bin/rails console
# バリデーションエラーの詳細確認
inquiry = Inquiry.new(name: "", email: "invalid")
inquiry.valid? # false が返される
inquiry.errors.full_messages # エラーメッセージの配列
# パラメータの確認
params = { inquiry: { name: "テスト", email: "test@example.com" } }
inquiry = Inquiry.new(params[:inquiry])
inquiry.valid?
3. ステップバイステップの確認
問題を小さく分割して確認:
- ルーティングは正しく設定されているか?
- コントローラーのアクションは実行されているか?
- モデルのバリデーションは通過しているか?
- データベースに保存されているか?
- メーラーは正しく呼ばれているか?
4. 一時的なデバッグコードの追加
# コントローラーに追加
def create
puts "=== DEBUG START ==="
puts "Params: #{params.inspect}"
puts "Inquiry params: #{inquiry_params.inspect}"
@inquiry = Inquiry.new(inquiry_params)
puts "Inquiry object: #{@inquiry.inspect}"
puts "Valid?: #{@inquiry.valid?}"
puts "Errors: #{@inquiry.errors.full_messages}" unless @inquiry.valid?
if @inquiry.save
puts "Save successful"
# メール送信処理
else
puts "Save failed"
end
puts "=== DEBUG END ==="
# 通常の処理...
end
よくある質問(FAQ)
Q1. フォームは送信できるのに、メールが届きません
A: これは正常です!開発環境では実際にメールを送信せず、tmp/mail/
ディレクトリにファイルとして保存されます。
ls tmp/mail/ # メールファイルを確認
実際にメールを送信したい場合は、「メール送信について」の章を参照してください。
補足説明: この設計は意図的なものです。開発中に実際のメールアドレスにテストメールが送信されることを防ぎ、安全な開発環境を提供しています。
Q2. バリデーションエラーが表示されない
A: ビューファイルにエラー表示のコードが含まれていない可能性があります。以下を確認してください:
<% if @inquiry.errors.any? %>
<div id="error_explanation">
<!-- エラー表示のコード -->
</div>
<% end %>
よくある原因:
- エラー表示部分のコードが記述されていない
- コントローラーで
redirect_to
を使っている(render
を使用する必要がある) - Strong Parametersでフィールドが許可されていない
Q3. 「No route matches [POST] /inquiries
」エラーが出る
A: ルーティングの設定が不完全です。config/routes.rb
を以下のように設定してください:
resources :inquiries, only: [:new, :create] do
collection do
get :thank_you
end
end
確認方法:
bash
bin/rails routes | grep inquiries
このコマンドで適切なルートが設定されているか確認できます。
Q4. Gmail SMTPでメールが送信できない
A: 以下を確認してください:
- Googleアカウントで2段階認証が有効になっているか
- アプリパスワードを正しく生成・設定しているか
- 通常のパスワードではなく、アプリパスワードを使用しているか
詳細な設定手順:
- Googleアカウント設定 → セキュリティ
- 2段階認証を有効化
- 「アプリパスワード」で16桁のパスワードを生成
- この16桁のパスワードを設定ファイルに記述
Q5. 本番環境でメール設定はどうすれば良い?
A: 本番環境では以下のようなメールサービスの利用を推奨します:
推奨サービス:
- SendGrid: 信頼性が高く、無料プランから始められる
- AWS SES: AWSを使用している場合に最適
- Mailgun: 開発者に人気、使いやすいAPI
- Postmark: トランザクションメールに特化
選択基準:
- 月間送信数と料金
- 配信成功率(Deliverability)
- サポート体制
- 既存システムとの連携しやすさ
Q6. お問い合わせ種類を追加したい
A: app/models/inquiry.rb
の INQUIRY_TYPES
定数を変更してください:
INQUIRY_TYPES = ['お見積もり', 'zoomご相談', '外部パートナー依頼', 'その他', '新しい種類'].freeze
より柔軟な管理方法: 将来的には、管理画面から動的に追加・編集できるように、別テーブルで管理することを推奨します。
Q7. メールのデザインを変更したい
A: 以下のファイルを編集してください:
-
app/views/inquirymailer/thankyou.html.erb
- お客様向けHTML -
app/views/inquirymailer/thankyou.text.erb
- お客様向けテキスト -
app/views/inquirymailer/adminnotification.html.erb
- 管理者向けHTML
デザインのコツ:
- インラインCSSを使用する(外部CSSは適用されない場合がある)
- テーブルレイアウトを活用する(メールクライアントの互換性のため)
- 画像は絶対URLを使用する
- テキスト版も必ず用意する
Q8. フォームの項目を追加したい
A: 以下の手順で追加できます:
- マイグレーションファイルを作成
bin/rails generate migration AddFieldToInquiries field_name:string
bin/rails db:migrate
- モデルにバリデーションを追加
# app/models/inquiry.rb
validates :field_name, presence: true # 必要に応じて
- Strong Parametersに追加
# app/controllers/inquiries_controller.rb
def inquiry_params
params.require(:inquiry).permit(:name, :company, :email, :inquiry_type, :content, :field_name)
end
- ビューにフォームフィールドを追加
<div class="c-form-item">
<%= form.label :field_name, "フィールド名", class: "c-form-label" %>
<%= form.text_field :field_name, class: "c-form-input" %>
</div>
Q9. CSS/JavaScriptが効かない
A: 以下を確認してください:
CSSが効かない場合:
- アセットプリコンパイルが正しく実行されているか
- CSSファイルのパスが正しいか
- ブラウザのキャッシュをクリアしてみる
JavaScriptが効かない場合:
- ブラウザのコンソールでエラーが出ていないか確認
- jQueryが読み込まれているか確認
- Turbolinksとの互換性を考慮
まずは無料で7講座から始めましょう!
募集人数には制限があります。サインアップはお早めに。
8月24日まで