Rails fields_for のドキュメントを和訳しました。

fields_forの使い方にかんして調べることが多かったので、[ドキュメント](http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for) を和訳しておく。

# fields_for

```
fields_for(record_name, record_object = nil, options = {}, &block) public
```

特定のモデルオブジェクトのためにスコープを作るが、form_tagをそれ自体では生成しない。
同じフォームの中で追加でモデルオブジェクトを特定する時に便利。

form_forと用途も目的も似ているが、特徴が少し異なる。
form_forと同様に得知恵のモデルオブジェクトに関するFormBuilderオブジェクトをブロック内に生成し、そのブロック内部ではそのbuilderに対してメソッドを呼び出せる。メソッドは、そのモデルオブジェクトのフィールドを生成したりする際に使われる。フィールドはモデルオブジェクトで二つの変数をいじることができて、一つは`name`、すなわちそのフィールドがどう呼ばれるか(すなわちcontroller内のparamsハッシュでどのkeyに対応するか)、二つ目は`フィールドの初期値`である。両方の変数が独立に指定されるように、それぞれ引数として別々に渡される。
下の例の `<%= fields_for :permission, @person.permission do |permission_fields| %>`の部分である。

```
<%= form_for @person do |person_form| %>
  First name: <%= person_form.text_field :first_name %>
  Last name : <%= person_form.text_field :last_name %>

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

  <%= person_form.submit %>
<% end %>
```

上の例では、check_boxフィールドは`permission[admin]`という`name`attributeを持つHTMLのinputタグで表現され、controllerでは`params[:permission][:admin]`で表現される。もし`@person.permission`がattribute`admin`を持つ既存のレコードであれば、上の例においてcheck_boxは`@person.permission.admin`を初期値としてもつ。

しばしば省略されて、モデルオブジェクトの名前だけを引数に渡す。

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

この場合、もし`:permission`がインスタンス変数`@permission`の名前と(たまたまでも)同じであると、インプットフィールドの初期値は、`@permission.admin`の値にセットされる。

もう一つの省略方法としては、モデルオブジェクトを単に渡すこともできる。(第一引数がstringでもsymbolでも内場合は、`fields_for`は`name`が省略されたものとみなす。)

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

この場合、fieldの`name`をモデルオブジェクトから持ってくる。例えば、今回のケースで、`@person.permission`がPermissionクラスのインスタンスだった場合、フィールドは`permission[admin]`という名前を持つ。

# Nested Attributes の例

現在のスコープに属しているオブジェクトがnested attribute writerをあるattributeに関して持っている場合、`fields_for`はそのattributeのための新しいスコープを生み出すために有効である。これによって、親オブジェクトとその子オブジェクトの更新を一度に行うことのできるフォームをつくることができる。

nested attribute writerはアソシエーションに対するセッターメソッドである。writerを定義する最も一般的な方法は、モデル定義において`accepts_nested_attributes_for`をつかうか、適切な名前でメソッドを定義することで可能である(`*1`)。例えば、`:address`というアソシエーションのattribute writerは`address_attributes=`で呼びだすことができる。

## 1対1の時

Personクラスが一つのAddressクラスを持つ時を考える。

`*1`の後者の方法、すなわち自分でリーダメソッド、ライターメソッドを定義する場合は以下のようにモデル定義できる。

```
class Person
  def address
    @address
  end

  def address_attributes=(attributes)
    # Process the attributes hash
  end
end
```

このモデルは**nested**なfields_forを使って以下のように利用できる。

```
<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    Street  : <%= address_fields.text_field :street %>
    Zip code: <%= address_fields.text_field :zip_code %>
  <% end %>
  ...
<% end %>
```

自分でリーダー、ライターメソッドを定義せずにアソシエーションをつくるメソッドを利用することで表すこともできる。

```
class Person < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
end
```

この時、もしフォームを使って紐づく子レコードを削除したい際には、まずはモデル定義において`:allow_destroy`オプションを設定する。

```
class Person < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address, allow_destroy: true
end
```

そして、フォームを使って削除する場合は、`_destroy`パラメータを持つフォーム要素を使用することができる。この要素の値がtrueの時、紐づく子レコードは削除される。

```
<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    ...
    Delete: <%= address_fields.check_box :_destroy %>
  <% end %>
  ...
<% end %>
```

## 1対多

同様に1対多のケースを考えると、以下の二つの方法でモデル定義をすることができる。

```
class Person
  def projects
    [@project1, @project2]
  end

  def projects_attributes=(attributes)
    # Process the attributes hash
  end
end
```

```
class Person < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects
end
```

`fields_for`を使って以下のように書くことができる。`fields_for`に与えられたブロックは、子レコードのインスタンスの数だけ繰り返される。(`name`に対応する名前のアソシエーションが存在する場合、その紐付いたレコードのインスタンスにアクセスする。)

```
<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    <% if project_fields.object.active? %>
      Name: <%= project_fields.text_field :name %>
    <% end %>
  <% end %>
  ...
<% end %>
```

ここで、使用されるインスタンスを明示することも可能である。(`fields_for`に複数レコードを繰り返し表示してもらうのではなく、それぞれの単体レコードに対して`fields_for`でスコープを定義してブロックを生成する。)

```
<%= form_for @person do |person_form| %>
  ...
  <% @person.projects.each do |project| %>
    <% if project.active? %>
      <%= person_form.fields_for :projects, project do |project_fields| %>
        Name: <%= project_fields.text_field :name %>
      <% end %>
    <% end %>
  <% end %>
  ...
<% end %>
```

`fields_for`は前述したように、`name`と`デフォ値`を取ることができるので、紐づくインスタンスを直接変数で(デフォ値として)指定することも可能である。

```
<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
    Name: <%= project_fields.text_field :name %>
  <% end %>
  ...
<% end %>
```

destroyオプションに関しては1対1の時と同様以下のように使用できる。

model定義して、

```
class Person < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects, allow_destroy: true
end
```

フォームで`_destroy`パラメータをセットできるようにする。

```
<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Delete: <%= project_fields.check_box :_destroy %>
  <% end %>
  ...
<% end %>
```

複数の紐づくオブジェクトのインスタンスたちのindexを知るには、`index`メソッドが使用できる。FormBuilderオブジェクトのインスタンスメソッドである。

```
<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Project #<%= project_fields.index %>
    ...
  <% end %>
  ...
<% end %>
```

最後にもうひとつ`fields_for`のオプションを紹介する。`fields_for`は自動で紐づくレコードのIDを持つ`hidden field`を生成するが、それが要らない時は、`include_id: false`とすることで生成されないようにすることができる。