4

我正在开发名为 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 app controllers 文件夹! )。

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 app/controllers 文件夹的情况下向 Rails Engines 控制器添加新操作?

UPD

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

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

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

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

4

2 回答 2

5

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

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

说你想延长FooController.

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

  2. 在文件中:

FooController.class_eval do
  #your additionnal code here.
end
于 2011-10-10T23:19:14.307 回答
1

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

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

于 2016-07-01T15:20:26.870 回答