LoginSignup
0
0

More than 1 year has passed since last update.

【モンキーパッチ】管理画面生成gemのAdministrateで、NameError uninitialized constant

Last updated at Posted at 2022-05-25

問題

Administrate gem
0.16.0

コントローラー
app/controllers/admin/students/users_controller.rb

モデル
app/models/students/user.rb

NameError: uninitialized constant Student::User
  File "/app/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.3/lib/active_support/inflector/methods.rb", line 284, in const_get
  File "/app/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.3/lib/active_support/inflector/methods.rb", line 284, in block in constantize
  File "/app/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.3/lib/active_support/inflector/methods.rb", line 280, in each
  File "/app/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.3/lib/active_support/inflector/methods.rb", line 280, in inject
  File "/app/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.3/lib/active_support/inflector/methods.rb", line 280, in constantize
  File "/app/vendor/bundle/ruby/2.6.0/gems/administrate-0.16.0/lib/administrate/resource_resolver.rb", line 16, in resource_class
  File "/app/vendor/bundle/ruby/2.6.0/gems/administrate-0.16.0/lib/administrate/resource_resolver.rb", line 24, in resource_title
  File "/app/vendor/bundle/ruby/2.6.0/gems/administrate-0.16.0/app/controllers/administrate/application_controller.rb", line 186, in translate_with_resource
  File "/app/vendor/bundle/ruby/2.6.0/gems/administrate-0.16.0/app/controllers/administrate/application_controller.rb", line 75, in destroy
  File "/app/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.3.3/lib/action_controller/metal/basic_implicit_render.rb", line 6, in send_action

backtraceを見ると、Administrate::ResourceResolver#resource_classあたりで例外が発生しているようだ。

解決策

Administrate::ResourceResolver#controller_path_partsにモンキーパッチをあてます。

# lib/monkey_patches/administrate.rb

require 'administrate/version'
raise "Consider removing this patch" unless Administrate::VERSION == "0.16.0"

module Administrate
  class ResourceResolver
    def controller_path_parts
      path_parts = controller_path.split("/")[1..-1]
      path_parts[-1] = path_parts[-1].singularize
      path_parts
    end
  end
end

モンキーパッチの詳細について

解説

gemのソースコードをみると、Administrate::ResourceResolverというクラスの機能で、コントローラーのパスから自動でリソースクラス(モデルクラス)を解決しているようです。

例えば、app/controllers/admin/students/users_controller.rbというコントローラーであれば、自動でStudent::Userというクラスを使用するようになっています。

そう、全て単数形になってしまうんですね。以下の箇所が原因です。

    def controller_path_parts
      controller_path.split("/")[1..-1].map(&:singularize)
    end

もし名前空間が複数形の場合(Students::Userのように)、Student::Userのような名前空間が単数形のクラス名が自動生成されると、名前解決できずNameError uninitialized constantが発生してしまうんですね。

そういうわけで、コントローラーのパスからモデル名を推測するさいに名前空間を単数形に変換しないようにすれば解決できるというわけです。

0
0
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
0
0