Suppose you want to have two controllers on the one namespaced model, call it Foo::Bar
. Suppose one is an admin controller and you want to namespace it as Admin::Foo::BarsController
. Any reason that shouldn’t work? Well, it sure doesn’t work, at least in Rails 3.2.x!
The problem I ran into is how the Rails determines the corresponding model for a controller.
- When Rails loads the controller, it will determine the model. I don’t see any way to disable that.
- If the controller is named
Admin::Foo::BarsController
, then the following are looked up, in this order:Admin::Foo::Bar
Admin::Bar
::Bar
- The 3rd result is found and that will find the file at
/app/models/foo/bar.rb
. But, the dependency loader is expecting to find::Bar
declared in this file, and thenFoo::Bar
is found. The stack trace is below.
The fix I’m using is to change the order of the modules for the controller. So I’m using the Foo::Admin::BarsController
Is that the best fix?
Here’s an article that somewhat partially explains the issue:
Rails autoloading — how it works, and when it doesn’t
Stack Dump of two controllers on same one namespaced model
/.rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:503:in `load_missing_constant': Expected /app/models/foo/bar.rb to define Bar (LoadError)
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:192:in `block in const_missing'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:190:in `each'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:190:in `const_missing'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:514:in `load_missing_constant'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:192:in `block in const_missing'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:190:in `each'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:190:in `const_missing'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:514:in `load_missing_constant'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:192:in `block in const_missing'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:190:in `each'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/dependencies.rb:190:in `const_missing'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/inflector/methods.rb:230:in `block in constantize'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/inflector/methods.rb:229:in `each'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/inflector/methods.rb:229:in `constantize'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/inflector/methods.rb:260:in `safe_constantize'
from .rvm/gems/ruby-2.1.5/gems/activesupport-3.2.16/lib/active_support/core_ext/string/inflections.rb:66:in `safe_constantize'
from .rvm/gems/ruby-2.1.5/gems/actionpack-3.2.16/lib/action_controller/metal/params_wrapper.rb:152:in `_default_wrap_model'
from .rvm/gems/ruby-2.1.5/gems/actionpack-3.2.16/lib/action_controller/metal/params_wrapper.rb:169:in `_set_wrapper_defaults'
from .rvm/gems/ruby-2.1.5/gems/actionpack-3.2.16/lib/action_controller/metal/params_wrapper.rb:133:in `inherited'
from .rvm/gems/ruby-2.1.5/gems/actionpack-3.2.16/lib/abstract_controller/railties/routes_helpers.rb:7:in `block (2 levels) in with'
from .rvm/gems/ruby-2.1.5/gems/actionpack-3.2.16/lib/action_controller/railties/paths.rb:7:in `block (2 levels) in with'
from /app/controllers/admin/foo/bars_controller.rb:61:in `<module:Foo>'
from /app/controllers/admin/foo/bars_controller.rb:12:in `<module:Admin>'
from /app/controllers/admin/foo/bars_controller.rb:11:in `<top (required)>'