[Ruby on Rails] date_selectで分割されたパラメーターをFormObjectに渡す。

一つのフォームの送信で複数のモデルを更新したいときなど、FormObjectを利用するかと思います。
（FormObjectについて知りたい方はこちら：[【Rails】FormObjectを使ってほしい] (https://qiita.com/9ro/items/10e3676741e09ffb98bb )）

そのFormObjectに`date_select`で分割されたパラメーターをそのまま渡すことできなく困っていた矢先、FormObjectに`include ActiveRecord::AttributeAssignment`を宣言したら、まとめて渡すことができたので以下にて紹介したいと思います。



### 説明

状況としては、新規登録画面で誕生日を登録する場面です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/50f8ea07-c970-bc69-a087-216c80965971.png" width=500px border="1">

画像の`CreateUser`ボタンを押すと、コントローラーのcreateアクションが走ります。user_paramsメソッドでStrongParameterの仕組みを使って、分割されたパラメーター`<ActionController::Parameters {"birthday(1i)"=>"2020", "birthday(2i)"=>"7", "birthday(3i)"=>"13"} permitted: true>`を取得。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = Form.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users
  # POST /users.json
  def create
    @user = Form.new(user_params)
    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def user_params
      params.require(:user).permit(:birthday)
    end
end
```

```ruby:app/forms/form.rb
class Form
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :birthday, :date

  def to_model
    User.new(birthday: birthday)
  end

  def save
    return false if invalid?
    to_model.save
  end
end
```

`@user = Form.new(user_params)`で記載されているように、
分割されたパラメーターをFormObjectの初期値で渡そうと思うと、分割されているが故にエラーが起きてしまう。`<ActionController::Parameters {"birthday(1i)"=>"2020", "birthday(2i)"=>"7", "birthday(3i)"=>"12"} permitted: true>`をまとめてbirthdayパラメーターとして渡したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/2a0af73f-440d-491b-19aa-c6e1acac5782.png)


そこで、`include ActiveRecord::AttributeAssignment`を宣言すると、分割されたパラメーターをまとめてattributeに渡してくれる。一件落着。

```ruby:app/forms/form.rb
class Form
  include ActiveModel::Model
  include ActiveModel::Attributes
  # 追加
  include ActiveRecord::AttributeAssignment

  attribute :birthday, :date

  def to_model
    User.new(birthday: birthday)
  end

  def save
    return false if invalid?
    to_model.save
  end
end
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185492/e33f2102-cddf-57d2-276b-44511f7f8471.png" width=500px border="1">