Scaffoldに確認画面を追加する

# 概要
scaffoldで生成したフォームに確認画面を追加します。
新規作成(new)の確認画面作成は見かけるのですが、編集(edit)に対するものは無く、割と悩んだので作成しました。
コントローラのcreateメソッドとupdateメソッド内で、確認画面の表示とDBへの保存を振り分けるようにしました。

# 準備
まずはscaffoldを作成します。

```bash
rails generate scaffold book title:string author:string
```

# バリデーションの追加
フォームに対するバリデーションを追加します。確認画面に移る前に入力値に問題が無いか検証します。

```ruby:book.rb
class Book < ApplicationRecord
  validates :title, :author, presence: true
end
```

# コントローラ
新規作成時のcreateメソッドと編集時のupdateメソッドをそれぞれ変更します。

## 新規作成
バリデーションで問題なく、confirmボタンが押された時は確認画面を開きます。
backボタンが押された時は新規作成画面に戻ります。

```ruby:books_controller.rb
  # POST /books
  # POST /books.json
  def create
    @book = Book.new(book_params)

    respond_to do |format|
      if @book.valid? && params[:confirm]
        format.html { render :new_confirm }
      elsif params[:back]
        format.html { render :new }
      elsif @book.save
        format.html { redirect_to @book, notice: 'Book was successfully created.' }
        format.json { render :show, status: :created, location: @book }
      else
        format.html { render :new }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end
```

## 編集
基本は新規作成と同じです。
scaffold自動生成の@book.updateを使わず、assign_attributesを使ってDBに保存しないようにすることで、確認画面を表示できるようにしています。

```ruby:books_controller.rb
  # PATCH/PUT /books/1
  # PATCH/PUT /books/1.json
  def update
    @book.assign_attributes(book_params)

    respond_to do |format|
      if @book.valid? && params[:confirm]
        format.html { render :edit_confirm }
      elsif params[:back]
        format.html { render :edit }
      elsif @book.save
        format.html { redirect_to @book, notice: 'Book was successfully updated.' }
        format.json { render :show, status: :ok, location: @book }
      else
        format.html { render :edit }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end
```

# ビュー
scaffold生成の作成画面を変更し、確認画面を新規に追加します。

## 作成画面
通常のcommitボタンからconfirmボタンに変更しています。

```erb:_form.html.erb
  <div class="actions">
    <%= form.submit 'Confirm', name: 'confirm' %>
  </div>
```

## 確認画面
まずフォームを呼び出すためのビューを作成します。

```erb:new_confirm.html.erb
<h1>New Book Confirmation</h1>

<%= render 'confirm', book: @book %>
```

```erb:edit_confirm.html.erb
<h1>Editing Book Confirmation</h1>

<%= render 'confirm', book: @book %>
```

実際のconfirmのビューはこちらです。form.hidden_fieldで値を持たせて、commitボタン押下時に値を受け取れるようにしています。
さらに、前画面に戻れるようにbackボタンを追加しています。

```erb:_confirm.html.erb
<%= form_with(model: book, local: true) do |form| %>
  <div class="field">
    <%= form.label :title %>
    <%= book.title %>
    <%= form.hidden_field :title %>
  </div>

  <div class="field">
    <%= form.label :author %>
    <%= book.author %>
    <%= form.hidden_field :author %>
  </div>

  <div class="actions">
    <%= form.submit 'Back', name: 'back' %>
    <%= form.submit %>
  </div>
<% end %>
```

# 結果
作成画面と確認画面はこのようになります。

## 作成画面
<img width="450" alt="スクリーンショット 2019-04-20 12.27.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336552/8cba0949-26cd-437f-cd99-376044dbe007.png">

## 確認画面
<img width="450" alt="スクリーンショット 2019-06-29 12.19.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336552/343d6b0e-9082-110a-0ca2-f06aaedcd4b4.png">

# 所感
Rails難しいですね。改善点ありましたら、アドバイスいただけると幸いです。

# ソースコード
ソースはこちらにアップロードしました。
https://github.com/myzkyuki/scaffold_confirm_example