Rails

【Rails】Formオブジェクトでdate_selectを使おうとしたらUnknownAttributeエラーが出た話

Rails

 

今回はフォームでdate_selectを使用し、かつFormオブジェクトを用いた場合にUnknownAttributeエラーが発生してしまい、結構ハマったので備忘録として残しておきます。同じように困っている人の参考になればと思います。

この記事に記載の解決方法は、date_selectだけでなくdatetime_selectにも適用することができます。

前提

  • 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エラーが出力されてしまいました。

エラー画面
date_selectから送られてくるパラメーターがunknown attribute(未知の属性)になってしまっているね。

解決方法【結論】

結論、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は便利なヘルパーメソッドですが、癖のあるメソッドなので慎重に使用していきましょう。