SlideShare uma empresa Scribd logo
1 de 29
Problem

 monolithic application

 no reusability

 slow tests

 bigger application, more mess
Possible solutions

 extract common functionality to modules

 create gems

 tie gem with rails application with railtie

 rails engine
What is a Gem ?

 packaged application or library
      code
      tests
      documentation
      gemspec
Creating gem

 bundle gem simplify                ├── Gemfile
                                     ├── LICENSE.txt
                                     ├── README.md
 structure                          ├── Rakefile
      code (lib/)                   ├── lib
                                     │ ├── simplify
      tests (test/ or spec/)        │ │ └── version.rb
      documentation (doc/ README)   │ └── simplify.rb
                                     └── simplify.gemspec
      executable files (bin/)

 information about gem
    simplify.gemspec
Releasing Gem

     change version

     run `bundle`

     commit changes

     run `rake release`

$ rake release
stupid_spam_protection 0.0.2 built to pkg/stupid_spam_protection-0.0.2.gem
Tagged v0.0.2
Pushed git commits and tags
Pushed stupid_spam_protection 0.0.2 to rubygems.org
in-memory testing with sqlite
spec/spec_helper.rb
require "active_record"
require "sqlite3”

ActiveRecord::Base.establish_connectio
n{
  :adapter => "sqlite3”,
  :database => ":memory:”
}

load "db/schema.rb"                      db/schema.rb
                                         ActiveRecord::Schema.define do
RSpec.configure do |config|               create_table "items", :force => true do |t|
 config.around do |example|                t.string "name”
  ActiveRecord::Base.transaction do        t.datetime "created_at", :null => false
   example.run                             t.datetime "updated_at", :null => false
   raise ActiveRecord::Rollback           end
  end
 end
end
testing with mysql
                       database
