Understanding Railtie and Mountable Rails Engine

8 March 2016 by Chandan Jhunjhunwal No comments

In earlier versions(Before 3.0) of Rails, we used to build plugins to add new functionality to our application. This would result in a lot of problems during up-gradation of any of the gem/dependencies or Ruby/Rails version. From Rails 3.0, Rails Engine were introduced to prevent these issues. Plugins were deprecated in Rails 4.0.Rails Engine is basically Railtie with some configurations. Before we dive into Rails Engine, let’s understand Railtie first. As per Rails API Doc: Railtie is the core of the Rails framework and provides several hooks to extend Rails and/or modify the initialization process. Every major component of Rails (Action Mailer, Action Controller, Action View and Active Record) is a Railtie. Each of them is responsible for their own initialization. This makes Rails itself absent of any component hooks, allowing other components to be used in place of any of the Rails defaults. Developing a Rails extension does not require any implementation of Railtie, but if you need to interact with the Rails framework during or after boot, then Railtie is needed.

Railtie is the core of the Rails framework and provides several hooks to extend Rails and/or modify the initialization process. Every major component of Rails (Action Mailer, Action Controller, Action View and Active Record) is a Railtie. Each of them is responsible for their own initialization. This makes Rails itself absent of any component hooks, allowing other components to be used in place of any of the Rails defaults. Developing a Rails extension does not require any implementation of Railtie, but if you need to interact with the Rails framework during or after boot, then Railtie is needed.To put in simple words, Railtie is an abstract class, which must be subclassed. It follows Class Based Design (Singleton) pattern. It is responsible for:

To put in simple words, Railtie is an abstract class, which must be subclassed. It follows Class Based Design (Singleton) pattern. It is responsible for:

1. Gluing the components to bootstrap Rails application.
2. Provides rails command line interface and core generator.
3. Provides a way to configure the application components(i.e. instance of subclasses)

The following code snippet from railtie.rb will make it’s function even clearer.

Now, we have understood Railtie, Rails:: Engine nothing more than a Railtie with few configurations set. As a matter of fact, Rails:: Application is also a Rails:: Engine.Let’s say, we want to build two application with similar functionality. One way to do this, to create two application with writing the same code for both applications. But that’s not Rails way. Rails go a mile further to make codes DRY. The better way to do this is to create Rails:: Engine and mount it in both applications. Few really popular examples of Rails:: Engine are: Devise, Spree etc.

Rails:: Engine can be created using the following command:

 ○ ➜ rails plugin new sample_engine --mountable 

It also creates an isolated namespace, so that there is no conflict between core application and Rails:: Engine. i.e. your application can have ‘Users’ model defined as well as your engine. Another option available for Rails:: Engine is –full. 

The above command will generate a number of directory/files similar to Rails new application. An engine can’t run without a Rails application, thus, the –mountable option creates a test/dummy application to run it.

Most of the details to create Rails:: Engine can be found at Rails EdgeGuide. So I’ll skip the steps to create/integrate Rails:: Engine with any Rails application.

Above Rails:: Engine can be mounted on any rails application by adding following route in routes.rb:

Rails.application.routes.draw do
  mount SampleApp::Engine => '/sample_app', as: 'admin'
end

Let’s analyze how mount of Rails:: Engine works. ActionDispatch::Routing is responsible for mapping the requests to appropriate controller/actions, which in turn is a part of ActionPack.

Below is the snippet of mapper.rb file under ActionDispatch::Routing::Mapper::Base

It’s important to keep in mind that the application should ALWAYS take precedence over its Rails::Engines. A Rails::Engine should be used only to enhance the application instead of changing it completely.

Chandan Jhunjhunwal

Follow me on Twitter

Subscribe To Our Blog

Get access to proven marketing ideas, latest trends and best practices.

Next up home

Contact

Lets build cool stuff

Share your contact information & we will get in touch!

I want (Tell us more about your dream project)