Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modularizing Rails Apps

Modularizing Rails Apps

So, you've been writing Rails apps and find yourself writing the same common logic across multiple applications. Rather than duplicating the same logic across the apps, you know there must be a better way to share this functionality.

Rails has a great modular architecture allowing you to take components and integrate them into your application. We'll walk through the various ways in which you can modularize and DRY up your shared functionality to best fit your needs.

Plugins? Engines? Full? Mountable? Railties?

This talk will explain each concept, what they are best suited for, and how you can take advantage of them. We will also cover how these concepts are changing in Rails 4 so you'll prepared when it is released.

Kevin Shekleton

May 04, 2013
Tweet

More Decks by Kevin Shekleton

Other Decks in Programming

Transcript

  1. class Plugin • The junk drawer of Rails apps •

    Code copied into
 your_app/vendor/plugins • Often managed via rake tasks or git submodules • Encourages local editing http://www.flickr.com/photos/listener42/3488807301
  2. Russian Doll Pattern • Y. Katz, C. Lerche
 RailsConf 2009


    http://vimeo.com/4611379 • Build reusable slices not core to your app and embed it • Apps within apps • Implemented earlier as
 Merb slices http://www.flickr.com/photos/johnkay/3539939004
  3. Full Engine $ rails plugin new \
 name --full A

    reusable app that fully integrates into your app MVC, routes, assets, etc defined in the engine are automatically available in your app http://www.flickr.com/photos/scania/2869106546
  4. Full engines 2005 2007 Rails 2.0 2009 Rails 2.3 2010

    Rails 3.0 Engine concept introduced Railties Overhauled
  5. Railtie Power • Add rake tasks • Add generators •

    Hook into the Rails console load • Hook into the various Rails lifecycle events (before/after_initialize, to_prepare, etc) https://blog.engineyard.com/2010/extending-rails-3-with-railties
  6. # See Railtie::Configuration config.to_prepare { ... } module Awesome end

    class Railtie < Rails::Railtie end rake_tasks do load ‘/awesome.tasks’ end initializer ‘awesome.configure’ do |app| # do awesome things like # subscribe to ActiveSupport::Notifications end Creating a Railtie
  7. •# Called before the app’s config is loaded config.before_configuration =

    {...} •# Called before Rails has been initialized config.before_initialize = {...} •# Called before app classes are loaded config.before_eager_load = {...} Railtie Initializer Hooks
  8. •# Called after app classes are loaded config.to_prepare = {...}

    •# Called after Rails has been initialized config.after_initialize = {...} Railtie Initializer Hooks (cont)
  9. Using a Railtie # Gemfile of your app gem ‘awesome’,

    ’~> 1.0’ # awesome.gem # awesome/lib/awesome.rb require ‘awesome/railtie’ if defined?(Rails)
  10. How are Railties Discovered? class Railtie autoload :Configuration, "rails/railtie/configuration" include

    Initializable ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Engine Rails::Application) class << self private :new delegate :config, to: :instance def subclasses @subclasses ||= [] end def inherited(base) unless base.abstract_railtie? subclasses << base end end
  11. How are Railties Discovered? class Railtie autoload :Configuration, "rails/railtie/configuration" include

    Initializable ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Engine Rails::Application) class << self private :new delegate :config, to: :instance def subclasses @subclasses ||= [] end def inherited(base) unless base.abstract_railtie? subclasses << base end end def subclasses @subclasses ||= [] end def inherited(base) unless base.abstract_railtie? subclasses << base end end
  12. class Railtie The core API that all of Rails is

    built upon class ActionMailer::Railtie
 class ActionController::Railtie
 class ActionDispatch::Railtie
 ...
 class ActiveModel::Railtie
 class ActiveRecord::Railtie
 class ActiveSupport::Railtie If Rails can dogfood their own APIs to create Rails,
 chances are you can build awesome things too.
  13. Full engines Overhauled Railties 2005 2011 Rails 3.1 2007 Rails

    2.0 2009 Rails 2.3 2010 Rails 3.0 Engine concept introduced Mountable engines
  14. Mountable Engine $ rails plugin new \
 name --mountable Like

    full engines, but... --Namespaced --Routes must be mounted in your app http://www.flickr.com/photos/tshearer/3935429228
  15. module Blog end # defining mountable engines isolate_namespace Blog class

    Engine < ::Rails::Engine end Full vs Mountable> Defining
  16. Full vs Mountable> Application Controller # Mountable engines define their

    # own ApplicationController module Blog class ApplicationController < ActionController::Base end
  17. Blog::Engine.routes.draw do resources :posts end Rails.application.routes.draw do mount Blog::Engine =>

    ‘/blog’ end # Mountable engine routes Full vs Mountable> Routes
  18. Full Mountable App ✔ ✔ Namespaced ✔ Routes Engines: Full

    vs Mountable Recap Inherited
 by your app Must be
 mounted
  19. Full + Mountable Engine # Start with a mountable engine

    $ rails plugin new \ name --mountable
  20. Full + Mountable Engine (cont) # Draw routes into the

    main app # like a full engine # Caution: Beware of collisions! Rails.application.routes.draw do resources :posts end
  21. Mountable engines Full engines Overhauled Railties 2005 2012 Rails 3.2

    2011 Rails 3.1 2007 Rails 2.0 2009 Rails 2.3 2010 Rails 3.0 Engine concept introduced vendor/plugins deprecated
  22. Mountable engines Full engines Overhauled Railties vendor/plugins deprecated 2005 2012

    Rails 3.2 2011 Rails 3.1 2013 Rails 4.0 2007 Rails 2.0 2009 Rails 2.3 2010 Rails 3.0 Engine concept introduced Plugin removed
  23. Dummy App • Full and Mountable engines are tested the

    same • A full blown dummy app is generated in /test which consumes your engine • Write tests against the dummy app http://www.flickr.com/photos/20759665@N03/7400887540