Rails Mountable Engine*

*plus some cat crazyness


Bartłomiej Skwira

Fakelook: https://www.facebook.com/bartlomiejskwira

I work in Amberbit

..and we make... oh.... that's the old logo ;)

*sth didn't work out

..again... I work in Amberbit

..and we make internetZ using: Ruby, Rails, Angular, CoffeeScript, HAML/Slim, SCSS etc...


Find us @ http://www.amberbit.com

Agenda:

  1. Waaaaat is it?
  2. How we can do that?
  3. Some innards
  4. ????????
  5. PROFIT

What is it?

  • A mini app that enhances a host app
  • ..so a plugin? => yeap
  • Examples: Devise, Rails (Engine on steroids!)
  • Requirements: Rails >= 3.1.0rc5
  • *Can be distributed as a gem

What can we do in the engine?

  • create controllers/models/views/helpers/mailers etc (namespace!)
  • generators work and namespace by default
  • customize engine's routes in config/routes.rb
  • add gem dependencies, assets, initializers, locales, rake tasks etc
  • TEST IT !
  • use rails console (in the dummy app :P) => namespace!

New feature in Rails 3.2.36 - judo cat

How


            $ rails plugin new brug --mountable
              create
              create  README.rdoc
              create  Rakefile
              create  brug.gemspec
              create  MIT-LICENSE
              create  .gitignore
              create  Gemfile
              create  app
              create  app/controllers/brug/application_controller.rb
              create  app/helpers/brug/application_helper.rb
              create  app/mailers
              create  app/models
              create  app/views/layouts/brug/application.html.erb
              create  app/assets/images/brug
              create  app/assets/images/brug/.keep
              create  config/routes.rb
              create  lib/brug.rb
              create  lib/tasks/brug_tasks.rake
              create  lib/brug/version.rb
              create  lib/brug/engine.rb
              create  app/assets/stylesheets/brug/application.css
              create  app/assets/javascripts/brug/application.js
              create  bin
              create  bin/rails
              create  test/test_helper.rb
              create  test/brug_test.rb
              append  Rakefile
              create  test/integration/navigation_test.rb
            vendor_app  test/dummy
                 run  bundle install
          

What did we get?

Namespaces, namespaces everywhere !!!1


            module Brug
              class ApplicationController < ActionController::Base
              end
            end

            #also assets
          

engine.rb - add configs here


            module Brug
              class Engine < ::Rails::Engine
                isolate_namespace Brug
              end
            end
          

Testing?


A dummy Rails App

*Inception FTW!

RSpec + FactoryGirl


            $ rails plugin new brug -T --mountable --full --dummy-path=spec/test_app
            #T - skip Test::Unit
            #--full tells the generator that you want app and config directories

            #Gemfile
            source "http://rubygems.org"
            gemspec
            gem "rspec-rails", "~> 2.12.2"
            gem "factory_girl_rails", "~> 4.0"

            #engine.rb
            module Brug
              class Engine < ::Rails::Engine
                isolate_namespace GemName

                config.generators do |g|
                  g.test_framework :rspec
                  g.fixture_replacement :factory_girl, :dir => 'spec/factories'
                end
              end
            end

            $rails generate rspec:install
          

Mounting the engine in routes.rb


            #brug/test/dummy/config/routes.rb
            Rails.application.routes.draw do

              mount Brug::Engine => "/brug" #any path here

              #add this line to README of your engine/gem
            end
          

Migrations

In the engine:

            $ rake db:migrate
          
In the mounting app:

            #migrations are copied to the app
            $ rake brug:install:migrations
          
Load seed data

            Brug::Engine.load_seed
          

Routing....

...The Cat Way

Routing....

...The Mountable Engine Way
In the Engine

            #engine path
            root_url
            #mounting app path
            main_app.root_url
          
In the mounting app:

            #config/routes.rb
            mount Brug::Engine => "/brug", as: 'brug_engine'

            brug_engine.root_url
          

Hooking the engine in the app....

...The Cat Way

Hooking the engine in the app....

...The Mountable Engine Way

Locally


            #Gemfile
            gem 'brug', path: "/workspace/.../hidden_porn_dir/.../brug
            #run bundle install

            #routes.rb
            mount Brug::Engine => "/brug"
          

Other goodnes we can do?

  • use a model/controller provided by the app
  • make the used model configurable => use mattr_acessor
  • override models, views and controllers
  • add gem dependencies via .gemspec

Haml? sure!


            #engine.rb
            config.generators.do |g|
               g.template_engine :haml
            end
          

Middleware stack


            module MyEngine
              class Engine < Rails::Engine
                middleware.use SomeMiddleware
              end
            end
          

Engine helpers in the app


            class ApplicationController < ActionController::Base
              #1 selected
              helper MyEngine::SharedEngineHelper
              
              #all of them
              helper MyEngine::Engine.helpers
            end
          

Resources

Questions?

Made with Slides.com