Rails Engines - Independent Heroes
Working with large Rails monolith applications can feel pretty obscure. Namespaces and Service Objects can be helpful. But sometimes that's not enough. Sometimes you need Rails engines.
If you have built a Rails application in the past, chances are that you used Rails engines already – maybe unknowingly. The well-known devise
gem, for example, is based on Rails engines. But what is it exactly? Well, simply put a Rails
engine is the miniature edition of a Rails application. It comes with an
app folder, including controllers, models, views, routes, migrations... The difference though is, that an
engine won't work on its own. To show what it's capable of, it needs to become part of something bigger - a part of a main Rails application.
THE POWER OF INDEPENDENCE
I can hear your question: if we still need a main application and an
engine is just a small edition of it, why do we need it in the first place?
Well, let me tell you of a van I bought a few years ago. A 1984 Volkswagen LT. Huge, kind of old, lots of adjustments made by more or less experienced former owners with a lack of documentation. Sounds familiar? This could be true for some larger applications as well.
When an app starts to grow, when it becomes huge, one can get confused. You are scared to touch file "A" because it is somehow related to file "S" and file "P". Maybe that's not even the case any longer! Maybe you don't need the file "S" any more. Fact is, bigger applications can drive you nuts easily. Wouldn't it be better, if you could separate some components? Wouldn't it be better if I could fix, test and improve the wires of my van without the need of the actual van? Or the motor? Sure, it would. And that's exactly why you might want to think about using Rails engines.
- You have a nice, clear structure where tasks are separated into different components
- You can and will test them on their own
- You can add and remove engines at will from/to your main application
But, same with everything in life, big decisions (outsourcing parts of a larger application into
engines is one of these decisions) come with a good portion of responsibility.
YOU'RE ALLOWED TO EAT ANYTHING BUT NOT TO KNOW EVERYTHING
engines it's the same as with that German phrase: they can include anything (controllers, models, gems, routes, migrations, ...) but they must not know about any behaviour of the main application.
What does that mean? Well, I told you about my van. Like any other car or van, it has a fuel system. This system should work. No matter if it's part of my van, your car or my Dads' bus. It should function totally independent and it should not care about the global picture – in this case, the car, van, bus. If it cared about it, yes, if it even would rely on the outer shell, what's the idea of having it separated in the first place? Why not creating a fuel system individually made for each car? Sure, that wouldn't make sense at all. And that's why it doesn't make sense for our
engines either. Use them as independent heroes for your main application, and don't mix up responsibilities.
Once you are aware of that, the next thing you want to take care of, is the testing part. Actually, it's kind of the same: you have an independent miniature application that should function on its own, 100% apart from any main application. So, the most obvious solution is testing it separately, right? Right. As the
engine shouldn't know about anything of the main application, stick to tests that are important to that
engine. That doesn't mean you shouldn't have tests that cover the integration of the
engine but these tests should sit inside the main application, not inside the
The first step is always the hardest. But let me give you some resources that will make it easier. For a good technical overview, I'd suggest following the official Rails engines tutorial. This shouldn't take too long as you already know what
engines are. You also can read about "component-based rails applications" as they use rails
engines quite often. Once you feel more confident and aren't afraid of a challenge, head over to decidim - The participatory democracy framework. It's an open-source application that is fully based on
engines. Fully means fully so it might feel a bit overwhelming at the beginning. But as it's open-source, you can see and use the whole code. There's also a detailed documentation included, so don't be afraid and give it a try!
And finally, if you want to know why decidim looks the way it looks like and why it's based on
engines, read the case study on: codegram - Bringing institutions and people closer together.
In case you have questions and/or suggestions, I'm happy to hear from you!