简体   繁体   English

装饰 Rails 引擎的助手以包含来自主应用程序的关注

[英]Decorate a Rails engine's helper to include a concern from the main app

I would like to include an ActiveSupport::Concern from an app in an engine, by decorating one of the engine's helper modules.我想通过装饰引擎的帮助程序模块之一,在引擎中包含来自应用程序的 ActiveSupport::Concern。 Here is the Helper from the engine:这是来自引擎的 Helper:

module MyEngine
  module MyHelper
  end
end

Here is the Concern from the main app :这是主应用程序的关注点:

module MyConcern
  extend ActiveSupport::Concern

  def do_this
  end

  def do_that
  end
end

Below is the decorated engine helper that needs to include the concern (for use in the engine views) - it is declared in the main app , using the decorator pattern described in the Rails guides :下面是需要包含关注点的装饰引擎助手(用于引擎视图) - 它在主应用程序中声明,使用Rails 指南中描述的装饰器模式:

module MyEngine
  module MyHelper
    include MyConcern

    def do_stuff
    end
  end
end

The decorated helper is properly loaded by the engine, but the engine views are only able to call "do_stuff".修饰的帮助器由引擎正确加载,但引擎视图只能调用“do_stuff”。 The methods from MyConcern are unavailable, and I'm having a hard time figuring out why. MyConcern 的方法不可用,我很难弄清楚原因。 I also tried to include the concern by embedding it in a MyEngine::MyHelper.module_eval call, but that didn't work either.我还尝试通过将其嵌入 MyEngine::MyHelper.module_eval 调用来包含该问题,但这也不起作用。

Has anyone faced this kind of issue before ?有没有人遇到过这种问题? Am I taking this the wrong way ?我是否以错误的方式看待这个问题?

I renplaced MyHelper from module to class我将 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

When calling :打电话时:

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

The result will be :结果将是:

do stuff做东西

do this做这个

do that去做

I think you may be reasoning about this backwards.我想你可能在反推这个。

If your engine provides:如果您的引擎提供:

module MyEngine
  module MyHelper
    def foo
    end
  end
end

You can extend the method (you could call it decorate but i'm not sure if this is technically the decorator pattern) in your main app:您可以在主应用程序中扩展该方法(您可以将其称为装饰,但我不确定这在技术上是否是装饰器模式):

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

When using the module-mixin pattern (which is what ActiveSupport::Concern does) you extend modules with modules and include modules in classes.当使用模块混合模式(这是 ActiveSupport::Concern 所做的)时,您可以使用模块扩展模块并将模块包含在类中。

If you engine and main app "share a partial" - it should just be placed in the engine as Rails will first look for the view when rendering in the app/views directory of the application before looking for it the mounted engines.如果您的引擎和主应用程序“共享部分” - 它应该只是放置在引擎中,因为 Rails 将在应用程序的 app/views 目录中渲染时首先查找视图,然后再查找已安装的引擎。

The main app can thus always override the functionality provided by the engine while the inverse is not true.因此,主应用程序可以始终覆盖引擎提供的功能,而反之则不然。

If you want to make a method provided by an engine configurable a better idea is to use a Rails configuration setting (or a seperate module configuration) or just method arguments rather than some crazy circular dependency circus.如果您想让引擎提供的方法可配置,更好的主意是使用 Rails 配置设置(或单独的模块配置)或仅使用方法参数,而不是一些疯狂的循环依赖马戏团。

So I finally found a way to do this in a "clean" way, as mentioned in the following comment : https://groups.google.com/g/rubyonrails-core/c/PaABJDXnxyo/m/k-QUJEi9a9wJ所以我终于找到了一种以“干净”的方式做到这一点的方法,如以下评论中所述: https : //groups.google.com/g/rubyonrails-core/c/PaABJDXnxyo/m/k-QUJEi9a9wJ

The idea is to add an empty placeholder helper in the engine, for example :这个想法是在引擎中添加一个空的占位符助手,例如:

module MyEngine
  module ExtendableHelper
  end
end

And then override it in the main app, by adding methods or including concerns, other gems' helpers, etc...然后在主应用程序中覆盖它,通过添加方法或包含关注点、其他 gem 的助手等...

module MyEngine
  module ExtendableHelper
    extend OtherGemFromMainApp::UsefulHelper
    include MainAppConcern
    
    def other_useful_method
      ...
    end
  end
end

Thus the helper used by the engine is the one provided by the app, and the UsefulHelper methods can be called in the engine views.因此引擎使用的助手是应用程序提供的助手,可以在引擎视图中调用UsefulHelper方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM