Ruby on Rails is a popular web framework known for rapid development backed by a great community. This post is intended to introduce and encourage you to build a more modular rails application. I maintain a collection of resources if you’d like to learn more.
Creating the Engine
Most applications require user authentication so I think that would be a great first engine to create. I’m going to walk you through the creation of
I’ll refer to our rails app as the host application.
rails new host_app --database postgresql
We will install Devise in our
ConnectBy engine. Let’s get started.
Generate the plugin
Our engines are installed locally in
/engines and gems in
/gems. Run the rails plugin generator from the host’s root.
(using whitespace for clarity)
Skip setting up
test_unit and create a dummy app that we will later use with rspec.
--skip-test --skip-system-test --dummy_path=spec/dummy
Our host app will dynamically load all of our engines.
Our frontend won’t live in our engine.
Add a rails-version file to our host app so each engine can reference it.
./host_app $ echo "188.8.131.52" > .rails-version
Update the gemspec
Load our engine in the host application’s gemfile.
# Gemfile Dir.glob(File.expand_path("../engines/*", __FILE__)).each do |path| gem File.basename(path), path: path end
Add devise to our engine’s gemfile.
# engines/connect_by/Gemfile gem "devise", "~> 4.7.1"
# engines/connect_by/lib/connect_by.rb require "connect_by/version" module ConnectBy end require "devise" require "connect_by/engine"
connect_by and our host.
./host_app $ bundle install
./host_app/engines/connect_by $ bundle install
Install devise and create our user model.
./host_app/engines/connect_by $ rails generate devise:install ./host_app/engines/connect_by $ rails generate devise user
Update our devise configuration.
# engines/connect_by/initializers/devise.rb config.parent_controller = 'ConnectBy::ApplicationController' config.router_name = :connect_by
Install our new migrations on the host application.
./host_app $ rails connect_by:install:migrations
Migrate your host app’s database.
./host_app $ rails db:create db:migrate
Mount our engine’s route in the host.
# config/routes.rb Rails.application.routes.draw do mount ConnectBy::Engine, at: "/a" end
We are creating an isolate namespaced engine so we need to tell devise that we are using their controllers in their
# engines/connect_by/config/routes.rb devise_for :users, class_name: "ConnectBy::User", module: :devise
I’ll drop the frontend from
ConnectBy to avoid taking away from the tutorial. Isolated frontends with Webpacker 4 can get very involved (How to use webpacker from within engines?).
Remove assets and view layouts from the engine.
./host_app/engines/connect_by $ rm -rf ./app/assets ./host_app/engines/connect_by $ rm -rf ./app/views/layouts
Start up the server and navigate to
/a/users/sign_in to confirm it worked.
We took a modular approach and created a rails engine for our user account’s.
The source code for this part is on github.
Part 2 focuses on setting up the test suite, specifically rspec.
- Part 1 - Create Your First Rails Engine
- Part 2 - Test Your First Rails Engine
- Part 3 - Configure Your First Rails Engine
I have compiled a list of useful resources for rails engines and the modular monolith architecture.
Scale With Rails Engines
Need help scaling your rails application with a modular monolith? Talk to us