ActiveHashの落とし穴 (EOTD No.3)
こちらはAmetaです!the Error Of The Day(EOTD)の三回目です。
今回は目次機能を使ってみました!
本日のエラー
ActionView::Template::Error (undefined method 'delivery_days_id' for #<Item:~>)
シチュエーション
ActiveHash[1]を用いて商品宅配日数を直接データベースに保存することなく管理するための実装です。
エラ-メッセージにある"delivery_day_id"というのは、Itemテーブルという商品を管理するテーブルに保存されているものです。
商品が届くまでにかかる日数を3パターン(1日後,2~3日後,4~7日後)に固定したので、ActiveHash::Base[2]を継承させたクラス(DeliveryDay)にハッシュで記述しました。
class DeliveryDay < ActiveHash::Base
self.data = [
{ id: 1, name: '--' },
{ id: 2, name: '1日後' },
{ id: 3, name: '2~3日後' },
{ id: 4, name: '4~7日後' }
]
itemモデル、そしてdelivery_dayモデルにもアソシエーションの記述をしてっと。
models/item.rb
class Item < ApplicationRecord
extend ActiveHash::Associations::ActiveRecordExtensions
belongs_to_active_hash :delivery_day
validates :delivery_days_id, numericality: { other_than: 1, message: "can't be blank" }
models/delivery_day.rb
class DeliveryDay < ActiveHash::Base
self.data = [
{ id: 1, name: '--' },
{ id: 2, name: '1日後' },
{ id: 3, name: '2~3日後' },
{ id: 4, name: '4~7日後' }
]
include ActiveHash::Associations
has_many :items
end
最後にdelivery_dayをビューファイルで呼び出す記述。
<%= @item.delivery_day.name %>
このビューファイルに遷移しようとした所、今回のエラーがおきました。。。
ActionView::Template::Error (undefined method 'delivery_days_id' for #<Item:~>)
考察
delivery_days_idが定義されていないメソッドなので、それを必要とするdelivery_daysメソッドが動いてくれないということなのか...?
でもデータベースのItemテーブルにはdelivery_days_idがカラムとして管理されてるのに。。
しばらく考え、休すかと思いきや...
一つ怪しいところを見つけました!
解決
Itemモデルにある記述です。
class Item < ApplicationRecord
extend ActiveHash::Associations::ActiveRecordExtensions
belongs_to_active_hash :delivery_day
validates :delivery_days_id, numericality: { other_than: 1, message: "can't be blank" }
お分かりいただけたでしょうか。。
belongs_to_active_hash :delivery_day
validates :delivery_days_id
この二つの記述が一致していないという点。
さらに言えば、delivery_day.rbにあるクラス(DeliveryDay)とdelivery_days_idの部分が一致していない。
これが今回のエラーの原因じゃないかということで、モデルとコントローラーにある記述を修正。そして、データベースも一度ロールバックしてマイグレーションをし直しました。
再度試してみると...。通りました!!
原因(おそらく)
ここまで済んだ後に思い出したのが、delivery_day.rbのモデルを作る時のコマンドがdelivery_daysとなってしまっていたことです。
rails g model delivery_days
モデル名は自動でdelivery_day.rbに変換されたみたいですが、データベースにそのまま反映してしまったようでした。
SOTD(Summary of the day)
モデル名は単数形というルールをうっかり忘れてしまった結果、かなり時間を取られました。
Discussion