为什么在 Rails 引擎中明确要求应用程序控制器?
Why explicitly require application controller in Rails engines?
我正在构建一个 Rails 引擎,我注意到如果我像这样生成一个控制器 rails g controller test
它会给我以下输出:
require_dependency "my_app/application_controller"
module MyApp
class TestController < ApplicationController
end
end
为什么需要引擎的应用程序控制器,module MyApp
下的嵌套应该已经消除了 ApplicationControlller 与主应用程序的歧义。
所以我对 rails 源进行了一些挖掘,找到了引入此功能的提交 (sha: 7c95be54)
Fix generators to help with ambiguous ApplicationController
issue
In development mode, dependencies are loaded dynamically at runtime,
using const_missing
. Because of that, when one of the constants is
already loaded and const_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
hit const_missing
. However if you load ApplicationController
first,
the constant will be loaded already, const_missing
hook will not be
fired and in result PostsController
will inherit from
ApplicationController
instead of Blog::ApplicationController
.
Since it can't be fixed in AS::Dependencies
, the easiest fix is to
just explicitly load application controller.
正如人们可能猜到的那样,这归结为自动加载问题!所以请记住孩子们,在处理可能有歧义的代码时,请始终明确说明您导入的内容。
真正令人不安的是,引擎引入的命名空间实际上并没有提供太多隔离,假设您在引擎中引用了其他一些 non-rails class 并且包含的主应用程序恰好有一个常量相同的名称,同样的问题将适用。
我被指向这个 post 用于 same issue within Component-based Rails apps。在这里留下我的想法以备将来参考...
可挂载的引擎带有一个命名空间,它允许另一种方法来解决这个问题:总是用它的命名空间 显式引用每个 class,即 Blog::ApplicationController
.
在您的情况下,以下代码不会出现所描述的问题(不需要显式 require
)。
module Blog
class PostsController < Blog::ApplicationController
end
end
当然,您仍然可以 运行 解决应用程序中出现两个 namespace/class 组合的问题,但这将更加罕见且更容易发现...
我正在构建一个 Rails 引擎,我注意到如果我像这样生成一个控制器 rails g controller test
它会给我以下输出:
require_dependency "my_app/application_controller"
module MyApp
class TestController < ApplicationController
end
end
为什么需要引擎的应用程序控制器,module MyApp
下的嵌套应该已经消除了 ApplicationControlller 与主应用程序的歧义。
所以我对 rails 源进行了一些挖掘,找到了引入此功能的提交 (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.
正如人们可能猜到的那样,这归结为自动加载问题!所以请记住孩子们,在处理可能有歧义的代码时,请始终明确说明您导入的内容。 真正令人不安的是,引擎引入的命名空间实际上并没有提供太多隔离,假设您在引擎中引用了其他一些 non-rails class 并且包含的主应用程序恰好有一个常量相同的名称,同样的问题将适用。
我被指向这个 post 用于 same issue within Component-based Rails apps。在这里留下我的想法以备将来参考...
可挂载的引擎带有一个命名空间,它允许另一种方法来解决这个问题:总是用它的命名空间 显式引用每个 class,即 Blog::ApplicationController
.
在您的情况下,以下代码不会出现所描述的问题(不需要显式 require
)。
module Blog
class PostsController < Blog::ApplicationController
end
end
当然,您仍然可以 运行 解决应用程序中出现两个 namespace/class 组合的问题,但这将更加罕见且更容易发现...