背景
grape
とactiveadmin
を使って、APIの管理画面を作りたかった。
両者とも基本に忠実に、ちょっと手を加えた程度の作り込みだったのがずっと以下のエラーが出てしまった。
load_missing_constant': Unable to autoload constant Base,
expected /vagrant/app/apis/api/base.rb to define it (LoadError)
問題
Grapeの記事は色々まとめられていて、
下記のリンクを見れば分かる通り多くの人がAPI::Base
という形でnamespaceを確保し、
base.rb
をapplication.rb
のような扱いで利用している。
- Grape で Web API 開発 - kzy52's blog
- GrapeをつかってAPIを作成する - It's now or never
- CODETUNES · Introduction to building APIs with Grape
- GrapeでAPIを構築時のメモ
自分も同じようにAPI::Base
でmountして、
base.rb
をapplication.rb
としてモリモリ作り込んでいた。
apis
└── api
├── base.rb
└── v2
├── base.rb
├── books.rb
└── users.rb
ある程度作った時に、ActiveAdminを入れてみるとエラーが起きた。
load_missing_constant': Unable to autoload constant Base,
expected /vagrant/app/apis/api/base.rb to define it (LoadError)
その時の設定はこんな感じ
routes.rb
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
mount API::Base => '/'
end
config/application.rb
module AppName
class Application < Rails::Application
config.paths.add File.join('app', 'apis'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'apis', '*')]
config.middleware.use(Rack::Config) do |env|
env['api.tilt.root'] = Rails.root.join 'app', 'views', 'apis'
end
end
end
apis/api/base.rb
module API
class Base < Grape::API
mount V2::Base
end
end
エラーメッセージでは/vagrant/app/apis/api/base.rb
でBaseを定義してよ!と言われているのだが、ちゃんとしている。
どちらももう一方を読み込まなければ動くので、何かの噛み合わせが悪いようだ。
原因
/home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:495:in `load_missing_constant': Unable to autoload constant Base, expected /vagrant/app/apis/api/base.rb to define it (LoadError)
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:184:in `const_missing'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:526:in `load_missing_constant'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:184:in `const_missing'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:263:in `const_get'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:263:in `block in constantize'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:259:in `each'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:259:in `inject'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/inflector/methods.rb:259:in `constantize'
from /home/vagrant/.gem/ruby/2.2.2/gems/activesupport-4.2.1/lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
from /home/vagrant/.gem/ruby/2.2.2/gems/inherited_resources-1.6.0/lib/inherited_resources/class_methods.rb:317:in `initialize_resources_class_accessors!'
from /home/vagrant/.gem/ruby/2.2.2/gems/inherited_resources-1.6.0/lib/inherited_resources/class_methods.rb:394:in `inherited'
from /home/vagrant/.gem/ruby/2.2.2/bundler/gems/active_admin-28e8a8f36640/lib/active_admin/base_controller/authorization.rb:2:in `<module:ActiveAdmin>'
from /home/vagrant/.gem/ruby/2.2.2/bundler/gems/active_admin-28e8a8f36640/lib/active_admin/base_controller/authorization.rb:1:in `<top (required)>'
エラーlogを見てみるとactiveadmin
のauthorize.rbがエラーを出していた。
が、どうやらactiveadmin
がGrapeのBase
を読みに行ってエラーを吐いているらしい。
解決
以下のようにbase
というクラス名を変更した。
```sh
apis
└── api
├── api_base.rb
└── v2
├── v2_base.rb
├── books.rb
└── users.rb
routes.rb
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
mount API::ApiBase => '/'
end
api_base.rb
module API
class ApiBase < Grape::API
mount V2::V2Base
end
end
根本的な解決にはなっていないかもしれないけど、とりあえずこれで動いたので一安心。
皆さんもハマらないように気をつけて下さい。