Posted at

Railsで入力の確認画面を出すときの定石

More than 3 years have passed since last update.


よくあるお問い合わせフォームみたいので、ユーザーの入力を一度確認画面みたいな感じで表示してから送信したい時・・


  • ユーザーが問い合わせの入力

  • 「確認」ボタンをクリック

  • 入力した項目を一度確認画面に表示(入力とほとんど一緒)

  • 「送信」ボタンをクリック

  • 実際にモデルとして保存

という流れを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で渡す。