9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Railsのconfig.eager_loadの影響によるエラーについて

Last updated at Posted at 2019-11-24

自身への注意喚起と同じところで躓いてしまった人がいたらすぐ解決できるように、メモします。

起こった問題

以下のようなcontrollerとviewがあります。(管理者一覧画面)

sysadmin_users_controller.rb
class SysadminUsersController < ApplicationController
 def index
  @sysadmin_users = SysadminUser.order(updated_at: :desc)
 end
end
index.html.slim
= "#{@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になりました:fearful:

エラーの発生原因と解決方法

development環境とstaging環境によってエラーが発生するか違うため、環境によって異なる点を元にエラー原因を確かめようとしました。

1. データベースの違い

development環境とstaging環境で読み込んでいるデータベースが異なっているため、staging環境のデータベースをdevelopment環境にインポートし、同じテーブル状態にしました。

結果

エラー原因分からず、development環境はエラーが発生しませんでした。

2. configファイルの違い

環境ごとに異なるのが、app>config>environments配下にあるファイルです。
development.rbとstaging.rbで異なる箇所を探っていくと、怪しい箇所が・・・。

development.rb
 config.eager_load = false
staging.rb
 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名)が!

users_controller.rb
class SysadminUsersController < ApplicationController
 def index
 end
end

衝撃的ことが2点。

  1. users_contorllerなのに、class名がSysadminUsersController
  2. このファイルは全く使用されていない・・・

ファイルを消したら、無事解決しました:ok_woman_tone1:

今後の対策

config.eager_loadについて理解するきっかけになったものの・・・。以下新たに肝に銘じておきます。

  1. 環境ごとにエラーの有無が異なったら、app>config>environments配下にあるファイルを確認する。(まあこれはいいとして)
  2. controller名とclass名を統一する
  3. 使っていないファイル(controllerに限らず)は削除する(おそらくあとで使うかもしれないと残していたかもしれないが、エラーが発生する原因になり得る)

最後に

今回のエラーの原因は開発経験半年越えている人にとってはとても当たり前のことかもしれませんが、初めたてのメンバーからすると当たり前ではありません。チームで開発していると今初めたてのメンバーがいなくても今後現れるはずなので、しっかりドキュメントに記載し、ルール化、注意喚起したいと思います:raised_hand_tone2:

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?