Railsでcollection_check_boxesを使い中間テーブルに複数レコードを登録する

# はじめに
実装したい内容としては、タイトルの通りです。
考えてみれば辺り前だなということだったのですが、アプリケーションを作成中に少しハマったので、忘れない用に書き残します。
Railsは便利ですが、故に最初は詳細な部分が分かりづらいことがあると

### 環境
- Ruby 2.7.2
- Rails 6.0.3.4

### 要件

要件を再度整理します。
1. 親子関係にある複数のモデルを一度にフォームから登録したい。
2. 子のモデルの方は、チェックボックスで複数選択をさせて登録させたい。

###  モデル関係
`※ 記事の説明に必要な最低限の情報のみ記載`

#### shopモデル

|カラム  |型  |備考  |
|---|---|---|
|id  |integer  |pk  |
|shop_name  | string |  |


#### tasteモデル
ショップで扱う系統(アメカジ、ストリート、カジュアル etc..)を格納するマスタデータ

|カラム  |型  |備考  |
|---|---|---|
|id  |integer  |pk  |
|style  | string |  |

####  shop_tasteモデル
`shop`モデルと`taste`モデルの情報を格納する中間モデル

|カラム  |型  |備考  |
|---|---|---|
|id  |integer  |pk  |
|shop_id  | integer | fk (参照先：shopモデルの`id` )|
|taste_id  | integer | fk (参照先：tasteモデルの`id` )|


### 関連付け

`shop.rb`内で、同一のフォームで登録したいモデルに対して、`accepts_nested_attributes_for`を指定する。


- shopモデル


```ruby
class Shop < ApplicationRecord
  has_many :shop_tastes, dependent: :destroy
  has_many :tastes, through: :shop_tastes

  accepts_nested_attributes_for :shop_tastes, allow_destroy: true
end
```

- tasteモデル

```ruby
class Taste < ApplicationRecord
  has_many :shop_tastes, dependent: :destroy
  has_many :shops, through: :shop_tastes
end

```

- shop_tasteモデル

```ruby
class ShopStyle < ApplicationRecord
  belongs_to :shop
  belongs_to :taste
end
```
### controllerとview

以下が今回ハマった部分のコードになります。

```ruby:shops_controller.rb
  def shop_params
    params.require(:shop).permit( :shop_name, taste_attributes[taste_ids:[]])
  end
```

```erb:new.html.erb

<%= form_with model: @shop, local: true do |f| %>

    <% f.fields_for :shop_tastes do |fc| %>
      <%= fc.collection_check_boxes :taste_ids, Taste.all, :id, :style, checked: @shop.taste_ids ,include_hidden: false do |b| %>
        <%= b.check_box %>
        <%= b.text %>
      <% end %>
    <% end %>

    <%= f.submit %>
<% end %>
```
#### ハマった理由とポイント

上記のコードで、フォームに値を入力して、送信を行うと `unkown attributes taste_ids for ...`と、そんな属性はない、という旨のエラーメッセージが出力されてしまいました。
自分では、小モデルの複数登録の場合`collection_check_boxes`と `fields_for`を基本的にセットで使用すると考えていました。

しかし`collection_check_boxes`自体パラメータを送信する時に配列の形式で送信を行うため、`XXX_ids`のようなパラメータ名を指定する必要があります。

[API doc](https://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for)で`fields_for`を見ると、以下の用に記述がありました。

>Like form_for, it yields a FormBuilder object associated with a particular model object to a block, and within the block allows methods to be called on the builder to generate fields associated with the model object. 


ざっくり日本語訳すると、以下のような内容です。

`form_for と同様に、特定のモデルオブジェクトに関連付けられた FormBuilder オブジェクトをブロックに生成し、ブロック内でビルダーにメソッドを呼び出してモデルオブジェクトに関連付けられたフィールドを生成することができます。`

確かに、`shop_taste`モデルには`taste_ids`というフィールドは存在しないため、エラーになるのは当たり前ですね。。。
自分の中で、親子関係にある複数モデルを一気に登録する場合、`fields_for`は必須だと勘違いしていたのですがそうではありませんでした。

```ruby
class ShopsController < ApplicationController

  def new
    @shop = Shop.new
    @shop.shop_tastes.build
  end

  def create
    @shop = Shop.new(shop_params)
    @shop.save
  end

  private
  def shop_params
    params.require(:shop).permit( :shop_name, taste_ids:[])
  end
end
``` 


以下正常に動いたコード

```erb

<%= form_with model: @shop, local: true do |f| %>
    <%= f.label :shop_name %>
    <%= f.text_field :shop_name, class: "form-control" %>

    <%= f.collection_check_boxes :taste_ids, Taste.all, :id, :style, checked: @shop.style_ids ,include_hidden: false do |b| %>
      <%= b.check_box %>
      <%= b.text %>
    <% end %>

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

正直`fields_for`については、詳細な部分まで調べきれておらず細かい仕様が把握できていないので、今後時間のある時に調べます。