Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Lessons:2Length:10 minutes
  • Overview
  • Transcript

1.2 Modularize Your App With Rails Engines

In this lesson, I’ll share some of my professional experience working on large applications with Rails Engines. I’ve used engines to modularize large applications, and also to create a plug-and-play interface for similar functionality. I’ll show you how to do the same for your own applications.

Related Links

1.Modularize Your App With Rails Engines
2 lessons, 10:07

Free Lesson

Modularize Your App With Rails Engines

1.2 Modularize Your App With Rails Engines

[MUSIC] You probably have seen this already. A project starts out as an innocent Rails app. And over time, the numbers of models and controllers grow and grow. It becomes hard to find anything in the project and running your test suite seems to take ages. Congratulations you have created a monolith, that is difficult to maintain and slow to test. Don't worry that doesn't mean you're a bad programmer or system architect. This just happens during the natural evolution of a software system. Welcome to the Coffee Break Course Model Services with Rails engine. I'm Markus Mühlberger and in this course we have a look on how to make your big applications more manageable with rails engines. Here I have a great example of a monolithic app this course. It has about seventy controls, hundred and forty models, and twenty services. Not only that there is a complete Ember Chair application inside the Assets JavaScript folder. Another good example for a big raise app is GitLab, which is a bit more organized within modules, but huge nonetheless. Sometimes it's okay to do so. For instance when you're distributing the software to the general public like those applications do. Nowadays one way to refactor is to turn decision to microservices. Those are very much in style right now. The concept is that you take one part of your application, like user management or image processing, and put it into it's own little application. Other microservices can then access an API provided by the service and use its data. But microservices are quite complicated, need a lot of infrastructure and planning, so you might think you are not ready for them yet. Using Rails engines however, you can simplify arrays up significantly. In the end it's still a monolith, but during development you have all those engines you can develop and test separately and just add them to your main application as a Gem. You only thing you have to do is find pieces of code that belong together and are well isolated from other parts of the application, but normally you won't have too many problems finding them. I have two examples I want to show you on how you can use Rails engines to make your application modular and maintainable. The first one is what I would call the classical use of engines to modularize your app. It describes the refactoring I mentioned before. Here I have a task administration module. It was extracted from the main application. It looks quite similar to a regular arrays app of controllers, models, and fuse. They include the engine and the main app. You just have to add a line to your chain file, using the path option. Of course, extracting the engine into a completely separate gem of its own git repository will also be a possibility. You can use the engine within your app by prepending the correct module on namespace. In our case, it is task on the school administration. As you can see in the side navigation file it also has its own routes. Those routes are defined like what you would do in a regular Rails app. The controllers are grouped in a module. The engine has its own application controller, which inherits from the main application controller. Having a Rails engine doesn't mean that you can't access anything within it. It is perfectly okay to create references between models of the main application and of an engine. Okay let's create such an engine. The command for generating an engine is rails plugin new. It has almost the same options you get when you initialize Rails app. Two important options though are full and mountable. A full engine means that you will generate a bundled Rails application, but don't use an isolate name space. So your engine still has access to all the controllers, models, and helpers from the main application. Our task administration module is exactly that. A mountable engine is a full engine, but isolates itself from the main application. You will need to mount the engine to a path whithin your main routes file. Examples for that are often up interfaces for gems like the sidekick. So to create a new engine you're going to write, rails plugin new, and then the path to your module. I'm choosing something like waste management stick with the general theme of the application. Then you have to specify the options either full, or what I'm using here, mountable. If you are not sure which you want experiment with an example and see which components you have access to in both versions. When we look at the project in the editor, we can see the new engine was created alongside the others. In the gems spec, you can change the gems name and also add dependencies between engines. By instance if you have a common module. Last thing to do is to add it to your main gem file with the path option. When you run bundle install you can see the local gems on the bottom. I have another interesting use of phrase engines to create a modular and extensible application. Here I have a basic Rails engine, not a full one, that only has a lib folder. It contains the basic definition of a sport in a tournament management system I'm currently working on. It defines how to register itself with the main application and how to do basic score calculation. Now I change to a specific sport, like Dodgeball. It inherents from the base sport and customizes the calculations according to the rules of the game. This is now a full engine it contains two major parts. One is the implementation of the logic interface it gets called by the main application and does these calculations. The other is the presentation layer. Every sport has different ways to count and display results. For dodgeball there are just two teams with a simple X versus Y score. While for example features three teams with a much more complicated scoring system. Now I will show you how I integrated those sports into the main application. Here I have a method, it prepares results for this play. It selects the tournament sport, which returns the Ruby class, or this very specific one, and calls methods on it that are defined by our designed interface. A similar way is used during the view rendering. We are rendering a partial view that is name space with the sports identifier within the gem. This allows us to support another sport very easily. With minimal changes to the main application and also keeps the test since we are expecting an interface not a real implementation that has to be tested for every spot every time. So, when you are confronted with a large Rails app again and get more and more frustrated by the vast amount of files and slow tests, try using Rails engines to modularize your big application into smaller bits.

Back to the top