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なリソースを使っている場合)
実際のコードを見てみましょう。
def new
@micropost = Micropost.new
end
<%= 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 チュートリアルで出てきた、ストロングパラメーターを覚えているでしょうか?
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
require (:micropost) がないですね。
これではネスト化されず、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.の直後の記述は何でしょうか?一部を紹介します。
<input> <textarea> 要素を生成するメソッド
--- XXXX_field / text_area メソッド ---
xxxx_field(obj, prop [,opts])
text_area(obj, prop [,opts])
obj: オブジェクト名(省略可) prop: プロパティ名
opts: 要素の属性
この他にも、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