4

我正在开发名为Carrier的Rails插件(它是3.1引擎)(https://github.com/stanislaw/carrier)。如何正确地扩展Rails Engine的控制器?

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

两个策略我在这里看到:

1)我复制{运营商的插件根} /app/controllers/carrier/messages_controller.rb文件,应用程序/控制器/载波/我的应用程序的文件夹,然后扩展它(所有插件的原始操作都被复制到rails应用程序控制器文件夹!)。

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

期待这两个控制器的内容(原始插件的文件夹+自定义在我的Rails应用程序只有新的#comment_form)将叠加,我试过第二种方式。但Rails停止识别载体插件文件夹中的messages_controller.rb中所有原始载体的操作(#index,#show等...),并开始将rails应用程序的messages_controller.rb版本视为唯一(所有原始操作开始处理作为空的,因此开始通过轨道约定默认流程呈现)。

所以我的问题一般是: 如何添加新的动作到Rails引擎控制器,而不是完全复制到Rails应用程序/控制器文件夹?

UPD

现在我看到了两个解决方案,允许发动机控制器的扩展而没有严重的黑客(喜欢这种宝石的作用:https://github.com/asee/mixable_engines从这个线程:Extending controllers of a Rails 3 Engine in the main app

1)负载YourEngine ::引擎.config.root +'app'+'controllers'+'your_controller' 位于#{main_app}/app/controller/your_engine文件夹中的your_controller.rb中。注意加载而不是要求。

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

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

+0

可能这是一个命名空间问题?只是猜测,但是如果Ruby在Rails应用程序名称空间中看到MessagesController对象,它将使用该名称空间中的任何方法调用。 – coreyward

回答

4

你的选择2)很好,因为它可以让你无缝升级宝石。

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

假设您想延长FooController

  1. 创建一个在你的初始化文件夹

  2. 在文件名为foo_controller_decorator.rb文件:

FooController.class_eval do 
    #your additionnal code here. 
end 
+0

感谢您的回答。我知道我可以这样做。我只是想知道为什么它被覆盖,因为如何可以在设计中完成 - https://github.com/plataformatec/devise/wiki/How-To:-Change-the-redirect-path-after-destroying -a-会话即签约了呢? (仅覆盖一个动作) –

+0

在这种情况下,您的应用程序定义了ApplicationController,除非您已经定义了它,否则一些操作将包含在内部。 – apneadiving

+0

要使用相同的逻辑,请使用addtional操作创建一个模块并将其包含在所需的控制器中 – apneadiving

1

我知道这是一个非常古老的问题,但万一别人会发现这个问题,这是一个很好的装饰者的宝石。它挂钩到Rails的ActiveSupport中,并且增加了一个约定来处理从循环依赖中安全的装饰器。我们一段时间以来一直在多个应用程序中使用它。

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