【问题标题】:Accessing helpers from the parent app in an isolated Rails engine在隔离的 Rails 引擎中从父应用程序访问帮助程序
【发布时间】:2015-10-30 21:43:07
【问题描述】:

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

有什么想法吗?

【问题讨论】:

  • 你试过我的方法了吗?你看了吗?

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


【解决方案1】:

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

【讨论】:

  • 谢谢!这适用于常规控制器,但我正在使用 RocketPants 并且遇到了一些麻烦。我已经更新了原始问题。你有什么想法吗?
  • @AlessandroDesantis 你能在控制器中包含 ActionController::Helpers 吗?
【解决方案2】:

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

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

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

由于RocketPant::Base 类不继承自ApplicationController::Base,我想您必须找到一些自定义方法来解决这个问题,并且不能采用 Rails 引擎的正常方法。也许您也可以尝试向 Rocket_pant 存储库提交问题,以添加 helper 方法。据我所知,他们很快希望在 2.0 (ref) 中从 ApplicationController::Base 继承。

【讨论】:

  • 子类化父控制器似乎有效。谢谢!
  • 是的,很抱歉。我做了很多事情,直到赏金到期后才找到时间尝试您的解决方案:(
【解决方案3】:

我认为你保持隔离的冲动是好的 - 因为依赖于“只是在那里”的方法的解决方案在调试时会很痛苦。使用您的 gem 在应用程序中出错(即方法名称中的拼写错误)。

如果你的 gem 进化了,有一天它不需要这个方法,以明确的方式给出一个有意义的错误是非常方便的:

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

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

【讨论】:

    【解决方案4】:

    我发现了这个discussion particularly insightful。在独立引擎助手下的Rails Engine API 中也有一些有趣的想法。

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

    【讨论】:

      【解决方案5】:

      您现在可能继续前进,但如果其他人需要访问“父应用程序”应用程序帮助程序。您始终可以将其显式包含在引擎的应用程序控制器中。像这样:

      include Rails.application.helpers

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多