【Rails】1つのform_forで複数モデルへデータ登録をする方法

#概要
アソシエーションで紐付いている複数のモデルへのデータ登録に苦労したのでまとめておきます。
一つのform_forで複数のモデルへのデータ登録を可能にする方法です。
例)ユーザーモデルとアドレスモデルがある時に、1つのform_forでユーザーモデルとアドレスモデルに同時にデータを渡したい。

#環境
Rails5.1
mysql

#前提
ユーザー情報の登録を実施。
Usersテーブル
・id
・name
Addressesテーブル
・都道府県
・市区町村
・番地

#ポイント
accepts_nested_attributes_for
form_for
fields_for
build


#Model
ユーザーは1対1でアドレス情報を持ちます。
ポイントは**accepts_nested_attributes_for**を記載している点です。
accepts_nested_attributes_forについて詳しくは以下を読んでみてください。
簡単に説明すると、親モデルを通じてネストしたモデルの関連レコードの登録・更新を可能にするメソッドです。
[Nested Models](https://github.com/plataformatec/simple_form/wiki/Nested-Models)

```user.rb
class User < ApplicationRecord
  has_one :address
  accepts_nested_attributes_for :address
end
```
```address.rb
class Address < ApplicationRecord
  belongs_to :user
end
```


これでモデル部分は完了です。次はコントローラ部分に移りましょう！

#Controller
ここでのポイントは2つです。
①buildメソッドの活用
②strong parameterにattributesを用いて、address_attributesを追記
それぞれ説明していきます。

①userはhas_oneでaddressを持っています。
そのため今回はUserのオブジェクトを作成すると同時にAddressのオブジェクトを作成します。
has_oneのリファレンスを読んでみましょう。
[has_oneリファレンス](http://railsdoc.com/references/has_one)
ここに記載されているbuild_associationに注目してください。
>新しいオブジェクトを作成
>引数にはオブジェクトを生成するのに必要なパラメータを指定
>この時点では保存されない

と記載されています。
そのため今回newアクションでUserのオブジェクトを作成すると同時にAddressのオブジェクトを作成するために
@user.build_addressを記載します。

②has_oneのリファレンスに
>引数にはオブジェクトを生成するのに必要なパラメータを指定

とあるため、strong parameterにaddress_attributesを追記してあります。

```users_controller.rb
class UsersController < ApplicationController
  def index

  end

  def new
    @user = User.new
    @user.build_address
  end

  def create
    @user = User.new(user_params)
    @user.save
    redirect_to users_path(@user)
  end

  private

  def user_params
    params.require(:user).permit(:name, address_attributes:[:id, :postal_code, :prefecture, :municipality, :address_number])
  end

end
```

これでコントローラは完了です。最後にViewに移りましょう！

#View
ここでのポイントは**fields_for**メソッドの部分になります。
fields_forはform_for内で異なるモデルを編集できるようにするメソッドです。
`<%= fields_for(モデル) do |i| %>
<% end %>`
の形で使用する事ができます。

```new.html.erb
<%= form_for @user, url: users_path do |f| %>
  <div class="form-user">
    <%= f.label :name, "名前" %>
    <%= f.text_field :name %>
  </div>
  <%= f.fields_for :address do |i| %>
    <div class="form-group">
      <%= i.label :postal_code, "郵便番号" %>
      <%= i.text_field :postal_code %>
      <br>
      <%= i.label :prefecture, "都道府県" %>
      <%= i.text_field :prefecture %>
      <br>
      <%= i.label :municipality, "市区町村" %>
      <%= i.text_field :municipality %>
      <br>
      <%= i.label :address_number, "番地" %>
      <%= i.text_field :address_number %>
    </div>
  <% end %>
  <%= f.submit "送信" %>
<% end %>
```
以上でViewは完了です。

以下の内容で登録してみました。
<img width="609" alt="スクリーンショット 0031-01-15 1.45.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/301569/5ec8aa41-1e64-235f-2090-3aa0d3867575.png">

パラメーターを確認してみましょう。

```
Parameters: {"utf8"=>"✓", "authenticity_token"=>"osNERk3el8wLyIWkNxSaCamany+VKi12RQo+FUH6n1Ec/IvhwcnBufZFtOEQPI4nQkxYTnjGHcH6qukheKTVpg==", 
"user"=>{"name"=>"テスト", "address_attributes"=>{"postal_code"=>"1234567", "prefecture"=>"東京都", "municipality"=>"多摩市一ノ宮", "address_number"=>"2-4"}}, "commit"=>"送信"}

  User Create (11.4ms)  INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES ('テスト', '2019-01-14 16:45:46', '2019-01-14 16:45:46')

  Address Create (0.4ms)  INSERT INTO `addresses` (`postal_code`, `prefecture`, `municipality`, `address_number`, `created_at`, `updated_at`, `user_id`) VALUES ('1234567', 0, '多摩市一ノ宮', '2-4', '2019-01-14 16:45:46', '2019-01-14 16:45:46', 3)
```
きちんとuserのハッシュの中addressの情報も含まれていますね。

以上です！



#参考記事
[Railsで1つのフォームで複数のモデルを登録・更新させる]
(https://qiita.com/tmzkysk/items/6349d8d860c5982771ff)
[Active Record Nested Attributes
](https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html)[has_oneリファレンス](http://railsdoc.com/references/has_one)
[fields_forリファレンス](http://railsdoc.com/references/fields_for)