Rails Engine - Modular Rails
Quick overview of Rails engines
Engines are small Rails applications that can be used to add functionalities to the application hosting them. The class defining a Ruby on Rails application is Rails::Application which actually inherits a lot of its behavior from Rails::Engine, the class defining an engine. We can say that a regular Rails application is simply an engine with more features.
Create a modular app
Section titled “Create a modular app”First, let’s generate a new Ruby on Rails application:
rails new ModularTodoThe next step is to generate an engine!
cd ModularTodo && rails plugin new todo --mountableWe will also create an ‘engines’ folder to store the engines (even if we just have one!).
mkdir engines && mv todo ./enginesEngines, just like gems, come with a gemspec file. Let’s put some real values to avoid warnings.
$:.push File.expand_path("../lib", __FILE__)
#Maintain your gem's version:require "todo/version"
#Describe your gem and declare its dependencies:Gem::Specification.new do |s| s.name = "todo" s.version = Todo::VERSION s.authors = ["Thibault Denizet"] s.email = ["bo@samurails.com"] s.homepage = "//samurails.com" s.summary = "Todo Module" s.description = "Todo Module for Modular Rails article" s.license = "MIT"
#Moar stuff #...end
Now we need to add the Todo engine to the parent application Gemfile.
#ModularTodo/Gemfile#Other gemsgem 'todo', path: 'engines/todo'Let’s run bundle install. You should see the following in the list of gems:
Using todo 0.0.1 from source at engines/todoGreat, our Todo engine is loaded correctly! Before we start coding, we have one last thing to do: mount the Todo engine. We can do that in the routes.rb file in the parent app.
Rails.application.routes.draw do mount Todo::Engine => "/", as: 'todo'endWe are mounting it at / but we could also make it accessible at /todo. Since we have only one module, / is fine.
Now you can fire up your server and check it in your browser. You should see the default Rails view because we didn’t define any controllers/views yet. Let’s do that now!
Building the Todo list
Section titled “Building the Todo list”We are going to scaffold a model named Task inside the Todo module but to correctly migrate the database from the parent application, we need to add a small initializer to the engine.rb file.
module Todo class Engine < ::Rails::Engine isolate_namespace Todo
initializer :append_migrations do |app| unless app.root.to_s.match(root.to_s) config.paths["db/migrate"].expanded.each do |p| app.config.paths["db/migrate"] << p end end end
endendThat’s it, now when we run migrations from the parent application, the migrations in the Todo engine will be loaded too.
Let’s create the Task model. The scaffold command needs to be run from the engine folder.
cd engines/todo && rails g scaffold Task title:string content:textRun the migrations from the parent folder:
rake db:migrateNow, we just need to define the root route inside the Todo engine:
Todo::Engine.routes.draw do resources :tasks root 'tasks#index'endYou can play with it, create tasks, delete them… Oh wait, the delete is not working! Why?! Well, it seems JQuery is not loaded, so let’s add it to the application.js file inside the engine!
//= require jquery//= require jquery_ujs//= require_tree .Yay, now we can destroy tasks!
Syntax
Section titled “Syntax”- rails plugin new my_module —mountable