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

问题描述 投票:2回答:2

我想通过装饰其中一个引擎的辅助模块,从引擎中的应用程序中包含一个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调用中来包含该问题,但这也不起作用。

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

ruby-on-rails ruby
2个回答
0
投票

我将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

结果将是:

做东西

做这个

去做


0
投票

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

如果您的引擎提供:

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配置设置(或单独的模块配置)或只是方法参数而不是一些疯狂的循环依赖马戏团。

© www.soinside.com 2019 - 2024. All rights reserved.