spec/spec_helper.rb

 begin
   ActiveRecord::Base.establish_connection(config)
 rescue
   ActiveRecord::Base.establish_connection(config.merge('database' => nil))
   ActiveRecord::Base.connection.create_database(config['database'], {
   :charset => 'utf8‟,
   :collation => 'utf8_unicode_ci‟})
 end                                   config = HashWithIndifferentAccess.new({
                                         :adapter => "mysql2",
 load "db/schema.rb"                     :host => "127.0.0.1",
                                         :username => "root",
 RSpec.configure do |config|             :password => "",
  # the same from previous slide         :database => ”database_name”
 end                                   })
Tie gem to Rails app
           Rails::Railtie
 extend Rails framework
    load all needed dependencies

 several hooks methods for all needs

require "wnm_support/railtie" if defined?(Rails)   lib/wnm_support.rb

module WnmSupport                                  lib/wnm_support/railtie.rb
 class Railtie < Rails::Railtie
  initializer "wnm_support.view_helpers" do
    ActionView::Base.send :include,
BoolToHuman
  end
 end
end
Railtie hooks 1

 Plugin hooks
     initializer
     generators
     rake_tasks
     console

  initializer "wnm_support.active_record_ext" do
    ActiveSupport.on_load(:active_record) do
          ActiveRecord::Base.send :include,
               WnmSupport::ActiveRecordExt::DestroyValidation
    end
  end
Railtie hooks 2

 Rails configuration hooks
      to_prepare (once in production, every request in development)
      before_initialize
      after_initialize
      app_middleware
      before_configuration
      before_eager_load
      generators
   config.to_prepare do
    AppController.send(:include,
   Controller::Authentication)
   end
What is Rails Engine ?

 every rails app is an engine
 Rails::Engine < Rails::Railtie
 all together
      gem skeleton
      railtie
      structure for app
      dummy app for testing
      assets
Engine walkthrough

 generate new engine

 basic commands

 testing

 mounting to host app

 overriding defaults
Generating Engine

 rails plugin new blorgh --mountable –
  full

 everything (assets, controller, models,
  views) are inside Blorgh namespace
    module Blorgh
     class Engine < ::Rails::Engine
      isolate_namespace Blorgh
     end
    end
Basics commands

 in root directory of the engine
      bundle
      rake
      rspec
      rails generate # generate code for engine

 in spec/dummy or test/dummy location
    rails console
    rails server
    rails generate # generate code for dummy app
Testing

      generally as in standard rails application

      engine is tested inside dummy app

      small problems with factory girl
           explicite model class in factory girl
           include routes for request tests
FactoryGirl.define do
 factory :user, :class => Blorgh ::User do
  sequence(:login) { |n| "admin_#{n}" }      RSpec.configure do |config|
  password "too_secret"                       config.include Blorgh ::Engine.routes.url_helper
  password_confirmation { password }         end
 end
end
Mounting Engine to host
        application
 Gemfile
    gem “blorgh”, :path => “~/Sites/blorgh”

 install migration
    `rake blorgh:install:migrations`

 load seeds data
    Blorgh::Engine.load_seed # in rails console

 require assets if needed
    *= require blorgh/application # assets/stylesheets/application.css

 mount to routes.rb
    mount Blorgh::Engine => "/blorgh"
Get to engine and get
             back
 routes to engine from host app
    prefix with engine name
    example engine “blorgh”
       <%= link_to “Users”, blorgh.users_path %>

 routes from engine to host app
    prefix with main_app
    example engine “blorgh”
       <%= link_to “Home page”,main_app.root_path %>
Overriding engine classes

       Controller, Model, etc.
            reopening classes
                 class_eval, module_eval

module MySite
 class Railtie < ::Rails::Railtie
  config.to_prepare do
    Dir["app/decorators/**/*.rb"].each do |path|
     load path                                     app/decorators/models/blorgh/article.rb
    end
  end                                              Blorgh::Article.class_eval do
 end                                                has_many :users, :class_name => „User'
end                                                end
Overriding engine views

 simple copy and paste view file that you want to
  override to the same location in host app
Application Modules with
        Rails Engine
 every new engine means new namespace

 application modules means for us more engines with
  same namespace

 inspiration from refinerycms
The same namespace
       different engines
 module Wnm                         module Wnm
  module Core                        module Pages
   class Engine < ::Rails::Engine     class Engine < ::Rails::Engine
    isolate_namespace Wnm              isolate_namespace Wnm
    engine_name :wnm_core              engine_name :wnm_pages
  end                                end
 end                                end



rake wnm_core:install:migrations     rake wnm_pages:install:migrations

Wnm::Core::Engine.load_seed          Wnm::Pages::Engine.load_seed



                 both are nested in `Wnm` namespace
Developing from local
           Production from git
   bundler does not allow to have same package from
    different sources in Gemfile

export LOAD_GEMS_FROM_LOCAL=1               .rvmrc

if ENV["LOAD_GEMS_FROM_LOCAL"] == "1"                             Gemfile
  gem "wnm_core", :path => "~/Sites/wnm_core"
  gem "wnm_pages", :path => "~/Sites/wnm_pages"
  gem "wnm_customers", :path => "~/Sites/wnm_customers"
else
  gem "wnm_core", :git => "git@…/wnm_core.git", :tag => "v1.0.0"
  gem "wnm_pages", :git => "git@…/wnm_pages.git", :tag => "v1.0.0"
  gem "wnm_customers", :git => "git@.../wnm_customers.git", :tag => "v1.0.0"
end
Deploying

 change LOAD_GEMS_FROM_LOCAL to 0 and run
  `bundle`

 commit and push

 `cap deploy`
Tips

 if you are overriding views heavily always prefix routes
  path with engine module name
<%= link_to page.name, wnm_page.page_path(page), :title => page.name %>


 use class methods instead of constants

 always write full path to class/module if it is in
  namespace
     ::ApplicationController instead of ApplicationController

 testing is essential
Why use Rails::Engine ?

   reusable code
        code
        hole application
        assets

   modular thinking

   gem with MVC

   faster test

   testing gem in dummy app infrastructure

   some well known engines
        devise, kaminari, refinerycms
Problems

 if you are bending engines weird thinks can happen

 a lot of weird errors
     application does not run in development mode from git
      sources
     tests passed, but in browser it is not running
     in browser it is running but tests are throwing exceptions

 overriding classes in host app

 helper methods from host app does not work in overridden
  views

 some things from documentation does not work at all
Why we did this like that ?

 a lot of our project are in general the same

 build core for site quickly
    “scaffold” for application

 rails engine is infrastructure for modular application

 we can have backend and frontend in the same
  application module
Sources

 http://guides.rubygems.org/what-is-a-gem/
 http://www.engineyard.com/blog/2010/extending-rails-3-with-railties/
 http://www.slideshare.net/AndyMaleh/rails-engine-patterns
 http://edgeguides.rubyonrails.org/engines.html
 http://edgeapi.rubyonrails.org/classes/Rails/Railtie.html
 http://edgeapi.rubyonrails.org/classes/Rails/Engine.html
 http://pivotallabs.com/users/shagemann/blog/articles/1994-migrating-
  from-a-single-rails-app-to-a-suite-of-rails-engines
 http://railscasts.com/episodes/301-extracting-a-ruby-gem
 http://railscasts.com/episodes/303-publishing-a-gem
 http://railscasts.com/episodes/277-mountable-engines

Mais conteúdo relacionado

Mais procurados

Rails Engines as a way to Micro services
Rails Engines as a way to Micro servicesRails Engines as a way to Micro services
Rails Engines as a way to Micro servicesLucas Alencar
 
Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)Fwdays
 
How to set up and test a Rails 3 Engine
How to set up and test a Rails 3 EngineHow to set up and test a Rails 3 Engine
How to set up and test a Rails 3 Enginenicholasf
 
React.js for Rails Developers
React.js for Rails DevelopersReact.js for Rails Developers
React.js for Rails DevelopersArkency
 
How angularjs saves rails
How angularjs saves railsHow angularjs saves rails
How angularjs saves railsMichael He
 
React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016Justin Gordon
 
API Development with Laravel
API Development with LaravelAPI Development with Laravel
API Development with LaravelMichael Peacock
 
AngularJS meets Rails
AngularJS meets RailsAngularJS meets Rails
AngularJS meets RailsElena Torró
 
Brief Introduction to Ember
Brief Introduction to EmberBrief Introduction to Ember
Brief Introduction to EmberVinay B
 
Building modular applications with JPMS and Layrry
Building modular applications with JPMS and LayrryBuilding modular applications with JPMS and Layrry
Building modular applications with JPMS and LayrryAndres Almiray
 
Laravel Restful API and AngularJS
Laravel Restful API and AngularJSLaravel Restful API and AngularJS
Laravel Restful API and AngularJSBlake Newman
 
How to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorialHow to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorialKaty Slemon
 
Web Development with Laravel 5
Web Development with Laravel 5Web Development with Laravel 5
Web Development with Laravel 5Soheil Khodayari
 

Mais procurados (20)

Rails Engines as a way to Micro services
Rails Engines as a way to Micro servicesRails Engines as a way to Micro services
Rails Engines as a way to Micro services
 
Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)
 
