Mountable Engines

Episode #79 by Teacher's Avatar David Kimura

Summary

Mountable Engines are a great way to extract code into its own namespace and allow the code to be reused in other applications. Other popular gems that are mountable engines are Devise and Doorkeeper.
rails view gem engine 9:23

Resources

Summary

# Terminal
rails plugin new books_module --mountable

# test/dummy/config/routes.rb
Rails.application.routes.draw do
  resources :users
  mount BooksModule::Engine => "/books_module", as: :books_engine
  root to: 'users#index'
end

# Terminal
cd test/dummy
rails g scaffold users first_name last_name
rake db:migrate

cd ../..
rails g scaffold books name year:date
rake db:migrate

rails g migration add_book_id_to_users book_id:integer:index
rake db:migrate

rake books_module:install:migrations

# test/dummy/app/views/users/index.html.erb
<%= link_to 'Books', books_engine.books_path %>

# app/views/books/index.html
<%= link_to 'Users', main_app.users_path %>

# lib/books_module.rb
require "books_module/engine"

module BooksModule
  require_relative 'books_module/model.rb'
end

# lib/books_module/model.rb
require_relative 'models/user.rb'

# lib/books_module/models/user.rb
module BooksModule
  module UserModel
    extend ActiveSupport::Concern
    included do
      belongs_to :book, class_name: 'BooksModule::Book', optional: true

      def has_favorite_book?
        book.present?
      end
    end
  end
end

# lib/test/dummy/app/models/user.rb
class User < ApplicationRecord
  # belongs_to :book, class_name: 'BooksModule::Book', optional: true

  # def has_favorite_book?
  #   book.present?
  # end
  include BooksModule::UserModel
end

# app/models/books_module/book.rb
module BooksModule
  class Book < ApplicationRecord
    has_many :users
  end
end

# test/dummy/app/views/users/_form.html.erb
    <%= form.label :book_id %>
    <%= form.collection_select :book_id, BooksModule::Book.all, :id, :name, include_blank: true %>

# test/dummy/app/controllers/uesrs_controller.rb
    private
    ...
    def user_params
      params.require(:user).permit(:first_name, :last_name, :book_id)
    end