【初心者向け】rails 投稿機能解説！form_withやストロングパラメータを図で理解！

# はじめに
form_withをつかった投稿機能は、Rails 初学者がつまづきやすいポイントかと思います！
本記事では **form_withを使った入力フォームの作成** 、**ストロングパラメータ**、**データの保存**までを解説していきます。

図を織り交ぜていますので、イメージをつかみつつ理解を深めていきましょう:sunny:

### 動作環境
- Ruby 2.6.7
- Rails 5.2.7 (動作としてはrails6系でも同様です)

### 実装する機能・仕様
フォームでタイトルと内容を入力し、データベースに保存する。
Blogモデルにtitle、bodyカラムを準備。

# form_withを用いて入力データを送信する
new.html.erbにてフォームを以下のように作成していきます。

```ruby:blogs_controller.rb
def new
  @blog = Blog.new
end
```

```erb:new.html.erb
<h1>Blogs#new</h1>

<%= form_with model: @blog, local: true do |f| %>
　<!--タイトル入力フォーム生成-->
  <%= f.label :title %><br>
  <%= f.text_field :title %><br>
  
　<!--内容入力フォーム生成-->
  <%= f.label :body %><br>
  <%= f.text_area :body %><br>
  
　<!--投稿ボタン生成-->
  <%= f.submit %>
<% end %>
```

実行画面
<img width=200 alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918398/9689d521-3d57-0240-721b-b227b24f1c19.png">

### 入力フォームのイメージ
`Blog.new`の記述がありますが、これはBlogの新しい箱を作るイメージになります。このBlogの箱の中には空のtitle、bodyの箱を持っています。この空の箱をインスタンス変数`@blog`に格納して、フォームヘルパー(form_with)に渡していきます。

<details><summary>フォームヘルパーとは</summary>
フォームヘルパーは入力フォームを簡単に作成できるように、あらかじめメソッド(処理)を用意してくれているものです。
f.text_fieldやf.text_area、f.submitなどがその例です。フォームをヘルパーなしで書こうとするとなかなか面倒になるので、とてもありがたい存在です</details>

文字や値を入力したのちに`Create Blog`のボタンを押すと、フォームヘルパーは入力値を該当する箱に入れていきます。


![Blog.new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918398/3e7fd977-b588-a6b1-0b3d-e24921b34f1d.png)

この作業を経てパラメータの一つが生成され、次にcreateアクションへ送信していきます。イメージとしては荷物パッキングをして次のアクションまで配送するイメージです。


![submit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918398/9720a91e-94b6-02e0-2328-2953b81092c2.png)

### パラメータとは
ここで、**パラメータ**について少し触れます。
パラメータとは基本的には**アクション間で受け渡しされるデータ**のことを指します。
どのような情報が渡されているのかはターミナルで確認することができます。titleに"hoge"、bodyに"fuga"を入力してターミナルを確認すると以下のようになります。(一部抜粋)

```terminal:terminal
Started POST "/blogs" for ......
:
Processing by BlogsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"..", "blog"=>{"title"=>"hoge", "body"=>"fuga"}, "commit"=>"Create Blog"}
:
:
```

今回はこの中でも 

```terminal
Parameters: {"utf8"=>"✓", "authenticity_token"=>"..", "blog"=>{"title"=>"hoge", "body"=>"fuga"}, "commit"=>"Create Blog"}
```

がパラメータになります。 『"〇〇"=>"××"』を一つのまとまりと考えます。上記を箱のイメージであらわすと
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918398/b8dd23bf-387e-9a78-6817-cd46de4c5061.png" width="500">

となります。箱の中にそれぞれ矢印の右辺の情報が入っているイメージです。
このように、先ほど入力した情報がBlogの箱の中のtitleとbodyに格納されて、送信されていることが確認できます。


# フォームの送信後createアクションでの挙動
ここからはcreateアクション内での処理を説明していきます。

```ruby:blogs_controller.rb
def create
  # ストロングパラメータで入力された値を取得
  @blog = Blog.new(blog_params)
  # 保存
  @blog.save
  # 保存後詳細ページに遷移
  redirect_to blog_path(@blog)
end

private
# ストロングパラメータ
def blog_params
  params.require(:blog).permit(:title, :body)
end
```

送られてきた箱をそのまま保存したい！！となりますが、railsではアクションごとに新しい箱を作成して移し替える作業を行う必要があります

`Blog.new(blog_params)`の`Blog.new()`関しては前章の考え方と同様に、空の箱を作るイメージです。
かっこの中身は空の箱の中に、値をはじめから入れたいときに入力します。

### ストロングパラメータ
今回はフォームで入力した値を空の箱に入れていきたいので、ここでストロングパラメータを定義した`blog_params`を呼び出しています。
`params.require(:blog).permit(:title, :body)`は3つに分割して考えていきます。

- **params**
パラメータ全体を呼び出します。

- **.require(:blog)**
パラメータの中で、どの要素(大きな箱)を選択するかを宣言します。今回の場合、4つの箱(utf8, authenticity_token, blog, commit)の中からblogを選択するという意味になります。

- **.permit(:title, :body)**
選択した要素(大きな箱)内に含まれるパラメータの中でどの情報の保存を許可するのかを選択します。今回の場合、blogの箱の中にあるtitleとbodyについて保存するという意味になります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918398/ca66a6ee-95fe-4add-6900-062826f64410.png" width="500">
<details><summary>ストロングパラメータはなぜ必要？</summary>
ストロングパラメータを設定することで、**不要な情報が保存されることを防ぎます**。
仮に悪意のあるユーザーがtitle、body以外の箱を自分で作って送信してきたとします。ストロングパラメータを設定していなかった場合、データベースにはそのカラムは存在していないので、その情報を保存するときにエラーを吐いてしまいます。ストロングパラメータで、必要な情報のみを選別しているといことになります。システムの根幹にもなるので、他の場所から呼び出して書き換えができないようにprivate下に書くことが一般的です。
</details>

これらをまとめると、`Blog.new(blog_params)` は『**送られてきたパラメータの中から、blogの中のtitleとbodyを取り出して、新しい箱に入れる**』ということになります。したがって、createアクションのイメージを描くと以下のようになります。
![save.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918398/304bff4f-1a19-0e40-be44-f9013afdad98.png)

これでフォームの入力～データの保存が完了です！


# おわりに
今回はフォームの入力から保存までの流れを図メインでまとめてみました！
イメージはつかめましたでしょうか？
少しでも参考になればと思います:four_leaf_clover: