装饰一个Rails引擎助手,以包含来自主应用程序的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰一个Rails引擎助手,以包含来自主应用程序的问题相关的知识,希望对你有一定的参考价值。

我想通过装饰其中一个引擎的辅助模块,从引擎中的应用程序中包含一个ActiveSupport :: Concern。这是引擎的助手:

module MyEngine
  module MyHelper
  end
end

以下是主应用程序的关注点:

module MyConcern
  extend ActiveSupport::Concern

  def do_this
  end

  def do_that
  end
end

下面是需要包含关注点(在引擎视图中使用)的装饰引擎助手 - 它在主应用程序中声明,使用Rails guides中描述的装饰器模式:

module MyEngine
  module MyHelper
    include MyConcern

    def do_stuff
    end
  end
end

装饰的助手由引擎正确加载,但引擎视图只能调用“do_stuff”。来自MyConcern的方法不可用,我很难搞清楚原因。我还尝试通过将其嵌入到MyEngine :: MyHelper.module_eval调用中来包含该问题,但这也不起作用。

以前有人遇到过这种问题吗?我采取了错误的方式吗?

答案

我将MyHelper从一个模块改为了类

module MyConcern
  extend ActiveSupport::Concern

  def do_this
    "do this"
  end

  def do_that
    "do that"
  end
end

module MyEngine
  class MyHelper
    include ::MyConcern

    def do_stuff
      "do stuff"
    end
  end
end

致电时:

MyEngine::MyHelper.new.do_stuff
MyEngine::MyHelper.new.do_this
MyEngine::MyHelper.new.do_that

结果将是:

做东西

做这个

去做

另一答案

我想你可能会向后推理这个问题。

如果您的引擎提供:

module MyEngine
  module MyHelper
    def foo
    end
  end
end

您可以在主应用程序中扩展该方法(您可以将其称为装饰,但我不确定这在技术上是否是装饰器模式):

module MainApp
  module MyHelper
    extend ::MyEngine::MyHelper
    def foo
      super
      do_something_else
    end
  end
end

当使用模块混合模式(这是ActiveSupport :: Concern所做的)时,您可以使用模块扩展模块并在类中包含模块。

如果你的引擎和主应用程序“共享一个部分” - 它应该只是放在引擎中,因为Rails将首先在应用程序的app / views目录中进行渲染时查找视图,然后再查找已安装的引擎。

因此,主应用程序可以始终覆盖引擎提供的功能,而反之则不然。

如果你想让一个引擎提供的方法可配置,更好的想法是使用Rails配置设置(或单独的模块配置)或只是方法参数而不是一些疯狂的循环依赖马戏团。

以上是关于装饰一个Rails引擎助手,以包含来自主应用程序的问题的主要内容,如果未能解决你的问题,请参考以下文章

rails prepend_view_path 可安装引擎

Rails引擎:命名空间多态URL

如何将 Rails 视图助手提取到 gem 中?

Rails - 如何向 url 助手添加格式?

Rails:如何访问 RESTful 助手?

使用 Rails 助手渲染部分