Rails4で登録確認ページを経由して登録する方法

# やりたいこと
Railsでは基本的にフォームで入力した内容はダイレクトにDBへ登録されてしまう。
Railsのformから送った内容を確認するページで見た後、再編集または登録を行いたい。

# ここで実装すること

* newページからconfirmページへ遷移可能に
* newページからconfirmへ行く時にバリデーションチェック
* confirmページでnewページの内容を確認可能に
* confirmページからnewページに戻るボタンを設置
* confirmページから登録

# 実装方法

scaffoldのTask管理アプリに実際に実装していきます。

## 前準備

実装する土台を用意します。

```bash:bash
$ rails new test_app
$ cd test_app
$ bundle install
$ rails g scaffold task title:string content:text
```

## 1. 確認ページのRoutingの追加

confirmというページで確認を行えるように穴を開けます。

```rb:config/routes.rb
Rails.application.routes.draw do
  resources :tasks do
    collection do
      post 'confirm'
    end
  end
  # 中略
end
```

下記のように出ていたらOK！

```bash:bash
$ rake routes
       Prefix Verb   URI Pattern               Controller#Action
confirm_tasks POST   /tasks/confirm(.:format)  tasks#confirm   # <=追加URL
        tasks GET    /tasks(.:format)          tasks#index
              POST   /tasks(.:format)          tasks#create
     new_task GET    /tasks/new(.:format)      tasks#new
    edit_task GET    /tasks/:id/edit(.:format) tasks#edit
         task GET    /tasks/:id(.:format)      tasks#show
              PATCH  /tasks/:id(.:format)      tasks#update
              PUT    /tasks/:id(.:format)      tasks#update
              DELETE /tasks/:id(.:format)      tasks#destroy
```

## 2. FormからのPOSTで確認ページへ遷移させる実装

### 2.1. 確認アクションへのPOST
scaffoldで自動生成されたform用のパーシャルはデフォルトで登録アクションへ飛びます。
これを確認用のアクションへ飛ばすように下記のように変更します。
form_forのurlにactionを指定すればOKです。

```erb:app/views/tasks/_form.html.erb
<%= form_for @task, url: {action: 'confirm'} do |f| # <= 変更 %>
  <% if @task.errors.any? %>
    # 中略
  <% end %>

  <div class="field">
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :content %><br>
    <%= f.text_area :content %>
  </div>
  <div class="actions">
    <%= f.submit 'next!' %>
  </div>
<% end %>
```

### 2.2. 確認アクションの内容

取りあえずControllerにも対応アクションのconfirmを入れます。
Viewで該当データを表示等する為にインスタンス変数で取得します。
`valid?`および`invalid?`メソッドはバリデーションチェックなどを行うメソッドで、
バリデーションチェックがエラーになったら（エラーMSGがあったら）Form入力画面へ差し戻します。

```rb:app/controllers/tasks_controller.rb
class TasksController < ApplicationController

  # 中略

  def confirm
    @task = Task.new(task_params) # <=POSTされたパラメータを取得
    render :new if @task.invalid? # <=バリデーションチェックNGなら戻す
  end

  #中略
end
```

## 3. 戻るボタンと登録アクションの実装

### 3.1. 確認ページの実装

確認ページを作成します。
登録や戻る際にPOSTでデータを送る為に`hidden_field`で情報を保持しています。
また、戻る処理を実現する為に、name属性を使用してcreatアクション内で分岐を行います。

```erb:app/views/tasks/confirm.html.erb
<%= form_for @task do |f| %>
  <div class="field">
    title: <%= @task.title %>
    <%= f.hidden_field :title   # <=データ保持 %>
  </div>
  <div class="field">
    content: <%= @task.content %>
    <%= f.hidden_field :content # <=データ保持 %>
  </div>
  <div class="actions">
    <%= f.submit 'Back!', name: 'back'  # <=戻る為のname %>
  </div>
  <div class="actions">
    <%= f.submit 'create!' %>
  </div>
<% end %>
```

### 3.2. 登録アクションの実装

`f.submit`のname属性の指定有無でnew画面に戻す、または登録の実行を行います。
※フォーマット指定による処理は入れていません。

```rb:app/controllers/tasks_controller.rb
  def create
    @task = Task.new(task_params)

    if params[:back]
      render :new
    elsif @task.save
      redirect_to @task, notice: 'Task was successfully created.'
    else
      render :new
    end
  end

  # 中略
end
```