まさ@ブログ書き込み中

自由に生きるための英語、プログラミング、考えごとについて色々書いています。

【Rails】fields_forについてドキュメントから和訳します【form_withでも使えます】

f:id:masaincebu:20180901100730j:plain

今回は、会社の同期が使い方を迷っていたfields_forについてまとめていきたいと思います。

 

fields_forとは

超簡単に説明しておくと、fields_forとはRailsのViewで使えるヘルパーメソッドで、フォームで使うオブジェクトの種類が複数になった時に役に立ちます。

 

ある1つのオブジェクトに関連するフォームだけを作りたいのであればform_forやform_withを使って解決できますが、複数のオブジェクトになった時にはfields_forが活躍するわけです。

 

fields_forはform_for内でのみ使われる?

fields_for - リファレンス - - Railsドキュメントでは、以下のように説明されています。

モデルを固定してフォームを生成。form_for内で異なるモデルを編集できるようになる。

 

この説明だと、Rails5.1からリリースされたform_withでは使えないのか?と一瞬思ってしまいます。

 

ただ、上のドキュメントの中では適用バージョンが最新で4.2.1と書かれていたのでもう少し最新の情報を調べてみることにしました。

 

「form_forだけ」とはどこにも書かれてない

Rails APIによると以下の通りです。

Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes #fields_for suitable for specifying additional model objects in the same form.

 

form_forのように特定のモデルのオブジェクトのスコープを作るが、フォームタグ自身は作らない。そんな時にはfields_for最適だよって書いてあります。

 

つまり、結論から言うとform_withでfields_forは使えます。

 

Railsドキュメントの説明例がform_forについてのみ言及していたのはまだform_withが出る前に説明が書かれたからなのだと思います。

 

fields_forがどうなっているかについて詳しくみる

それでは、fields_forの基本的な仕組みについて説明して、簡単な使い方を見ていきたいと思います。

 

ざっくりと理解する

fields_forはform_for(やおそらくform_with)と同じように、ブロックの中で特定のオブジェクトに関連したFormBuilderオブジェクトを生成します。

 

ブロックの中では、そのモデルのオブジェクトに関連したフィールドを生成するメソッドがビルダーから呼べるようになります。

 

難しいことを言っている気がしますが、要するにform_forやform_withで見慣れたこういったコードを書いてフィールドを生成できるということです。

<%= fields_for @person.permission do |permission_fields| %>
 Admin?: <%= permission_fields.check_box :admin %>
<% end %>

 

これでpermissionに関連するadminフィールドを生成できます。具体的には、name属性がpermission[admin]となったチェックボックスができます。

 

ちゃんと理解する 

ここから細かい話をしていきます。fields_forがモデルのオブジェクトを反映する方法は二通りあります。

 

  1. 名前(name属性)のつけられ方(コントローラー側でparamsで受け取った時にどう見えるか)

  2. フォームやフィールドが最初に表示された時にどんなデフォルト値を取るか

 

2つの機能をそれぞれ別に利用する 

この2つの機能をそれぞれ別に利用するのであれば、オブジェクト名とオブジェクト自身をバラバラに渡せばOKです。

<%= fields_for :permission, @person.permission do |permission_fields| %>
 Admin? : <%= permission_fields.check_box :admin %>
<% end %>

 

これで、このチェックボックスのname属性はpermission[admin]となり、params[:permission][:admin]でコントローラー側で値を受け取れます。

 

そして@person.permissionがadmin属性を持っていて、すでに存在しているレコードであれば、このチェックボックスの初期値は@person.permission.adminの値になります。

 

モデル「名」のみを渡す

fields_forにモデル名のみを渡すこともできます。

<%= fields_for :permission do |permission_fields| %>
 Admin?: <%= permission_fields.check_box :admin %>
<% end %> 

 

もしこの:permissionが変数の名前と一緒であれば(@permissionが存在するのであれば)このチェックボックスの初期値は@permission.adminの値と同じになります。

 

オブジェクトのみを渡す

オブジェクトのみを渡すこともできます(fields_forは最初の引数がシンボルや文字列でなければ、名前に関する指定は省略されたとみなします)。

<%= fields_for @person.permission do |permission_fields| %>
 Admin?: <%= permission_fields.check_box :admin %>
<% end %> 

 

この場合、fields_forは必要なフィールド名をオブジェクトのクラス名から取得します。このケースの場合、@person.permissionのクラスがPermissionだった場合、このチェックボックス(inputタグ)のname属性はpermission[admin]となります。

 

fields_forについての説明はここまでです。皆さんいいfields_forライフをお過ごしください。