Search code examples
ruby-on-rails-3ruby-on-rails-pluginsrails-enginesruby-on-rails-3.1

Rails 3.1: Engine vs. Mountable App


Can someone help me understand the differences between a Rails Engine and a Mountable app? In Rails 3.1, you can create either one with the "rails new plugin ___" command.

rails plugin new forum --full        # Engine
rails plugin new forum --mountable   # Mountable App

When would you want to use one versus the other? I know you can package an Engine as a gem, for one. Is that not the case for Mountable Apps? What other differences are there?


Solution

  • I have noticed the following:

    Full Engine

    With a full engine, the parent application inherits the routes from the engine. It is not necessary to specify anything in parent_app/config/routes.rb. Specifying the gem in Gemfile is enough for the parent app to inherit the models, routes etc. The engine routes are specified as:

    # my_engine/config/routes.rb 
    Rails.application.routes.draw do 
      # whatever 
    end 
    

    No namespacing of models, controllers, etc. These are immediately accessible to the parent application.

    Mountable Engine

    The engine's namespace is isolated by default:

    # my_engine/lib/my_engine/engine.rb
    module MyEngine 
      class Engine < Rails::Engine 
        isolate_namespace MyEngine 
      end 
    end
    

    With a mountable engine, the routes are namespaced and the parent app can bundle this functionality under a single route:

    # my_engine/config/routes.rb 
    MyEngine::Engine.routes.draw do 
      #whatever 
    end 
    
    # parent_app/config/routes.rb 
    ParentApp::Application.routes.draw do 
        mount MyEngine::Engine => "/engine", :as => "namespaced" 
    end 
    

    Models, controllers, etc are isolated from the parent application - although helpers can be shared easily.

    These are the main differences I have spotted. Perhaps there are others? I have asked over here, but have yet to receive a response.

    My impression is that since a full engine does not isolate itself from the parent application, it is best used as a standalone application adjacent to the parent app. I believe name clashes could occur.

    A mountable engine could be used in situations where you want to avoid name conflicts and bundle the engine under one specific route in the parent application. For example, I am working on building my first engine designed for customer service. The parent application could bundle it's functionality under a single route such as:

    mount Cornerstone::Engine => "/cornerstone", :as => "help" 
    

    If I'm way off in my assumptions, someone please let me know and I'll fix this response. I have made a small article about the subject here.