在隔离的Rails引擎中从父应用程序访问帮助程序

时间:2015-08-07 12:34:46

标签: ruby-on-rails ruby rails-engines

我正在编写一个可配置的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(适用于常规控制器),但这也不起作用(控制器找不到帮助器)。

有什么想法吗?

5 个答案:

答案 0 :(得分:5)

您可以通过在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

答案 1 :(得分:2)

RailsAdmin引擎也是独立的,但它们具有您想要实现的相同配置选项。它们具有可配置的before_filters,用于身份验证和授权。看看this

据我所知,他们只是将父控制器子类化为::ApplicationController,或者你可以配置一个(ref)。

对于您的控制器,您可以创建自己的EngineController,它继承自RocketPant::Base,并且可能只是创建一个方法,直接通过父控制器上的send调用配置的身份验证方法。

由于RocketPant::Base类不从ApplicationController::Base继承,我猜你必须找到一些自定义的方法,并且不能采用Rails引擎的常规方法。也许你也可以尝试向rocket_pant repo提交一个问题,添加helper方法。据我所知,他们很快就想在2.0(ref)中继承ApplicationController::Base

答案 2 :(得分:0)

我认为你保持隔离是好的冲动 - 因为一种解决方案依赖于一种方法而只是在那里&#39;如果s.th.是一个痛苦的调试。使用您的宝石在应用程序中出错(即方法名称中的拼写错误)。

此外,如果你的宝石进化,有一天它不会需要这种方法,以明确的方式非常方便地给出一个可怕的错误:

您可以提供在初始化程序中调用的配置方法:

YourGem.configure do |config|
  config.add_callback { MyApp.doIt() }
end

答案 3 :(得分:0)

我发现了discussion particularly insightful。隔离引擎助手下的Rails Engine API中也有一些有趣的想法。

Rails Engine API文档帮助我找到了url_helpers的一个很好的解决方案

答案 4 :(得分:0)

您现在可能已经搬走了,但是如果其他人需要访问“父应用程序”应用程序助手。您始终可以将其明确包含在引擎的应用程序控制器中。像这样:

include Rails.application.helpers