I am building a Rails engine and I noticed that if I generate a controller like so rails g controller test
it gives me the following output:
require_dependency "my_app/application_controller"
module MyApp
class TestController < ApplicationController
end
end
Why is it necessary to require the engine's application controller, the nesting under module MyApp
should already disambiguate the ApplicationControlller from the main app's.
So I did some digging through the rails source and found the commit who introduced this feature (sha: 7c95be54)
Fix generators to help with ambiguous
ApplicationController
issueIn development mode, dependencies are loaded dynamically at runtime, using
const_missing
. Because of that, when one of the constants is already loaded andconst_missing
is not triggered, user can end up with unexpected results.Given such file in an Engine:
module Blog
class PostsController < ApplicationController
end
end
If you load it first, before loading any application files, it will correctly load
Blog::ApplicationController
, because second line will hitconst_missing
. However if you loadApplicationController
first, the constant will be loaded already,const_missing
hook will not be fired and in resultPostsController
will inherit fromApplicationController
instead ofBlog::ApplicationController
.Since it can't be fixed in
AS::Dependencies
, the easiest fix is to just explicitly load application controller.
So as one could have guessed, this comes down to an autoloading issue! So remember kids, always make explicit what you import when dealing with potentially ambiguous code. What is really disconcerting is that the namespacing introduced by engines, really doesn't provide too much isolation, imagine you reference some other non-rails class in your engine and the including main app happens to have a constant of the same name, the same issue would apply.