Ruby on Rails 6.0.0 で作成したアプリケーションに、JWTトークンの発行・認証を行う目的で knock をインストールしようとしたところ、loadに関するエラーが発生したので対処法をまとめます。
発生したエラー
現象1
rails generate knock:install
を実行するとwarningとerrorが出力される。
config/initializers/knock.rb
の生成自体はできている。
$ rails generate knock:install
Running via Spring preloader in process 14337
[WARNING] Could not load generator "generators/knock/install_generator". Error: expected file /home/user/.rbenv/versions
現象2
ApplicationController
にて Knock::Authenticable
をincludeさせると、railsが起動できない。
$ rails c
/home/user/Documents/develop/knock_test/app/controllers/application_controller.rb:2:in `<class:ApplicationController>': uninitialized constant Knock::Authenticable (NameError)
原因
Rails6でのautoloadがzeitwerkモードに変更となったことで、autoloadの挙動がRails5以前と変わったことに起因しています。
Rails 6 zeitwerk autoload problem with gem
対処法
対処法1. 明示的にrequireする[推奨]
上記issueにある通り、明示的にソースをrequireすることでエラーを回避できます。
require 'knock/version'
require 'knock/authenticable'
対処法2. autoloadをclassicモードに戻す[非推奨]
Rails5以前と同じ方法でautoloadさせることでもエラーを回避できます。
基本的には新しいバージョンに追従すべきなので非推奨ですが、他のgemで同様のエラーが発生する場合などはこちらの方が手っ取り早いかもしれません。
require_relative 'boot'
require "rails"
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "rails/test_unit/railtie"
Bundler.require(*Rails.groups)
module KnockTest
class Application < Rails::Application
config.load_defaults 6.0
config.api_only = true
config.autoloader = :classic # ★追記
end
end
まとめ
こちらの issueで何かしら修正が入ることに期待しつつ、まずは上記のような対策でエラーを回避するしかなさそうです。