【Rails初心者向け】form_for メソッドを5分で理解しよう！


Rails チュートリアルを勉強していくと、
様々なわからないことに遭遇します。
特にこの form for メソッド は、かなり難しかったので、まとめてみました。 



まず、なぜ難しいか？？　なんですが


#1. Progate で習ってない！ 

Progate では、form_tag メソッドでしたね。これは、全く素直なメソッドで、簡単に理解できましたが、このform-for は・・・　
難しい！！ 　

form_tag じゃダメなの？？
なんで？？

#2. form for () 

　()の中に何書けばいいの？？？　
　f. の後もよくわからない！　 


#3. params[:~][:~] がわからない
 送信して得られるパラメータが、よくわからない！　
 何で2つシンボルがあるの？



と、このように、わからないことだらけだったので
疑問を潰していこうと思います。　





##❶　なんでわざわざ、form_for　使うか？　
 
2つの違いは、これです！　
>
・特定のモデルに特化したフォームを作りたい　→　form_for
・別になんでも良い　→　form_tag 
 

rails チュートリアルだと、micropost モデルとか、userモデルなどありますね。　
このモデルに特化したかったから、form_for だったんですね。　
　
では、特化すると、どんないいことが待っているでしょうか？



### (Ⅰ) モデルのインスタンスを渡すだけで、自動的にRailsが処理してくれる. (RESTfulなリソースを使っている場合)




実際のコードを見てみましょう。　
 
```app/controllers/microposts_controller.rb
def new 
   @micropost = Micropost.new
end

```

```app/views/microposts/new.html.erb
<%= form_for(@micropost) do |f| %>
  <%= f.label :名前 %>
  <%= f.text_field :name %>
<% end %>
```


もし、この@micropost がすでに保存されていた場合は、update アクション、未保存の時は、create アクションを、Rails は自動的に選んでくれるんです。
 


```
#新規作成の時、これらは同じ内容
form_for(@micropost) 
form_for(@micropost,  url: microposts_path)　
　
#上書きする時、これらは同じ内容
form_for(@micropost) 
form_for(@micropost, url: micropost_path(@micropost), html: {method: "patch"})　

```


新規作成の時も、上書きする時も、どちらも同じ form_for(@micropost) であれば、コードを書く量は減りますね。尚、基本動作の create, update以外を指定したい時は、`url:, method:` の両方を書かなければいけません。

　


### (Ⅱ) ネスト化してくれる

ネスト化とは、「入れこ」のことです。コードを見てみましょう。
rails チュートリアル5章、SCSSのとこです。

```
.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}
```

これは、以下のように、ネスト化できます。

```
.center {
  text-align: center;
  h1 {
    margin-bottom: 10px;
  }
}
```

ネスト化のイメージは掴んだでしょうか？
ここでいきなりですが、rails チュートリアルで出てきた、ストロングパラメーターを覚えているでしょうか？　
　　

```app/controllers/microposts_controller.rb

 private
    def micropost_params
      params.require(:micropost).permit(:content, :picture)
    end
 end
```

これは、Strong Parameter という、安全な書き方です。(詳細は、Rails チュートリアル第7章 Strong Parameter 参照ください。)
　

こう書いてあることで
`params[:micropost][:content]、params[:micropost][:picture] `
　

このように、ネスト化された、パラメータを受け取ることができます。
一方、ネスト化されていない受け取り方は、下のようなコードになります。

```
def micropost_params
　 params.permit(:content, :picture)
end
```

<b>require (:micropost)<b> がないですね。

これではネスト化されず、strong なparameter ではなくなってしまいます。
そして、このパラメーターの受け取り方は、progate でよく出てきた

`params[:content],  params[:picture] `

になります。 

form_tag ヘルパーをProgate のように使用すると、ネスト化されていないパラメータを受け取る
ことになり、webアプリの安全性に問題が出てくることになります。　
 
form_for メソッドは、`params[:micropost][:content]` のように、ネストしたパラメーターを送ってくれるので、安全性が担保されるというわけですね。

　

##❷　form for ()　の()の中に何書けばいいの？？？　

構文を書きます。

```
form_for (var [,opts]) do |f|
  ...body...
end 

# var: モデルオブジェクト　opts: 動作オプション
```
 

- モデルオブジェクト 
User モデルでこのform_for を使うなら、@user 
Micropost モデルなら、@micropost になりますね。

- 動作オプション(url, html)
create, update の機能だけであれば、不要ですね。　
それ以外の機能の時には、記載が必要になります。

url: フォームの送信先 (名前付きルート)   ex: user_path(user) 
html: class, methodなどを明記します。 ex: html: {class:"~"}



##❸　f. の後に何書けばいいの？？？　

f とは、form の略です。
Rails チュートリアル第7章を参照しましょう。

>このf オブジェクトは、HTMLフォーム要素(テキストフィールド、パスワードフィールドなど)に対応するメソッドが呼ばれると、@micropostの属性を設定するために、特別に設計されたHTMLを返します


コードをご覧ください。

```
<%= form_for(@micropost) do |f| %>
  <%= f.text_area :content %>
  <%= f.submit "送信" %>
<% end %>
```

:content のcontent とは、micropost の属性ですね。

`rails g model Micropost content:text`

micropost モデルを作る時に設定しました

では、f.の直後の記述は何でしょうか？一部を紹介します。



<b> \<input> \<textarea> 要素を生成するメソッド<b>

--- XXXX_field / text_area メソッド ---　 
>xxxx_field(obj, prop [,opts])
text_area(obj, prop [,opts])
obj: オブジェクト名(省略可)　prop: プロパティ名 　
opts: <input> <textarea>要素の属性
 

 

この他にも、check_box, radio_button, select などたくさんあります。
気になる方は調べてくみてください。　
 

これで、form_for メソッドは完成しました。
最終的になコードは次のようになります。



```
<%= form_for(@micropost) do |f| %>
  <%= f.file_field :picture %>
  <%= f.text_area :content　%>
  <%= f.submit "送信" %>
<% end %>
```


以上で、終了となります。
間違ってる所など、お気付きのことがありましたら、コメントを頂けますと幸いです。
　


　 

参考文献:　
Ruby on Rails 5 アプリケーションプログラミング  　
Rails ガイド
Rails チュートリアル
https://qiita.com/shunsuke227ono/items/7accec12eef6d89b0aa9