How to properly distribute Rails Engine controllers?

I am developing a Rails plugin (this is 3.1 Engine) called Carrier ( https://github.com/stanislaw/carrier ).

In one of my rails applications, I want to extend the Carrier controller with several new methods - fx. add a new #comment_form action to Carrier :: MessagesController (I want this action to exist only in my application - I don't want to add it to Engine because it is very specific).

Two strategies that I see here:

1) I copy the file {Carrier plugin root} /app/controllers/carrier/messages_controller.rb to the application / controllers / operator / folder of my application, and then expand it (all the original actions of the plugin are copied to the application controllers rails folder too!).

2) A more accurate way I want is to simply create {My rails app} /app/controllers/carrier/messages_controller.rb and write only the #comment_form method. I want Carrier to be expanded.

Expecting that the two contents of the controllers (the original from the plugins folder + user in my rails application, having only the new #comment_form) will overlap, I tried the second option. But Rails then stopped recognizing all the original Carrier actions (#index, #show, etc.) written in messages_controller.rb from the Carrier plugin folder, and began to consider the rails app messages_controller.rb version as the only one (all initial actions began to be processed as empty and, thus, began to appear on standard rails legend flows).

So my overall question is: How do I add new actions to Rails Engines controllers without completely copying them to the Rails application / controller folder?

UPD

At the moment, I see two solutions that allow you to expand engine controllers without serious hacks (for example, this pearl does: https://github.com/asee/mixable_engines from this topic: Extending Rails 3 Engine controllers in the main application )

1) load YourEngine :: Engine.config.root + 'application' + 'controllers' + 'your_controller' inside your_controller.rb, which is located in the folder # {main_app} / app / controller / your_engine. Pay attention to the download instead of the required one.

2) Imagine a way (according to some topics): In the main application, create a new controller that subclasses the one + edit routes engine to point to this new controller.

I am still sure that there are even better solutions. Please correct me if they do!

+4
source share
2 answers

Your option 2) is good because it will allow you to easily upgrade your gem.

Your current method simply overrides the existing controller.

Suppose you want to extend the FooController .

  • Create a file called foo_controller_decorator.rb in the initialization folder

  • In file:

 FooController.class_eval do #your additionnal code here. end 
+4
source

I know this is a very old question, but if someone finds this question, here is a stone that decorators do great. It connects to Rails ActiveSupport and adds a decorator convention that is safe from circular dependencies. We used it in production in several applications for a while.

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

+1
source

All Articles