【发布时间】: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 + 编辑路由子类化以指向这个新控制器。
我仍然确信存在一些更好的解决方案。如果他们这样做,请纠正我!
【问题讨论】:
-
这可能是命名空间问题吗?只是猜测,但如果 Ruby 在 Rails 应用程序命名空间中看到 MessagesController 对象,它将用于该命名空间中的任何方法调用。
标签: ruby-on-rails ruby-on-rails-3.1 ruby-on-rails-plugins rails-engines