Rails Engines are an architectural pattern that can be used to modularize a Rails application. They are self-contained applications that can be mounted within a larger Rails application. In this post, we will dive into the world of Rails Engines and explore what they are, how to create them, how to use them, when to use them, and why they are important.

What are Rails Engines?

Rails Engines are essentially mini-applications that can be plugged into a larger Rails application. They allow you to modularize your code and keep it separate from the core application. This makes it easier to maintain and update the codebase as a whole.

Engines can include models, controllers, views, and assets, and they can also have their own routes and configurations. For example Devise
opens a new window
, an engine that provides authentication for a host application, has its own views, controllers, routes and configurations.

It is worth mentioning that Rails Engines are similar to Railities
opens a new window
. However, they differ in that Railities are simple Ruby modules that includes various hooks into the Rails initialization process, such as configuring middleware or adding new generators, whereas a Rails Engine has a more complex directory structure and includes everything needed to function as a standalone application, such as controllers, models, and views.

How to Create a Rails Engine

Creating a Rails engine is a relatively simple process. To create a new engine, run the following command in the terminal:

rails plugin new payments --mountable

This will create a new Rails engine in the payments directory with the --mountable option, which means that the engine can be mounted within another Rails application. Please note that the --mountable option is very important as running the above command without it will create a typical plugin which is not mountable. Below are the files generated by the above command:

$ bin/rails plugin new payments --mountable
      create  
      create  README.md
      create  Rakefile
      create  payments.gemspec
      create  .gitignore
      create  Gemfile
         run  git init from "."
Initialized empty Git repository in /ombulabs.com/payments/.git/
      create  app
      create  app/controllers/payments/application_controller.rb
      create  app/helpers/payments/application_helper.rb
      create  app/jobs/payments/application_job.rb
      create  app/mailers/payments/application_mailer.rb
      create  app/models/payments/application_record.rb
      create  app/views/layouts/payments/application.html.erb
      create  app/assets/images/payments
      create  app/assets/images/payments/.keep
      create  app/models/concerns
      create  app/models/concerns/.keep
      create  app/controllers/concerns
      create  app/controllers/concerns/.keep
      create  config/routes.rb
      create  lib/payments.rb
      create  lib/tasks/payments_tasks.rake
      create  lib/payments/version.rb
      create  lib/payments/engine.rb
      create  app/assets/config/payments_manifest.js
      create  app/assets/stylesheets/payments/application.css
      create  bin/rails
      create  test/test_helper.rb
      create  test/payments_test.rb
      create  test/fixtures/files
      create  test/fixtures/files/.keep
      create  test/controllers
      create  test/controllers/.keep
      create  test/mailers
      create  test/mailers/.keep
      create  test/models
      create  test/models/.keep
      create  test/integration
      create  test/integration/.keep
      create  test/helpers
      create  test/helpers/.keep
      create  test/integration/navigation_test.rb
  vendor_app  test/dummy
      append  /ombulabs.com/Gemfile

Once you have created your engine, you can add models, controllers, views, and assets just like you would in a regular Rails application. You can also define your own routes and configurations within the engine.

How to Use Rails Engines

Using a Rails Engine is also straightforward. The engine needs to be specified inside the Gemfile and run bundle install:

gem 'payments', path: 'payments'

To make our Payments engine’s functionality accessible from within our application, we need to mount it in the host application’s config/routes.rb file. However, it is not always the case as we can use the engine functionality without mounting it:

mount Payments::Engine, at: "/payments"

This will mount our Payments engine at the specified path within your application. You can now use the models, controllers, views, and assets from the engine just like you would in a regular Rails application.

When to Use Rails Engines

Rails Engines are particularly useful when you want to modularize your codebase and keep it separate from the core application. This is especially helpful when you are working on a large project with multiple developers, as it allows you to separate responsibilities and avoid conflicts.

Engines can also be used to create reusable components that can be shared across multiple applications. For example, in an e-commerce context, you could use Rails Engines to build separate modules for different aspects of the site, such as product catalog, shopping cart, payment gateway, and order management.

Each module could be developed and tested independently and then mounted within the main Rails application. This approach would allow you to scale each module independently as needed, and also make it easier to reuse the code across different e-commerce sites.

Why Rails Engines are Important

Rails Engines are important because they provide a modular way to organize and share code within a larger Rails application. Here are a few key benefits of using Rails engines:

  • Code Reuse: Rails engines allow you to extract reusable code into separate modules, making it easier to share code across multiple projects. This can save time and effort in development, as you can develop and test functionality once and then reuse it in different contexts.

  • Modularity: By breaking up your Rails application into smaller, self-contained modules, you can make your codebase more manageable and easier to maintain. Each engine can be developed and tested independently, allowing you to focus on specific areas of functionality without worrying about breaking changes in the rest of the application.

  • Encapsulation: Engines provide a way to encapsulate functionality within a well-defined interface. This makes it easier to reason about the code and reduces the risk of introducing bugs or breaking changes in other parts of the application.

  • Scalability: Engines can be used to scale your application horizontally by allowing you to add or remove functionality as needed. This can help you to adapt your application to changing business requirements and user needs without having to make major changes to the overall architecture.

  • Customization: Rails engines can be customized to meet the specific needs of different projects or clients. This can be particularly useful in agency or consultancy contexts, where you may need to develop similar functionality across multiple projects but with slight variations in requirements.

By keeping your code organized and modularized, you can improve the overall quality and maintainability of your application.

Conclusion

In conclusion, Rails engines provide a powerful way to organize and share code within a larger Rails application. By breaking up your application into smaller, self-contained modules, you can make your codebase more manageable and easier to maintain. Engines allow you to extract reusable code, encapsulate functionality, and scale your application horizontally by adding or removing functionality as needed. Additionally, engines can be customized to meet the specific needs of different projects or clients.

While Rails engines may not be appropriate for every project or context, they can be a valuable tool for developers looking to create more modular, maintainable, and scalable applications. Whether you’re building an HR management system, an e-commerce site, or a content management system, Rails engines can help you to develop and reuse functionality in a more efficient and effective way.

For further reading you can go through the Rails guide for Engines
opens a new window
.

Need help modularising your Rails application? Contact us
opens a new window
and have the FastRuby.io experts
opens a new window
help you with it!

Read More