在隔离的 Rails 引擎中从父应用程序访问助手
Accessing helpers from the parent app in an isolated Rails engine
我正在编写一个可配置的 Rails 引擎。我有一个 authentication_helper
配置选项来定义在所有需要身份验证的控制器的 before_action
中应该调用哪个助手。
问题是我无法从引擎的控制器访问父应用程序的助手。 My understanding是因为引擎被隔离了才会出现这种情况。
我考虑过使用块而不是方法名称,但我不确定这是否可行,或者我是否能够从我的控制器外部干净地访问授权逻辑。
Active Admin,我过去用过,也有类似的配置选项。我注意到他们的引擎不是隔离的,所以也许我高估了引擎隔离的重要性?
有没有一种优雅的方式既可以享受引擎隔离的好处,又可以进行这种自定义?还是我应该完全放弃隔离?
编辑#1
Brad Werth 为我指出了正确的方向,因为这适用于继承自 ApplicationController::Base
:
的常规控制器
module MyBigFancyEngine
class Engine < Rails::Engine
isolate_namespace MyBigFancyEngine
config.to_prepare do
# Make the implementing application's helpers available to the engine.
# This is required for the overriding of engine views and helpers to work correctly.
MyBigFancyEngine::ApplicationController.helper Rails.application.helpers
end
end
end
然而,我的引擎的 ApplicationController
继承自 RocketPant::Base
,它不提供 helper
方法。我试过使用一个简单的 include
(对于常规控制器工作正常),但这也不起作用(控制器找不到助手)。
有什么想法吗?
我认为你保持隔离的冲动是好的 - 因为如果 s.th 依赖方法 'just being there' 的解决方案很难调试。使用您的 gem 的应用程序出错(即方法名称中的拼写错误)。
此外,如果您的 gem 有所发展,总有一天它不需要该方法,以一种明确的方式给出有意义的错误非常方便:
您可以提供一个在初始化程序中调用的配置方法:
YourGem.configure do |config|
config.add_callback { MyApp.doIt() }
end
我在 Isolated engine helpers 下找到了这个 discussion particularly insightful. There are also some interesting ideas in the Rails Engine API。
Rails 引擎 API 文档帮助我找到了 url_helpers
的良好解决方案
您可以通过在 engine.rb 文件中包含以下代码来公开引擎可用的实施应用程序助手:
engine.rb
module MyBigFancyEngine
class Engine < Rails::Engine
isolate_namespace MyBigFancyEngine
config.to_prepare do
# Make the implementing application's helpers available to the engine.
# This is required for the overriding of engine views and helpers to work correctly.
MyBigFancyEngine::ApplicationController.helper Rails.application.helpers
end
end
end
Rails管理引擎也是独立的,但它们具有与您希望实现的相同的配置选项。他们具有可配置的 before_filters 用于身份验证和授权。看看 this.
据我所知,它们只是像这样子类化父控制器::ApplicationController
,或者您可以配置一个 (ref)。
对于您的控制器,您可以创建自己的 EngineController
,它继承自 RocketPant::Base
,并且可能只是在那里创建一个方法,通过 send
直接调用配置的身份验证方法父控制器。
因为 RocketPant::Base
Class 没有继承自 ApplicationController::Base
我想你必须找到一些自定义的方法来解决这个问题并且不能使用 [=32= 的正常方法] 引擎。也许您也可以尝试向 rocket_pant 存储库提交问题,以添加 helper
方法。据我所知,他们很快就想在 2.0 (ref) 中继承 ApplicationController::Base
。
您现在可能继续前进,但如果其他人需要访问 "parent app" 应用程序助手。您总是可以将它显式地包含在引擎的应用程序控制器中。像这样:
include Rails.application.helpers
我正在编写一个可配置的 Rails 引擎。我有一个 authentication_helper
配置选项来定义在所有需要身份验证的控制器的 before_action
中应该调用哪个助手。
问题是我无法从引擎的控制器访问父应用程序的助手。 My understanding是因为引擎被隔离了才会出现这种情况。
我考虑过使用块而不是方法名称,但我不确定这是否可行,或者我是否能够从我的控制器外部干净地访问授权逻辑。
Active Admin,我过去用过,也有类似的配置选项。我注意到他们的引擎不是隔离的,所以也许我高估了引擎隔离的重要性?
有没有一种优雅的方式既可以享受引擎隔离的好处,又可以进行这种自定义?还是我应该完全放弃隔离?
编辑#1
Brad Werth 为我指出了正确的方向,因为这适用于继承自 ApplicationController::Base
:
module MyBigFancyEngine
class Engine < Rails::Engine
isolate_namespace MyBigFancyEngine
config.to_prepare do
# Make the implementing application's helpers available to the engine.
# This is required for the overriding of engine views and helpers to work correctly.
MyBigFancyEngine::ApplicationController.helper Rails.application.helpers
end
end
end
然而,我的引擎的 ApplicationController
继承自 RocketPant::Base
,它不提供 helper
方法。我试过使用一个简单的 include
(对于常规控制器工作正常),但这也不起作用(控制器找不到助手)。
有什么想法吗?
我认为你保持隔离的冲动是好的 - 因为如果 s.th 依赖方法 'just being there' 的解决方案很难调试。使用您的 gem 的应用程序出错(即方法名称中的拼写错误)。
此外,如果您的 gem 有所发展,总有一天它不需要该方法,以一种明确的方式给出有意义的错误非常方便:
您可以提供一个在初始化程序中调用的配置方法:
YourGem.configure do |config|
config.add_callback { MyApp.doIt() }
end
我在 Isolated engine helpers 下找到了这个 discussion particularly insightful. There are also some interesting ideas in the Rails Engine API。
Rails 引擎 API 文档帮助我找到了 url_helpers
的良好解决方案您可以通过在 engine.rb 文件中包含以下代码来公开引擎可用的实施应用程序助手:
engine.rb
module MyBigFancyEngine
class Engine < Rails::Engine
isolate_namespace MyBigFancyEngine
config.to_prepare do
# Make the implementing application's helpers available to the engine.
# This is required for the overriding of engine views and helpers to work correctly.
MyBigFancyEngine::ApplicationController.helper Rails.application.helpers
end
end
end
Rails管理引擎也是独立的,但它们具有与您希望实现的相同的配置选项。他们具有可配置的 before_filters 用于身份验证和授权。看看 this.
据我所知,它们只是像这样子类化父控制器::ApplicationController
,或者您可以配置一个 (ref)。
对于您的控制器,您可以创建自己的 EngineController
,它继承自 RocketPant::Base
,并且可能只是在那里创建一个方法,通过 send
直接调用配置的身份验证方法父控制器。
因为 RocketPant::Base
Class 没有继承自 ApplicationController::Base
我想你必须找到一些自定义的方法来解决这个问题并且不能使用 [=32= 的正常方法] 引擎。也许您也可以尝试向 rocket_pant 存储库提交问题,以添加 helper
方法。据我所知,他们很快就想在 2.0 (ref) 中继承 ApplicationController::Base
。
您现在可能继续前进,但如果其他人需要访问 "parent app" 应用程序助手。您总是可以将它显式地包含在引擎的应用程序控制器中。像这样:
include Rails.application.helpers