How to set up and test a Rails 3 Engine
How to set up and test a Rails 3 EngineHow to set up and test a Rails 3 Engine
How to set up and test a Rails 3 Engine
 
Rails::Engine
Rails::EngineRails::Engine
Rails::Engine
 
React.js for Rails Developers
React.js for Rails DevelopersReact.js for Rails Developers
React.js for Rails Developers
 
How angularjs saves rails
How angularjs saves railsHow angularjs saves rails
How angularjs saves rails
 
React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016
 
API Development with Laravel
API Development with LaravelAPI Development with Laravel
API Development with Laravel
 
AngularJS meets Rails
AngularJS meets RailsAngularJS meets Rails
AngularJS meets Rails
 
Brief Introduction to Ember
Brief Introduction to EmberBrief Introduction to Ember
Brief Introduction to Ember
 
Building modular applications with JPMS and Layrry
Building modular applications with JPMS and LayrryBuilding modular applications with JPMS and Layrry
Building modular applications with JPMS and Layrry
 
Laravel Restful API and AngularJS
Laravel Restful API and AngularJSLaravel Restful API and AngularJS
Laravel Restful API and AngularJS
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
Laravel Introduction
Laravel IntroductionLaravel Introduction
Laravel Introduction
 
How to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorialHow to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorial
 
Laravel 5
Laravel 5Laravel 5
Laravel 5
 
Intro to Laravel
Intro to LaravelIntro to Laravel
Intro to Laravel
 
Slim3 quick start
Slim3 quick startSlim3 quick start
Slim3 quick start
 
Curso rails
Curso railsCurso rails
Curso rails
 
Web Development with Laravel 5
Web Development with Laravel 5Web Development with Laravel 5
Web Development with Laravel 5
 

Semelhante a Rails Engine | Modular application

Deploying configurable frontend web application containers
Deploying configurable frontend web application containersDeploying configurable frontend web application containers
Deploying configurable frontend web application containersJosé Moreira
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Racksickill
 
Rest web service_with_spring_hateoas
Rest web service_with_spring_hateoasRest web service_with_spring_hateoas
Rest web service_with_spring_hateoasZeid Hassan
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发shaokun
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Clinton Dreisbach
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails DevsDiacode
 
Porting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability SystemsPorting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability SystemsMarcelo Pinheiro
 
Angular JS in 2017
Angular JS in 2017Angular JS in 2017
Angular JS in 2017Ayush Sharma
 
Practical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppPractical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppSmartLogic
 
Improving build solutions dependency management with webpack
Improving build solutions  dependency management with webpackImproving build solutions  dependency management with webpack
Improving build solutions dependency management with webpackNodeXperts
 

Semelhante a Rails Engine | Modular application (20)

Deploying configurable frontend web application containers
Deploying configurable frontend web application containersDeploying configurable frontend web application containers
Deploying configurable frontend web application containers
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Rest web service_with_spring_hateoas
Rest web service_with_spring_hateoasRest web service_with_spring_hateoas
Rest web service_with_spring_hateoas
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
 
Capistrano
CapistranoCapistrano
Capistrano
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
 
RoR guide_p1
RoR guide_p1RoR guide_p1
RoR guide_p1
 
Generators
GeneratorsGenerators
Generators
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails Devs
 
Porting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability SystemsPorting Rails Apps to High Availability Systems
Porting Rails Apps to High Availability Systems
 
Cooking with Chef
Cooking with ChefCooking with Chef
Cooking with Chef
 
Rails engines
Rails enginesRails engines
Rails engines
 
RequireJS
RequireJSRequireJS
RequireJS
 
Angular JS in 2017
Angular JS in 2017Angular JS in 2017
Angular JS in 2017
 
Intro to Rack
Intro to RackIntro to Rack
Intro to Rack
 
Practical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppPractical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails App
 
Improving build solutions dependency management with webpack
Improving build solutions  dependency management with webpackImproving build solutions  dependency management with webpack
Improving build solutions dependency management with webpack
 

Último

How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 

Último (20)

How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 

Rails Engine | Modular application

  • 1.
  • 2. Problem  monolithic application  no reusability  slow tests  bigger application, more mess
  • 3. Possible solutions  extract common functionality to modules  create gems  tie gem with rails application with railtie  rails engine
  • 4. What is a Gem ?  packaged application or library  code  tests  documentation  gemspec
  • 5. Creating gem  bundle gem simplify ├── Gemfile ├── LICENSE.txt ├── README.md  structure ├── Rakefile  code (lib/) ├── lib │ ├── simplify  tests (test/ or spec/) │ │ └── version.rb  documentation (doc/ README) │ └── simplify.rb └── simplify.gemspec  executable files (bin/)  information about gem  simplify.gemspec
  • 6. Releasing Gem  change version  run `bundle`  commit changes  run `rake release` $ rake release stupid_spam_protection 0.0.2 built to pkg/stupid_spam_protection-0.0.2.gem Tagged v0.0.2 Pushed git commits and tags Pushed stupid_spam_protection 0.0.2 to rubygems.org
  • 7. in-memory testing with sqlite spec/spec_helper.rb require "active_record" require "sqlite3” ActiveRecord::Base.establish_connectio n{ :adapter => "sqlite3”, :database => ":memory:” } load "db/schema.rb" db/schema.rb ActiveRecord::Schema.define do RSpec.configure do |config| create_table "items", :force => true do |t| config.around do |example| t.string "name” ActiveRecord::Base.transaction do t.datetime "created_at", :null => false example.run t.datetime "updated_at", :null => false raise ActiveRecord::Rollback end end end end
  • 8. testing with mysql database spec/spec_helper.rb begin ActiveRecord::Base.establish_connection(config) rescue ActiveRecord::Base.establish_connection(config.merge('database' => nil)) ActiveRecord::Base.connection.create_database(config['database'], { :charset => 'utf8‟, :collation => 'utf8_unicode_ci‟}) end config = HashWithIndifferentAccess.new({ :adapter => "mysql2", load "db/schema.rb" :host => "127.0.0.1", :username => "root", RSpec.configure do |config| :password => "", # the same from previous slide :database => ”database_name” end })
  • 9. Tie gem to Rails app Rails::Railtie  extend Rails framework  load all needed dependencies  several hooks methods for all needs require "wnm_support/railtie" if defined?(Rails) lib/wnm_support.rb module WnmSupport lib/wnm_support/railtie.rb class Railtie < Rails::Railtie initializer "wnm_support.view_helpers" do ActionView::Base.send :include, BoolToHuman end end end
  • 10. Railtie hooks 1  Plugin hooks  initializer  generators  rake_tasks  console initializer "wnm_support.active_record_ext" do ActiveSupport.on_load(:active_record) do ActiveRecord::Base.send :include, WnmSupport::ActiveRecordExt::DestroyValidation end end
  • 11. Railtie hooks 2  Rails configuration hooks  to_prepare (once in production, every request in development)  before_initialize  after_initialize  app_middleware  before_configuration  before_eager_load  generators config.to_prepare do AppController.send(:include, Controller::Authentication) end
  • 12. What is Rails Engine ?  every rails app is an engine  Rails::Engine < Rails::Railtie  all together  gem skeleton  railtie  structure for app  dummy app for testing  assets
  • 13. Engine walkthrough  generate new engine  basic commands  testing  mounting to host app  overriding defaults
  • 14. Generating Engine  rails plugin new blorgh --mountable – full  everything (assets, controller, models, views) are inside Blorgh namespace module Blorgh class Engine < ::Rails::Engine isolate_namespace Blorgh end end
  • 15. Basics commands  in root directory of the engine  bundle  rake  rspec  rails generate # generate code for engine  in spec/dummy or test/dummy location  rails console  rails server  rails generate # generate code for dummy app
  • 16. Testing  generally as in standard rails application  engine is tested inside dummy app  small problems with factory girl  explicite model class in factory girl  include routes for request tests FactoryGirl.define do factory :user, :class => Blorgh ::User do sequence(:login) { |n| "admin_#{n}" } RSpec.configure do |config| password "too_secret" config.include Blorgh ::Engine.routes.url_helper password_confirmation { password } end end end
  • 17. Mounting Engine to host application  Gemfile  gem “blorgh”, :path => “~/Sites/blorgh”  install migration  `rake blorgh:install:migrations`  load seeds data  Blorgh::Engine.load_seed # in rails console  require assets if needed  *= require blorgh/application # assets/stylesheets/application.css  mount to routes.rb  mount Blorgh::Engine => "/blorgh"
  • 18. Get to engine and get back  routes to engine from host app  prefix with engine name  example engine “blorgh”  <%= link_to “Users”, blorgh.users_path %>  routes from engine to host app  prefix with main_app  example engine “blorgh”  <%= link_to “Home page”,main_app.root_path %>
  • 19. Overriding engine classes  Controller, Model, etc.  reopening classes  class_eval, module_eval module MySite class Railtie < ::Rails::Railtie config.to_prepare do Dir["app/decorators/**/*.rb"].each do |path| load path app/decorators/models/blorgh/article.rb end end Blorgh::Article.class_eval do end has_many :users, :class_name => „User' end end
  • 20. Overriding engine views  simple copy and paste view file that you want to override to the same location in host app
  • 21. Application Modules with Rails Engine  every new engine means new namespace  application modules means for us more engines with same namespace  inspiration from refinerycms
  • 22. The same namespace different engines module Wnm module Wnm module Core module Pages class Engine < ::Rails::Engine class Engine < ::Rails::Engine isolate_namespace Wnm isolate_namespace Wnm engine_name :wnm_core engine_name :wnm_pages end end end end rake wnm_core:install:migrations rake wnm_pages:install:migrations Wnm::Core::Engine.load_seed Wnm::Pages::Engine.load_seed both are nested in `Wnm` namespace
  • 23. Developing from local Production from git  bundler does not allow to have same package from different sources in Gemfile export LOAD_GEMS_FROM_LOCAL=1 .rvmrc if ENV["LOAD_GEMS_FROM_LOCAL"] == "1" Gemfile gem "wnm_core", :path => "~/Sites/wnm_core" gem "wnm_pages", :path => "~/Sites/wnm_pages" gem "wnm_customers", :path => "~/Sites/wnm_customers" else gem "wnm_core", :git => "git@…/wnm_core.git", :tag => "v1.0.0" gem "wnm_pages", :git => "git@…/wnm_pages.git", :tag => "v1.0.0" gem "wnm_customers", :git => "git@.../wnm_customers.git", :tag => "v1.0.0" end
  • 24. Deploying  change LOAD_GEMS_FROM_LOCAL to 0 and run `bundle`  commit and push  `cap deploy`
  • 25. Tips  if you are overriding views heavily always prefix routes path with engine module name <%= link_to page.name, wnm_page.page_path(page), :title => page.name %>  use class methods instead of constants  always write full path to class/module if it is in namespace  ::ApplicationController instead of ApplicationController  testing is essential
  • 26. Why use Rails::Engine ?  reusable code  code  hole application  assets  modular thinking  gem with MVC  faster test  testing gem in dummy app infrastructure  some well known engines  devise, kaminari, refinerycms
  • 27. Problems  if you are bending engines weird thinks can happen  a lot of weird errors  application does not run in development mode from git sources  tests passed, but in browser it is not running  in browser it is running but tests are throwing exceptions  overriding classes in host app  helper methods from host app does not work in overridden views  some things from documentation does not work at all
  • 28. Why we did this like that ?  a lot of our project are in general the same  build core for site quickly  “scaffold” for application  rails engine is infrastructure for modular application  we can have backend and frontend in the same application module
  • 29. Sources  http://guides.rubygems.org/what-is-a-gem/  http://www.engineyard.com/blog/2010/extending-rails-3-with-railties/  http://www.slideshare.net/AndyMaleh/rails-engine-patterns  http://edgeguides.rubyonrails.org/engines.html  http://edgeapi.rubyonrails.org/classes/Rails/Railtie.html  http://edgeapi.rubyonrails.org/classes/Rails/Engine.html  http://pivotallabs.com/users/shagemann/blog/articles/1994-migrating- from-a-single-rails-app-to-a-suite-of-rails-engines  http://railscasts.com/episodes/301-extracting-a-ruby-gem  http://railscasts.com/episodes/303-publishing-a-gem  http://railscasts.com/episodes/277-mountable-engines