【问题标题】:How to extend Rails Engine's controllers properly?如何正确扩展 Rails Engine 的控制器?
【发布时间】:2011-10-10 23:00:42
【问题描述】:

我正在开发名为 Carrier (https://github.com/stanislaw/carrier) 的 Rails 插件(它是 3.1 引擎)。

在我的一个 Rails 应用程序中,我想用一些新方法来扩展 Carrier 的控制器 - fx。向 Carrier::MessagesController 添加新操作 #comment_form(我希望此操作仅存在于我的应用程序中 - 我不想将其添加到引擎中 - 因为它非常具体)。

我在这里看到的两种策略:

1) 我将 {Carrier's plugin root}/app/controllers/carrier/messages_controller.rb 文件复制到我的应用程序的 app/controllers/carrier/ 文件夹,然后扩展它(所有插件的原始操作都复制到 rails 应用程序控制器文件夹!)。

2) 我想要的更准确的方法 - 只是创建 {My rails app}/app/controllers/carrier/messages_controller.rb 并只编写我希望扩展 Carrier 的#comment_form 方法。

期望两个控制器的内容(来自插件文件夹的原始内容+我的 rails 应用程序中的自定义内容只有新的#comment_form)会重叠,我尝试了第二种方式。但是Rails随后停止识别Carrier插件文件夹中messages_controller.rb中写入的所有原始Carrier操作(#index,#show等),并开始将rails应用程序的messages_controller.rb版本视为唯一一个(所有原始操作都开始处理为空,因此开始通过 rails 约定的默认流程呈现)。

所以我的一般问题是: 如何在不将它们完全复制到 Rails 应用程序/控制器文件夹的情况下向 Rails 引擎控制器添加新操作?

UPD

现在我看到了两种解决方案,它们允许扩展引擎的控制器而不会造成严重的黑客攻击(就像这个 gem 所做的那样:https://github.com/asee/mixable_engines 来自这个线程:Extending controllers of a Rails 3 Engine in the main app

1) 加载 YourEngine::Engine.config.root + 'app' + 'controllers' + 'your_controller' 在 #{main_app}/app/controller/your_engine 文件夹中的 your_controller.rb 中。注意 load 而不是 require。

2)设计方式(根据一些SO主题建议): 在主应用程序中创建新控制器,将引擎的 one + 编辑路由子类化以指向这个新控制器。

我仍然确信存在一些更好的解决方案。如果他们这样做,请纠正我!

【问题讨论】:

  • 这可能是命名空间问题吗?只是猜测,但如果 R​​uby 在 Rails 应用程序命名空间中看到 MessagesController 对象,它将用于该命名空间中的任何方法调用。

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


【解决方案1】:

您的选项 2) 很好,因为它可以让您无缝升级 gem。

您当前的方式只是覆盖现有的控制器。

说你想扩展FooController

  1. 在初始化程序文件夹中创建一个名为 foo_controller_decorator.rb 的文件

  2. 在文件中:

FooController.class_eval do
  #your additionnal code here.
end

【讨论】:

  • 感谢您的回答。我知道我可以这样做。我只是想知道为什么它被覆盖,因为这可以在设计中完成 - github.com/plataformatec/devise/wiki/…? (仅覆盖一项操作)
  • 在这种情况下,您的应用定义了 ApplicationController 并且其中包含一些操作,除非您已经定义它。
  • 要使用相同的逻辑,请使用您的附加操作创建一个模块并将其包含在所需的控制器中
  • 是的,你是对的。现在我明白我对设计的引用是无关紧要的。然而,主题问题保持不变。
【解决方案2】:

我知道这是一个非常古老的问题,但如果其他人发现这个问题,这里有一个很好的装饰器的宝石。它与 Rails ActiveSupport 挂钩,并添加了一个约定来做装饰器,使其免受循环依赖的影响。一段时间以来,我们一直在多个应用的​​生产环境中使用它。

https://github.com/EPI-USE-Labs/activesupport-decorators

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 2016-02-13
    • 2012-01-05
    • 2015-01-22
    相关资源
    最近更新 更多