Как правильно расширить контроллеры Rails Engine?

Я разрабатываю плагин Rails (это движок 3.1) под названием Carrier (https://github.com/stanislaw/carrier< /а>).

В одном из моих приложений rails я хочу расширить контроллер Carrier некоторыми новыми методами — fx. добавить новое действие #comment_form в Carrier::MessagesController (я хочу, чтобы это действие существовало только в моем приложении — я не хочу добавлять его в Engine — потому что оно очень специфичное).

Здесь я вижу две стратегии:

1) Я копирую файл {корень плагина Carrier}/app/controllers/carrier/messages_controller.rb в папку app/controllers/carrier/ моего приложения, а затем расширяю его (все исходные действия плагина также копируются в папку контроллеров приложений rails! ).

2) Я хочу более точного способа - просто создать {My rails app}/app/controllers/carrier/messages_controller.rb и написать только метод #comment_form, который я хочу использовать для расширения Carrier.

Ожидая, что содержимое двух контроллеров (исходное из папки плагина + настраиваемое в моем приложении rails, имеющее только новый #comment_form) будет накладываться друг на друга, я попробовал второй способ. Но затем Rails перестал распознавать все исходные действия Carrier (#index, #show и т. д.), записанные в messages_controller.rb из папки плагина Carrier, и начал рассматривать версию messages_controller.rb приложения rails как единственную (все исходные действия начали обрабатываться как пустой и, таким образом, начал рендеринг через поток по умолчанию для соглашений о рельсах).

Итак, мой вопрос в целом: как добавить новые действия в контроллеры Rails Engines, не копируя их полностью в папку приложений/контроллеров Rails?

UPD

На данный момент я вижу два решения, которые позволяют расширять контроллеры движка без серьезных хаков (как это делает этот гем: https://github.com/asee/mixable_engines из этой темы: Расширение контроллеров движка Rails 3 в основном приложении)

1) загрузите YourEngine::Engine.config.root + 'app' + 'controllers' + 'your_controller' внутри your_controller.rb, который находится в папке #{main_app}/app/controller/your_engine. Обратите внимание на load вместо require.

2) Разработайте способ (согласно некоторым темам SO): в основном приложении создайте новый контроллер, который подклассифицирует один движок + отредактируйте маршруты, чтобы они указывали на этот новый контроллер.

Я все еще уверен, что существуют еще лучшие решения. Пожалуйста, поправьте меня, если они делают!


person Stanislav Pankevich    schedule 10.10.2011    source источник
comment
Может ли это быть проблемой пространства имен? Просто предположение, но если Ruby увидит объект MessagesController в пространстве имен вашего приложения Rails, он будет использовать его для любых вызовов методов в этом пространстве имен.   -  person coreyward    schedule 11.10.2011


Ответы (2)


Ваш вариант 2) хорош, потому что он позволит вам легко обновить драгоценный камень.

Ваш текущий способ просто переопределяет существующий контроллер.

Допустим, вы хотите расширить FooController.

  1. Создайте файл с именем foo_controller_decorator.rb в папке инициализатора.

  2. В файле:

FooController.class_eval do
  #your additionnal code here.
end
person apneadiving    schedule 10.10.2011
comment
Спасибо за ответ. Я знаю, что могу сделать это таким образом. Мне просто интересно, почему это переопределяется из-за того, как это можно было бы сделать в devise - github.com/plataformatec/devise/wiki/? (отменяет только одно действие) - person Stanislav Pankevich; 11.10.2011
comment
В этом случае ваше приложение определяет ApplicationController, и некоторые действия включены внутрь, если вы еще не определили его. - person apneadiving; 11.10.2011
comment
Чтобы использовать ту же логику, создайте модуль с вашим дополнительным действием и включите его в нужный контроллер. - person apneadiving; 11.10.2011
comment
Да, ты прав. Теперь я понимаю, что моя цитата из devise была неактуальна. Тем не менее, тема вопроса остается прежней. - person Stanislav Pankevich; 11.10.2011

Я знаю, что это очень старый вопрос, но на случай, если кто-то еще найдет этот вопрос, вот драгоценный камень, который прекрасно справляется с декораторами. Он подключается к Rails ActiveSupport и добавляет соглашение о создании декораторов, которое защищено от циклических зависимостей. Мы уже давно используем его в производстве в нескольких приложениях.

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

person Pierre Pretorius    schedule 01.07.2016