Engines for dummies24th October 2022
During my research to write this post I noticed that Engines in Rails are a little known tool, even by experienced developers in large companies. And although you might think that it is because they don't need them, I think they don't use them because they are unaware of their existence.
Using an example from everyday life, you could fix a lot of things with a hammer, but that doesn't mean it's always the right way. Let's suppose that you have to screw something but you only know hammers, how will you know that the best way to do it is using a screwdriver if you don't know that they exist?
“Tools amplify your talent. The better your tools, and the better you know how to use them, the more productive you can be.”
― Andrew Hunt, The Pragmatic Programmer: From Journeyman to Master
I realized that if you want to improve your programming skills, you should always be aware of the tools you have at your disposal to facilitate your work and do it in the best possible way.
It is for this reason that in this article I am going to explain the basics of the Engines in Rails, so you can increase your repertoire of tools, you do not need to master them, I just want you to know that they exist and how you can use them.
What is an Engine in Rails?
It's a miniature Rails app that adds specific functionality to your main app in the form of a gem.
So we could say that an engine is similar to a rails app, but different.
Rails::Applications vs Rails::Engine
Both have a similar structure with Rails entities (controllers, models, view, etc) but unlike a common rails app, the engines are intended to have a single very specific functionality.
Engines are implemented with namespace for ease of use and to avoid collisions with your main application's classes, this creates folders with your engine's name inside the classic Rails folders and wraps the classes inside a module. Some examples are:
You have a directory that a common Rails app doesn't have, it's the Dummy! Yes, that's where the title of the article comes from.
The dummy is a rails app inside your engine, it allows you to test the functionality of your engine internally.
The engines are gems, so they have a
.gemspec file that is the "Gemfile" of your engine, all the gems you need for your engine go here in addition to the specs.
The usual Gemfile is also present, but in this case this is where the gems you want to use in your Dummy app go.
Gem === engine => false
Is a gem and an engine the same? No!
Unlike an engine, a gem can offer functionality without being a Rails App.
Both have things in common, the gemspec file, they can be published in ruby gems among other things, but the most important difference is that for a gem using ruby is enough, while an engine must have the Rails entities: controllers, models, views, migrations, etc.
"All engines can be gems, but not all gems are engines."
Thibault, Gems vs Engines: Know the difference
Everything looks nice, but why do I want an engine?
An engine is a tool that Rails provides us, and like any tool, using it makes life easier. Engines have many benefits, some of which are:
- It increases the speed of development, by allowing you to encapsulate specific functionality and reduce the scope. You can have a dedicated team working on your engine code without affecting your host application while they develop it.
- It facilitates the maintenance of the code. Since it works like a gem, you can have a single engine implemented in multiple projects (hosts) and if you require changes, you only make them in one place but they are applied in all the projects.
- The code is reusable, engines are gems, it is possible to share the code, so you can implement the functionality of the engine in your project without the need to have its files present in your app.
They need a host
Something to consider about engines is that they don't work by themselves, they need to be mounted on a Rails app (host app) to work.
If you think about it, it would be weird to use them by themselves. Using the Devise example, why would you need to have authentication functionality if you don't have any website to access? You need a host app to make sense to use an engine!
You've probably used engines and didn't know it!
A very common example of an engine is Devise. If you are a Ruby on Rails developer you have surely heard of it and most likely you have used it at least once.
Devise allows you to implement authentication for your App without the need to code it yourself, you only need to install the gem in your project, do a little configuration and you have the functionality ready! This is the value and power of engines!
How to create an engine?
You just need the following command
--mountable option creates a mountable engine. The structure is generated similar to a rails app but adds unique characteristics of an engine such as namespace through modules, the
.gemspec file, and also mounts the engine in the dummy routes.
How to use an engine in my Rails application?
Like any gem, you must add it in the Gemfile, although depending on the location of your engine there are different ways to do it.
Once installed in your Gemfile, it is necessary to mount it in the routes of your project to have the engine routes available. This is done in
config/routes.rb by prefixing the word
mount followed by the name of your engine and the subpath, which you can give an alias, for example
config/routes.rb file should look like this:
This example mounts the engine to
And you can access in the route: http://localhost:3000/login
One of the benefits of using engines as I mentioned before is that you have its functionality available without the need to have the files present, but despite the fact that it may seem like a limitation if you need to adapt an engine to your project, in fact you can do it in a very simple way!
To modify views and classes it is necessary to create the file with the same name in the same path that it originally has in the engine.
Depending on the engine, the creation of these files can be done manually or automatically, some engines have a rake task that does it with commands.
This is an example of a Devise rake task, which generates the files needed to modify the default views.
If you are creating your own engine you can create your own rake tasks.
Design your own views
To override views it is enough to have the files present in your project. This works because of the way Rails decides which files to use, it first looks for the file in your own project and if it doesn't find it then that's when it goes to the engines folders:
“When Rails looks for a view to render, it will first look in the app/views directory of the application. If it cannot find the view there, it will check in the app/views directories of all engines that have this directory.”
Rails Guides, Getting Started with Engines
Open engine classes
To open controller or model classes, you also need to have the file present in your project with the same name and in the same path that it originally has in the engine.
Inside the class you can use
class_eval to override the engine code.
Long story short
- Engines are mini Rails apps in gem form.
- An engine is used to encapsulate functionalities to be implemented easily and quickly in multiple projects.
- An engine doesn't work by itself, it needs a host.
- The dummy is an internal Rails app for testing your engine.
- You don't need the engine files in your app, but you can easily customize them.
In conclusion, engines are a tool that Rails provides us with. Knowing that they exist and what they do can will help us facilitate development and maintenance of specific functionalities.