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

Rails Engines - Lessons Learned

Rails Engines - Lessons Learned

This talk was performed at SpreeConf 2012 and a slightly shorter/modified version at Ruby on Ales in Bend Oregon, March 2012.

It covers the lessons that I've learned from building engines and working with them on massive scale applications. Two engines mentioned prominently in this talk are the Forem (https://github.com/radar/forem) and Spree (https://github.com/spree/spree), with some mentions of others, such as Devise.

Great information for those looking to get started with engines!

Ryan Bigg

March 03, 2012
Tweet

More Decks by Ryan Bigg

Other Decks in Programming

Transcript

  1. “[engines are a] nasty hack that breaks every new version

    of Rails” http://glu.ttono.us/articles/2006/08/30/guide-things-you-shouldnt-be-doing-in-rails Saturday, 3 March 12
  2. “I didn't want Rails to succumb to the lure of

    high-level components like login systems, forums, content management, and the likes.” - DHH http://david.heinemeierhansson.com/arc/000407.html Saturday, 3 March 12
  3. “But the goal of Rails is to create a world

    where [engines] are neither needed or strongly desired. Obviously, we are not quite there yet.” - DHH http://weblog.rubyonrails.org/2005/11/11/why-engines-and- components-are-not-evil-but-distracting Saturday, 3 March 12
  4. “Engines have not received the blessing of the RoR core

    team, and I wouldn't expect any different, because it would be madness to include them in the core Rails.” - James Adam http://article.gmane.org/gmane.comp.lang.ruby.rails/29166 Saturday, 3 March 12
  5. “In Rails 3.0, a Rails::Application object was introduced which is

    nothing more than an Engine but with the responsibility of coordinating the whole boot process.” Rails::Application Saturday, 3 March 12
  6. GOOD README not included but for the love of God

    write one Saturday, 3 March 12
  7. module Forem class Ability include CanCan::Ability def initialize(user) user ||=

    Forem.user_class.constantize.new can :read, Forem::Category do |category| user.can_read_forem_category?(category) end ... Saturday, 3 March 12
  8. module Forem class Ability include CanCan::Ability def initialize(user) user ||=

    Forem.user_class.constantize.new can :read, Forem::Category do |category| user.can_read_forem_category?(category) end ... Saturday, 3 March 12
  9. gem ‘forem’, :git => “git://github.com/radar/forem” bundle install rake forem:install:migrations rake

    db:migrate create config/initializers/forem.rb Add forem_user method to AppController Saturday, 3 March 12
  10. gem ‘forem’, :git => “git://github.com/radar/forem” bundle install rake forem:install:migrations rake

    db:migrate create config/initializers/forem.rb Add forem_user method to AppController Add User#to_s method Saturday, 3 March 12
  11. gem ‘forem’, :git => “git://github.com/radar/forem” bundle install rake forem:install:migrations rake

    db:migrate create config/initializers/forem.rb Add forem_user method to AppController Add User#to_s method Go into console + create first forum Saturday, 3 March 12
  12. gem ‘forem’, :git => “git://github.com/radar/forem” bundle install rake forem:install:migrations rake

    db:migrate create config/initializers/forem.rb Add forem_user method to AppController Add User#to_s method Go into console + create first forum Mount Forem::Engine, :at => ‘/’ Saturday, 3 March 12
  13. gem ‘forem’, :git => “git://github.com/radar/forem” bundle install rake forem:install:migrations rake

    db:migrate Pray that it works. create config/initializers/forem.rb Add forem_user method to AppController Add User#to_s method Go into console + create first forum Mount Forem::Engine, :at => ‘/’ Saturday, 3 March 12
  14. gem ‘forem’, :git => “git://github.com/radar/forem” bundle install rails g forem:install

    It works! Answer two questions. (assuming you have a User model) Saturday, 3 March 12
  15. mount Spree::Core::Engine, :at => ‘/’ mount Spree::Auth::Engine, :at => ‘/’

    mount Spree::Api::Engine, :at => ‘/’ mount Spree::Dash::Engine, :at => ‘/’ mount Spree::Promo::Engine, :at => ‘/’ Saturday, 3 March 12
  16. mount Spree::Core::Engine, :at => ‘/’ mount Spree::Auth::Engine, :at => ‘/’

    mount Spree::Api::Engine, :at => ‘/’ mount Spree::Dash::Engine, :at => ‘/’ mount Spree::Promo::Engine, :at => ‘/’ mount Spree::YourExtension, :at => ‘/’ mount Spree::YourExtension, :at => ‘/’ mount Spree::YourExtension, :at => ‘/’ mount Spree::YourExtension, :at => ‘/’ Saturday, 3 March 12
  17. describe Spree::ProductsController do it “gets a list of products” do

    get :index end end spec/controllers/products_controller_spec.rb Saturday, 3 March 12
  18. describe Spree::ProductsController do it “gets a list of products” do

    get :index end end spec/controllers/products_controller_spec.rb No route matches { :controller => “Spree::ProductsController”, :action => “index” } Saturday, 3 March 12
  19. http://stackoverflow.com/a/5832908/15245 How do I write a Rails 3.1 engine controller

    test in RSpec? The workaround is quite simple, instead of this get  :show,  :id  =>  1 use this get  :show,  {:id  =>  1,  :use_route  =>  :posts} Saturday, 3 March 12