Rails 3.1:更好的方式在客户端应用程序中公开引擎的帮助程序

27

我发现了一些关于引擎内部帮助程序无法被消费(父级)应用程序访问的文章。为了确保我们都理解得一致,假设我们有以下情况:

module MyEngine
  module ImportantHelper
    def some_important_helper
      ...do something important...
    end
  end
end

如果您查看“隔离引擎辅助程序”(L293)中的rails engine文档,它会说:
  # Sometimes you may want to isolate engine, but use helpers that are defined for it.
  # If you want to share just a few specific helpers you can add them to application's
  # helpers in ApplicationController:
  #
  # class ApplicationController < ActionController::Base
  #   helper MyEngine::SharedEngineHelper
  # end
  #
  # If you want to include all of the engine's helpers, you can use #helpers method on an engine's
  # instance:
  #
  # class ApplicationController < ActionController::Base
  #   helper MyEngine::Engine.helpers
  # end

如果我要求任何使用我的引擎的人将此添加到他们的application_controller.rb中,那么他们就可以访问我所有重要的帮助方法:

class ApplicationController < ActionController::Base
  helper MyEngine::ImportantHelper
end

这是我想要的,而且它有效,但这有点麻烦,特别是如果像我的用例一样,引擎暴露的每个东西都可以/应该在使用的应用程序中任何地方使用。因此,我再找了一些资料,发现了一个解决方案,建议我执行以下操作:

module MyEngine
  class Engine < Rails::Engine
    isolate_namespace MyEngine

    config.to_prepare do
      ApplicationController.helper(ImportantHelper)
    end
  end
end

现在这正是我想要的:将所有重要的帮助方法添加到父应用程序的应用程序辅助程序中。但是,它不起作用。有人能帮我弄清楚为什么这个更好的解决方案不起作用吗?
我正在运行ruby 1.8.7和rails 3.1.3。如果我错过了与问题相关的任何重要信息,请告诉我,提前感谢您。
5个回答

44

您可以创建一个初始化程序来完成这个操作,如下所示:

module MyEngine
  class Engine < Rails::Engine
    initializer 'my_engine.action_controller' do |app|
      ActiveSupport.on_load :action_controller do
        helper MyEngine::ImportantHelper
      end
    end
  end
end

似乎每个控制器都自动包含了所有的帮助程序,至少在使用 --full 引擎时是这样。 - Joshua Muheim
这可能自我最初发布以来已经发生了变化,但当时是必需的。 - JDutil
在Rails 4中,即使是引擎内部的helpers也无法正常工作。使用上述代码解决了这个问题 :) - Marcus Mansur
1
我认为如果引擎被隔离,它们就不会被加载。移除 isolate_namespace MyEngine 意味着它们会被加载,但当然会有其他副作用。 - Kris
是的,伙计,在Rails 4中使用可挂载引擎对我有效。 - jspooner
显示剩余5条评论

6

1
链接已失效 :/ - Waclock

6

如果你想将代码保存在引擎中,而不是每个实现应用程序,可以使用以下方法:

module MyEngine
  class Engine < Rails::Engine
    isolate_namespace MyEngine

    config.to_prepare do
      MyEngine::ApplicationController.helper Rails.application.helpers
    end

  end
end

1
module YourEngine
  module Helpers
    def a_helper
    end

    ...
  end
end

ActionController::Base.send(:helper, YourEngine::Helpers)

1
在engine.rb中包含这段代码也会非常有帮助。
config.before_initialize do
  ActiveSupport.on_load :action_controller do
    helper MyEngine::Engine.helpers
  end
end

基本上,您的引擎会看起来像这样。
module MyEngine
  class Engine < Rails::Engine
    isolate_namespace MyEngine

    # Here comes the code quoted above 

  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接