自身への注意喚起と同じところで躓いてしまった人がいたらすぐ解決できるように、メモします。
起こった問題
以下のようなcontrollerとviewがあります。(管理者一覧画面)
class SysadminUsersController < ApplicationController
def index
@sysadmin_users = SysadminUser.order(updated_at: :desc)
end
end
= "#{@sysadmin_users.count}件"
table
thead
tr
th | 氏名
th | メールアドレス
th | 最終更新日
tbody
- @sysadmin_users.each do |sysadmin_user|
td = sysadmin_user.name
td = sysadmin_user.email
td = l(sysadmin_user.updated_at, format: :short)
上記該当するURL(/sysadmin_users)にアクセスするとdevelopment環境では問題なかったのですが、staging環境では、index.html.slimのcount
がno metthod errorになりました
エラーの発生原因と解決方法
development環境とstaging環境によってエラーが発生するか違うため、環境によって異なる点を元にエラー原因を確かめようとしました。
1. データベースの違い
development環境とstaging環境で読み込んでいるデータベースが異なっているため、staging環境のデータベースをdevelopment環境にインポートし、同じテーブル状態にしました。
結果
エラー原因分からず、development環境はエラーが発生しませんでした。
2. configファイルの違い
環境ごとに異なるのが、app>config>environments配下にあるファイルです。
development.rbとstaging.rbで異なる箇所を探っていくと、怪しい箇所が・・・。
config.eager_load = false
config.eager_load = true
development.rbをconfig.eager_load = true
に書き換えると・・・
staging環境と同じエラーが発生しました!
config.eager_loadって何?
@shakemurasanさんの記事が分かりやすいと思いますので、こちらを参照してみてください。
https://qiita.com/shakemurasan/items/305bd3d78d67b646bc06
config.eager_loadをtrueにすると、controllerやmodelなどのclass名がすべて事前に読み込まれます。(事前というのはおそらくrails serverが起動するタイミングです)
そのため、ページを読み込むたびにclassを読み込む必要はないので、ページ読み込みスピードは速くなります。
一方、config.eager_loadをfalseにすると、ページ読み込みスピードは遅くなりますが、rails serverの起動スピードは速くなります。
ちなみに、development環境においてconfig.eager_loadをfalseにしている理由としては、stagingとは異なり頻繁にソースコードが変更され、その度にrails serverを再起動しdevelopment環境でブラウザテストしているという背景があるためです。
なぜconfig.eager_loadの設定でエラーが発生したのか?
事前にnamespace(class名)をすべて読み込まれるとエラーが起こって、ページにアクセスしたタイミングで特定のclassを読み込むとエラーが発生しない・・・。
ん?もしや同じnamespace(class名)が存在しているのでは?
SysadminUsersControllerで全文検索すると、ありました!同じnamespace(class名)が!
class SysadminUsersController < ApplicationController
def index
end
end
衝撃的ことが2点。
- users_contorllerなのに、class名がSysadminUsersController
- このファイルは全く使用されていない・・・
ファイルを消したら、無事解決しました
今後の対策
config.eager_loadについて理解するきっかけになったものの・・・。以下新たに肝に銘じておきます。
- 環境ごとにエラーの有無が異なったら、app>config>environments配下にあるファイルを確認する。(まあこれはいいとして)
- controller名とclass名を統一する
- 使っていないファイル(controllerに限らず)は削除する(おそらくあとで使うかもしれないと残していたかもしれないが、エラーが発生する原因になり得る)
最後に
今回のエラーの原因は開発経験半年越えている人にとってはとても当たり前のことかもしれませんが、初めたてのメンバーからすると当たり前ではありません。チームで開発していると今初めたてのメンバーがいなくても今後現れるはずなので、しっかりドキュメントに記載し、ルール化、注意喚起したいと思います