今回はフォームでdate_selectを使用し、かつFormオブジェクトを用いた場合にUnknownAttributeエラーが発生してしまい、結構ハマったので備忘録として残しておきます。同じように困っている人の参考になればと思います。
前提
- Rails:6.0.3.2
- Ruby:2.6.5
- DB:MySQL
コードに関しては該当箇所のみ記載しておきます。
↓ ビュー(出版日と生年月日にdate_selectを使用しています)
<%= form_with(model: @book, url: books_path, local: true) do |form| %>
<% if book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% book.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :タイトル %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :出版日 %>
<%= form.date_select :publish_date %>
</div>
<br>
<h1>作者情報</h1>
<div class="field">
<%= form.label :名前 %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :生年月日 %>
<%= form.date_select :birth_date %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
date_selectは、年月日を簡単に実装できるヘルパーメソッドです。年月日はプルダウン形式で表示されます。
date_select(オブジェクト名, メソッド名 [, オプション or HTML属性 or イベント属性])
Railsドキュメント:https://railsdoc.com/page/date_select
↓ モデル(Formオブジェクトを採用しています)
class AutherBooks
include ActiveModel::Model
attr_accessor :name, :birth_date, :title, :publish_date
with_options presence: true do
validates :name
validates :birth_date
validates :title
validates :publish_date
end
def save
auther = Auther.create(name: name, birth_date: birth_date)
Book.create(title: title, publish_date: publish_date, auther_id: auther.id)
end
end
↓ コントローラー
class BooksController < ApplicationController
def new
@book = AutherBooks.new
end
def create
@book = AutherBooks.new(book_params)
if @book.valid?
@book.save
redirect_to root_path
else
render :new
end
end
private
def book_params
params.require(:auther_books).permit(:title, :publish_date, :name, :birth_date)
end
end
エラー内容
本情報と作者情報を新規登録しようとしたところ、以下のようなUnknownAttributeエラーが出力されてしまいました。

解決方法【結論】
結論、Formオブジェクトに以下の1行を追記しましょう。
include ActiveRecord::AttributeAssignment
こうすることで「publish_date(1i)」「publish_date(2i)」「publish_date(3i)」を1つのpublish_dateと認識してくれるようになります。
もう少し深堀り
本来であれば、「publish_date(1i)」「publish_date(2i)」「publish_date(3i)」の3つのパラメーターが送られたとしても、ストロングパラメーターに「publish_date」と記述するだけでRails側が自動的に解釈してくれます。
そしてデータベースには「publish_date = ‘2020-10-13 18:20’」という形で保存されます。
これはassign_multiparameter_attributesというメソッドの中でうまく処理してくれているためであり、加えてこれはActiveRecord::Baseを継承したモデルでしか機能しません。
そこで解決方法にも記載した通り、ActiveRecord::Baseを継承していないモデルの場合は「include ActiveRecord::AttributeAssignment」を追記することで、モデルが初期化できるよう設定しています。
参考
Railsのdatetime_selectの保存の仕組みを調べてみる:
http://success.tracpath.com/blog/2010/09/28/rails%E3%81%AEdatetime_select%E3%81%AE%E4%BF%9D%E5%AD%98%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%82%92%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%82%8B/
今回はフォームでdate_selectを使用し、かつFormオブジェクトを用いた場合にUnknownAttributeエラーが発生した時の対処方法について解説しました。date_selectやdatetime_selectは便利なヘルパーメソッドですが、癖のあるメソッドなので慎重に使用していきましょう。