よくあるお問い合わせフォームみたいので、ユーザーの入力を一度確認画面みたいな感じで表示してから送信したい時・・
- ユーザーが問い合わせの入力
- 「確認」ボタンをクリック
- 入力した項目を一度確認画面に表示(入力とほとんど一緒)
- 「送信」ボタンをクリック
- 実際にモデルとして保存
という流れをRailsで実装する時の定石
Model
- Question
app/models/question.rb
validates :title, presence: true
validates :name, presence: true
validates :content, presence: true
validates_acceptance_of :confirming
after_validation :check_confirming
def check_confirming
errors.delete(:confirming)
self.confirming = errors.empty? ? '1' : ''
end
ここではDBに保存する値は、 title, name, content とする。(必須入力)
validates_acceptance_of
はRailsの機能。
validates_acceptance_of - リファレンス - - Railsドキュメント
confirmingはDBに保存しなくて大丈夫。
ポイントは次の2点
- validate_accepttance_ofが指定してあるので、confirmingの値が存在するかのバリデーションチェックが発生
- 一度validationした後に
after_validation
で指定されているメソッドがコールされる。この時confirming以外にエラーがない場合は、チェック済として値をセット
Controller
応答するコントローラーメソッド
RESTに従う
- 新規質問入力画面を表示 : QuestionsController#new (GET)
- 確認ボタンクリックに応答 : QuestionsController#create (POST)
- 入力内容を確認する画面を表示 : QuestionsController#new (GET)
- 送信ボタンクリックに応答 : QuestionsController#create (POST)
ポイントはmodelのconfirmingのバリデーション機能で、上手いことページ遷移を発生させてるとこ。
app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
def new
@question = Question.new
end
def create
@question = Question.build(question_params)
respond_to do |format|
if @question.save
format.html { redirect_to @question, notice: '質問を送信しました。' }
else
# 一度目の「確認」ボタンクリック時は、confirmingがセットされていないのsaveでエラーが発生しこっちに来る
# ただし、ここに到達した時点で model の after_validation 後なので、confirmingはセットされている状態で new アクションへ
format.html { render action: 'new' }
end
end
end
private
def question_params
params.require(:question).permit(:title, :name, :content, :confirming)
end
end
View
同じフォームで confirming
値の有無で、画面表示を分岐させる。
(入力項目と確認項目はinputか単なるテキストかの違いだけで、ほぼ同一なので、一緒のテンプレートにある方がわかりやすい)
(simple_form gemを使っている)
app/views/questions/_form.html.haml
= simple_form_for @question do |f|
- if @question.confirming.blank?
.form-inputs
= f.input :name, label: 'お名前'
= f.input :title, label: 'ご質問'
= f.input :content, label: 'ご質問内容'
.form-actions
= f.button :submit, '内容を確認する'
- else
%table.table
%tr
%th お名前
%td= @question.name
%tr
%th ご質問
%td= @question.title
%tr
%th ご質問内容
%td= @question.content
.form-inputs
= f.hidden_field :name
= f.hidden_field :title
= f.hidden_field :content
.form-actions
%p この内容でご質問メールを送信します。よろしいですか?
= f.button :submit, '送信する'
= f.hidden_field :confirming
2回目の「送信」ボタンでは、ユーザー入力のパラメータはhiddenで渡す。