Railsで作ったフォームがDBに格納されるまでのデータの流れ

# はじめに

[Rails チュートリアル](https://railstutorial.jp/)などで、Railsの勉強をしていてフォームを作成して、データをフォームから入力して、最終的にDBに格納するという、`View`、`Controller`、`DB`のデータの流れが勉強になったので、まとめておきます。

# 環境

この記事では以下の環境（2018年6月26日時点）で動作確認できました。

- Ruby: 2.4.1
- Rails: 5.0.7

# モデル

モデルの構成などは[以前に作成した記事](https://qiita.com/ryosuketter/items/516cc93b9dbbfd2020b4)に詳しく記載しましたので、ここでは割愛します。

# ルーティング

ルーティングの設定は以下の通りです。

```bash

$ rails routes

  Prefix Verb URI Pattern          Controller#Action
    root GET  /                    toppages#index
  signup GET  /signup(.:format)    users#new
   users POST /users(.:format)     users#create
new_user GET  /users/new(.:format) users#new
    user GET  /users/:id(.:format) users#show
```

# データの流れを大まかに

Webアプリケーションでよく見るユーザー登録に関する、`View`、`Controller`、`DB`のデータの流れを説明していきます。大まかには、

- 1. ユーザーが登録画面へ遷移するリンクをクリック（URLは`~/signup`とする）
- 2. ルーティング | `Get`（HTTPリクエスト）　| URLからアクセスすべき`controller`と`アクション`を判別（`users#new`）
- 3. コントローラが呼び出されてその中のアクションの処理が走って必要なデータ（があれば）（今回はインスタンス変数（`@user`））それを`View`に送る
- 4. ビュー | インスタンス変数の内容を元にHTMLを作成、表示
- 5. ユーザーがフォームを入力し、ユーザー登録ボタンを押した
- 6. ルーティング | `Post`（HTTPリクエスト）なので　| URLからアクセスすべき`controller`と`アクション`を判別（`users#create`しかない）
- 7. コントローラが呼び出されてその中のアクションの処理が走って必要なデータ（インスタンス変数`@user`）をDBに保存
- 8. DBに保存された

それぞれを説明していきます。

## ユーザーが登録画面へ遷移するリンクをクリック

例えばユーザーが新規登録ボタンをクリックしたら、URLが`~/sigup`だったら

## ルーティングからコントローラ（`users`）のアクション（`new`）を判別

URLが`~/sigup`だったら、どこのコントローラに行けばいいかルーティング確認したら、`users`コントローラの`new`アクションと判別

![スクリーンショット 2018-06-25 19.03.12.png](https://qiita-image-store.s3.amazonaws.com/0/14191/5c30977a-a8fa-7ac3-b798-fcaee73cd0ca.png)

## コントローラ（`users`）のアクション（`new`）内の処理

```/app/controllers/users_controller.rb
def new
  @user = User.new
end
```

`User`という名のモデルクラスに、`new`というメソッドを使って、新規レコードのためのモデルインスタンスを作成します。
今回は、何もデータがないので、空のインスタンスをここで作成して、インスタンス変数（`@user`）に代入します。
インスタンス変数を、フォームがある`View`に送ります。

ここでは進むビューの指示がありません。なので、デフォルトの `views/users/new.html.erb` へ処理が進みます。

## HTMLを作成し、ブラウザに表示

見た目はBootstrapベースなので、こんな感じ。

この一個一個のフォームに、`users`コントローラの`new`アクションで作った空のインスタンスに、実際のデータをユーザーに入れてもらって、のちにDBに格納していきます。

<img width="470" alt="スクリーンショット 2018-06-25 19.22.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/67bc2814-7a28-2f45-3d4f-90502022eccd.png">

## ユーザーがフォームを入力し、ユーザー登録ボタンを押した

全部入力して、登録するボタンをおしたら、form内の情報をまとめてサーバへ送信（`Post`リクエストを送信）します。

デベロッパーツールを確認して見ましょう。その中のネットワークを見てみましょう。HTTPのヘッダーの中の情報を見ると（右側）、HTTPメソッドがPOSTであることがわかるかと思います。

![スクリーンショット 2018-06-25 19.52.10.png](https://qiita-image-store.s3.amazonaws.com/0/14191/f2745fc8-ddf9-5413-db00-72cd5e9eba9f.png)

パラメータをクリックすると、フォームから送られて来たデータを確認することができます。

![スクリーンショット 2018-06-25 19.55.01.png](https://qiita-image-store.s3.amazonaws.com/0/14191/f59e0409-0e4c-ea2a-33c4-6d5dac54b868.png)

次は、飛んだこのリクエストがどのように処理されるかを見ていきます。

## ルーティングからコントローラ（`users`）のアクション（`create`）を判別

URLが`~/sigup`だったら、どこのコントローラに行けばいいかルーティング確認したら、`users`コントローラの`new`アクションと判別

`users`からの`Post`メソッドなので、デフォルトでは`users`コントローラの`create`アクションへ処理が渡ると思います。

## コントローラ（`users`）のアクション内の処理

```ruby:app/controllers/users_controller.rb
  def create
    # ストロングパラメータから精査されたデータだけをインスタンスに格納
    @user = User.new(user_params)
    
    # インスタンスの保存に成功した場合の処理
    if @user.save
      flash[:success] = "ユーザを登録しました"
      redirect_to @user

    # インスタンスの保存に失敗した場合の処理
    else
      flash[:danger] = "ユーザの登録に失敗しました"
      render :new
    end
  end
  
  private
  
  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end
```

コード下部にある `private` は、それ以降に定義されたメソッドがアクションではなく、このクラス内でのみ使用するメソッドであると明示しています。

なので、`def user_params` は、アクションではなく単なるメソッドとなります。また、このメソッドは`Strong Paramter`です。これは必要なパラメータを把握して、送信されきたデータをフィルタリングすることができます。

今回は、

- `params.require(:user)` で `User` モデルのフォームから得られるデータに関するものだと明示
- `permit`以降がフィルタリングさせずに通すカラムを指定しています。

## DB保存

```sql
mysql> select * from users;
+----+----------+--------------------+--------------------------------------------------------------+---------------------+---------------------+
| id | name     | email              | password_digest                                              | created_at          | updated_at          |
+----+----------+--------------------+--------------------------------------------------------------+---------------------+---------------------+
|  7 | pass7777 | pass7777@gmail.com | $2a$10$Hofz4hjxvF4sors86Q1kZugn/FGdAB/7SE.4/ZTuyfi4aJrItV.Am | 2018-06-25 08:26:05 | 2018-06-25 08:26:05 |
+----+----------+--------------------+--------------------------------------------------------------+---------------------+---------------------+
7 rows in set (0.00 sec)
```

格納されたことを確認しました（idの1から6を省略しています）。

---

以上です！

# この記事を読んだ方に

この記事を読んで、誤っている箇所をみつけたり、追記した方がいい内容などありましたら、編集リクエストやコメント欄で指摘していただけると助かります。

# 参考
- http://igarashikuniaki.net/rails_textbook/new-create.html