[Rails] ActiveRecordオブジェクト保存時に「WARNING: Can’t mass-assign protected attributes: type」

最近、Railsにどっぷりのkadoppeです。まだまだ未熟者なので、しょっちゅうわからないことやトラブルに遭遇していますが。

今回はそのトラブルの一例の紹介。

ActiveRecordオブジェクトのデータを保存するためにsaveメソッドを呼び出したところ、以下のような例外が発生してしまいました。

保存しようとしていたモデルには普通に「type」という属性を定義していたのですが、『「type」属性は保護されているので値を設定できませんよ』とのこと。保護した覚えはないのに。

どうしてだろうと不思議に思ったので調べてみると、どうやらこの「type」属性は、Railsの「単一テーブル継承(Single Table Inheritance)」という機能で使われる特殊な属性だそう。つまり予約語。

「単一テーブル継承」は、継承関係にある複数のモデルのデータを、一つのテーブルで管理するための機能。テーブルに保存されているデータがどのモデルに対応しているのかを管理するために、この「type」属性が使われます。

今回僕は、通常の属性として「type」属性を定義(つまりテーブルに「type」カラムを追加)していたのですが、単一テーブル継承が使う「type」属性とバッティングしちゃって例外が発生したみたいです。

この例外の回避策としては、

  • 属性を別の名前に変更する。
  • 「set_inheritance_column」メソッドを使って予約語を変更する。

があるかと思います。

前者は単純。自分で定義した「type」属性を「hogehoge_type」のような名前に変更すればOK。

後者は予約語自体を変更してしまおうというアプローチ。「set_inheritance_column」メソッドを問題が生じているモデルクラスにてオーバライドすることで、単一テーブル継承が使う特殊な属性名を変更することができます。

set_inheritance_column (ActiveRecord::Base) – APIdock

僕はどっちかというと、余計なコードを書かなくてもいい前者のアプローチが好みです。

どこかに「使ってはいけない属性リスト」なんて転がっていないかなぁ、とふと思ったkadoppeでした。
それでは!