我正在开发名为Carrier(https://github.com/stanislaw/carrier)的Rails插件(它是3.1引擎)。
在我的一个rails应用程序中,我想用一些新方法扩展Carrier的控制器 - fx。将新动作#comment_form添加到Carrier :: MessagesController(我希望此操作仅存在于我的应用程序中 - 我不想在引擎中添加它 - 因为它非常具体)。
我在这里看到两种策略:
1)我将{Carrier的插件root} /app/controllers/carrier/messages_controller.rb文件复制到我的应用程序的app / controllers / carrier /文件夹,然后扩展它(所有插件的原始操作都被复制到rails app controllers文件夹也是!)。
2)我想要的更准确的方法 - 只是创建{My rails app} /app/controllers/carrier/messages_controller.rb并且只写#comment_form方法我希望Carrier扩展。
期望两个控制器的内容(来自插件的文件夹中的原始文件+我的rails app中的自定义只有新的#comment_form)将叠加,我尝试了第二种方式。但是Rails然后停止识别Carrier插件文件夹中的messages_controller.rb中写的所有原始Carrier的操作(#index,#show等等),并开始将rails app的messages_controller.rb版本视为唯一的(所有原始操作都开始处理)为空,因此开始通过rails约定默认流程渲染。
所以我的问题一般是: 如何将新操作添加到Rails引擎控制器而不将它们完全复制到Rails app / controllers文件夹?
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内。注意加载而不是require。
2)设计方式(根据一些SO主题建议): 在主应用程序中创建新的控制器,子类引擎的一个+编辑路由指向这个新的控制器。
我仍然确定存在一些更好的解决方案。如果他们这样做,请纠正我!
答案 0 :(得分:4)
您的选项2)很好,因为它可以让您无缝升级宝石。
您当前的方式只是覆盖现有的控制器。
假设你想扩展FooController
。
在初始化文件夹
foo_controller_decorator.rb
的文件
在文件中:
FooController.class_eval do #your additionnal code here. end
答案 1 :(得分:1)
我知道这是一个非常古老的问题,但万一其他人发现了这个问题,这里有一个很好地装饰器的宝石。它挂钩到Rails ActiveSupport并添加一个约定来做装饰器,这是一个安全的循环依赖。我们已经在多个应用程序的生产中使用它了一段时间。