Help us understand the problem. What is going on with this article?

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で渡す。

heartrails
ハートレイルズは、新規事業の立ち上げに伴うウェブサービス、スマホアプリの企画、開発、運用に特化した開発会社です。
http://www.heartrails.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした