我正在编写一个可配置的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
(对于常规控制器来说效果很好),但也不起作用(该控制器找不到助手)。
有什么想法吗?
RailsAdmin Engine也被隔离,但是它们具有与您要实现的配置选项相同的配置选项。它们具有可配置的before_filters,用于身份验证和授权。看看this。
据我所知,它们只是像这样::ApplicationController
子类化了父控制器,或者您可以配置一个(ref)。
对于您的控制器,您可以只创建自己的EngineController
,它继承自RocketPant::Base
,也可以在那里创建一个方法,该方法直接通过父控制器上的send
调用已配置的身份验证方法。
因为RocketPant::Base
类不会继承自ApplicationController::Base
,所以我想您必须找到一些自定义方法,而不能采用Rails Engines的常规方法。也许您也可以尝试将问题提交到rocket_pant存储库,以添加helper
方法。据我所知,他们很快想从ApplicationController::Base
中继承2.0(ref)。
您可以通过在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
我认为您一时冲动保持隔离性是好的-因为如果某方法依赖于“仅存在”方法,则很难调试。在使用您的gem的应用程序中出错(即方法名称中的错字)。
此外,如果您的宝石进化了,有朝一日它就不需要此方法,以一种明确的方式给出一个令人发指的错误是非常方便的:
您可以提供要在初始化程序中调用的config方法:
YourGem.configure do |config|
config.add_callback { MyApp.doIt() }
end
我找到了这个discussion particularly insightful。 Rails Engine API中的“隔离引擎帮助程序”下也有一些有趣的想法。
Rails Engine API文档帮助我为url_helpers找到了一个好的解决方案
您现在可能已经继续前进,但是如果其他人需要访问“父应用程序”应用程序助手。您始终可以将其明确包含在引擎的应用程序控制器中。像这样:
include Rails.application.helpers