利用ケースは少ないと思いますが、ActiveRecord::Base
を継承しないフォームと date_select
や date_time_select
を使ったビューの組み合わせだと、フォーム初期化時に UnknownAttributeError
が発生していて、原因と対処方法がよく分からず若干ハマってしまったので誰かのためにメモで書いておきます。
前提
- Ruby on rails 5.2.3
UnknownAttributeErrorが発生する原因
以下のようにdate_select
や date_time_select
を使ってビューを実装します。
- # app/views/plans/new.html.haml = form_for(@plan) do |f| .field = f.date_select :start_date = f.date_select :end_date
【見た目】
するとコントローラ側の変数params
には、start_date(1i), start_date(2i), start_date(3i)
のように入ってきます。そして、コントローラ側のStrongParameter
の機能 (以下のplan_params
の箇所)までは、これらの値はstart_date
と解釈してくれてうまく動きます。
# app/controllers/plan_controller.rb class PlanController < ApplicationController def new @plan_form = PlanForm.new(plan_params) end private def plan_params params.require(:plan).permit(:start_date, :end_date) end end
その後に、以下のようなフォームを作って同じコントローラでPlanForm.new(plan_params)
のようにPlanForm
クラスを初期化しようとすると
# app/forms/application_form.rb class ApplicationForm include ActiveModel::Model include ActiveModel::Attributes end # app/forms/plan_form.rb class PlanForm < ApplicationForm attribute :start_date attribute :end_date end
フォームPlanForm
に start_date(1i)、start_date(2i)、start_date(3i)
という属性がないため(start_date
ならある)、UnknownAttributeError
が発生します。
ちなみにフォームではなく、データベースに値を保存するActiveRecord::Baseを継承したモデルでは、assign_multiparameter_attributesというメソッドの中でうまく処理してくれます。
対処方法
こういう時はフォームに include ActiveRecord::AttributeAssignment
を追加すると start_date(1i)、start_date(2i)、start_date(3i)
を start_date
と解釈してくれるようになって、フォーム(PlanForm
)を初期化できるようになります。
# app/forms/application_form.rb class ApplicationForm include ActiveModel::Model include ActiveModel::Attributes include ActiveRecord::AttributeAssignment # ←これを追加 end # app/forms/plan_form.rb class PlanForm < ApplicationForm attribute :start_date attribute :end_date end