We'll respond shortly.
On the project I’m currently working on we have a main portal that provides a user registration system and a generic billing mechanism. It also has several sub applications which need to know some information about the user and be able to publish billing events. With a fairly easy to articulate boundary, we thought it might make sense to be deliberate in how we organized our code – we came up with three main solutions:
Our Boulder office had been making some noise about Rails Mountable Engines for some time, gave a presentation in the SF office, and I had experience working with engines both in the dark times of engines in Rails 2.x and the markedly improved days of Rails 3.x, and even better still in 3.1+. We had need to scale one sub-component of one of the applications independently, but not entire apps as the primary usage of the system would be low-volume. We set off down the engines path…
It worked pretty well. Two months in to the project we had a retrospective specifically about how engines were working. We agreed that we had felt some pain, but overall they drove out interesting decoupling and that the cost to pull them out could potentially outweigh the little pain we might encounter in the future.
Then our team size doubled. We had multiple epics that had high priority and deadlines associated with them. We also needed to ramp up four new people which led me to reassess our choice of engines once again, not to mention that we eventually will be handing over the code to developers who haven’t seen much Rails.
The conclusion I came to was that engines had to go. Here’s the list of why:
None of this was impossible, or even difficult to solve. It’s just that it wasn’t intuitive, not what a well seasoned Rails developer was expecting out of the box. It would have been a waste of our client’s time to bring a whole new team up to speed on all that we had learned about engines, rather than having one big application.
This is especially true since the only semi-real-payoff was that it made us isolate our sub-application code from the portal code. I say “semi-real” because the boundary was artificial – the reality was that the sub applications needed to know about the user and his account, and anything we built out for billing was really a dependency of each of the apps. This was different from a great engine like rails_admin that really is a drop in and has no domain-specific dependencies. Here we had nothing but domain-specific dependencies and now, by removing engines, our code and our domain are back where they belong: together.
Engines really are great and there’s lots of situations where they can be really powerful. Boulder Pivot, Stephan Hagemann, had these additional tips that I wanted to share with you.
Regarding RubyMine and running specs: there is a simple way to make RubyMine run all specs in all engines. It will make all engines modules with their own “RubMine root”, which fixes spec runs. http://blog.pivotal.io/users/shagemann/blog/articles/intellij-modules-in-rubymine-
Regarding migration duplication: You can have an engine or app that requires others run their migrations. Check out the migrations run by the main app in this sample app: https://github.com/shageman/the_next_big_thing
Regarding testing: If an engine is relying on some layout or style to be around, it should depend on it and include it (potentially by way of another engine).