Engine routes in Application Controller

rails engine routes
rails engine routes main app
rails engine routes not working
rails engine application controller
rails routes
rails engine configuration
rails engine migrations
generate engine

I have a before_filter hook in my main app's application controller that does something like: (It doesn't just put a link in the flash, there is a message, but it isn't relevant to the question, it just accesses the route in the method)

class ApplicationController < ActionController::Base
  before_filter :set_link

  def set_link
    flash[:notice] = items_path
  end
end

This works fine for the app, however when I go into the controllers for an engine I made I get the exception

No route matches {:controller=>"items", :action=>"index"}

I understand that when in the engine, the routes helpers are for the engine unless prefixed with main_app

So changing the method in the application controller to

  def set_link
    flash[:notice] = main_app.items_path
  end

Gets rid of the exception but I really don't want to have to do that. Is there another solution to getting the engine to recognize the main_app routes?

EDIT:

This also happens if the application layout calls path helpers. So if the engine is designed to integrated into the main_app's layout then this issue will crop there up too.

Mountable engines are designed to work like this, that is isolate the main app routes and the engine routes.

If you want the two sets of routes to be merged, you can use a non-isolated engine. The first step is removing the isolated_namespace method call in your engine definition:

module MyEngine
  class Engine < Rails::Engine
    isolate_namespace MyEngine # remove this line
  end
end

The second step is to convert your routes in my_engine/config/routes.rb, you should go from this:

MyEngine::Engine.routes.draw do
  # stuff that routes things
end

to this:

Rails.application.routes.draw do
  # stuff that routes things
end

and remove the mount method call in your application's routes:

App::Application.routes.draw do
  mount MyEngine::Engine => "/engine" # remove this line
end

The main advantages of doing it this way would be:

  1. No need to monkey-patch rails. I know devise does this, but this could be a leftover from the days when engines didn't exist in rails.

  2. No need to mount the engine in the application routes. On the other hand, this could backfire if you'd like to control more precisely the insertion point as all you engine routes would be called after (or before, I don't have the answer to this question) your main routes.

If you're looking for documentation on engines, the rails docs for the Engine class are a pretty good starting point. I'd strongly recommend that you read them (in case you haven't yet) if you're interested in the subject.

Rails::Engine, Mountable engines are designed to work like this, that is isolate the main app routes and the engine routes. If you want the two sets of routes to� Using Engine's routes outside Engine. Since you can now mount an engine inside application's routes, you do not have direct access to Engine's url_helpers inside Application. When you mount an engine in an application's routes, a special helper is created to allow you to do that. Consider such a scenario:

I figured out how to do this. The problems lies within the isolated namespace. In order to integrate the engine with the app and share the same layout (which may have path helpers from the main app) I did this:

Firstly I removed config/routes.rb from the engine

Then I removed the isolate_namespace from the engine class

module MyEngine
   class Engine < Rails::Engine
-    isolate_namespace MyEngine
   end
 end
end

I added a file that was loaded in the engine:

module ActionDispatch::Routing
  class Mapper
    def mount_my_engine_at(mount_location)
      scope mount_location do
        #Declare all your routes here
      end
    end
  end
end

Finally, in the main app's config/routes.rb instead of 'mount'ing the engine, you can call your method

mount_my_engine_at "mount_location"

This will basically 'mount' your engine as part of the main app instead of being isolated from it. It is similar to how Devise does it too.

Engine routes in Application Controller, rb - defining routes engine will provide, same as Rails app. Also noticable things are similar to Rails application application_controller.rb and� This is so that the engine routes are confined to the engine itself and can be mounted at a specific point as shown in the test directory section. It also causes the engine's routes to be isolated from those routes that are within the application. The Routes section of this guide describes it in detail.

You can keep the isolate_namespace. In your engine routes.rb

MyEngine::Engine.routes.draw do
  ...
  root to: "something#index"
end

Rails.application.routes.draw do
  get "something", to: "my_engine/something#index"
end

And then in the main app routes.rb

Rails.application.routes.draw do

  mount MyEngine::Engine => "/anything_you_want"

  root to: "main#index"
end

This way you can choose what routes you want to expose (and which you do not)

Rails mountable engines, Routes inside an engine are isolated from the application by default. The application and its engines from any place in app (in controller, or in a class in lib/ ). This RegisterRoutes method is called by the Global.ascx when the application is started. The Application_Start method under Global.ascx calls this MapRoute function which sets the default Controller and its action (method inside the Controller class). To modify the above default mapping as per our example, change the following line of code −

The easiest way is to draw the routes in both the main app, and the engine, so that they are accessible to both:

[MyEngine::Engine, App::Application].each do |app|
  app.routes.draw do
    # Declare all your routes here
  end
end

Integrating Gem/Engine and Main Rails App � GitHub, class Clearance::SessionsController < ApplicationController unloadable end in the engine ActionController::Routing::Routes.draw do |map|� For rails 3. desc 'Print out all defined routes inside engine match order, with names. Target specific controller with CONTROLLER=x.' task engine_routes: :environment do Rails.application.reload_routes!

You can keep the isolate_namespace, as strongly recommended by Rails Engine guide, and do this:

# inside your main_app's config/routes.rb
Rails.application.routes.draw do
  root to: 'home#index'

  mount MyEngine::Engine, at: "/" 
end
# inside your engine's controller
module MyEngine
  class SomeController << ::ApplicationController
    # include main_app's route helpers
    helper Rails.application.routes.url_helpers

  end
end

And inside your gem, make sure all the url helpers are prefixed with the correct routing proxy method (e.g. my_engine.pages_path).

Your main_app's layout and engine's controller will route and link to those url helpers correctly to the main app. You don't have to add "main_app" prefix anywhere to the main app. The only downside is you're mounting your engine's routes at main_app's root path, which could collide with any routes by the same name. This is expected anyway if you were to do non-isolate_namespace.

Tips For Writing Your Own Rails Engine, In the Passages Engine, the RoutesController demonstrates this nesting. |-app |-- controllers |---passages |----routes_controller.rb. module� Routing data gets filled in Application_Start event. It uses RouteTable object to fill routes. Route engine uses this table to match incoming request and execute action methods. You can add route details to application by adding Route object to static Routes property of RouteTable. The Routes property is RouteCollection object.

How to Build a Ruby on Rails Engine, class Plugin::RoutesController < ApplicationController def index # … end end If you are wanting to change existing routes, an engine is not required. The final part of the engine that we’ll take a look at in this quick overview is in the /test directory. Under /test/dummy is a Rails application and it’s there to show us how our engine works when it’s mounted into an app. The application’s config directory contains a routes.rb file.

Plugin controller spec: Plugin routes are not drawn - dev, rb file. Extracting Controllers. Then I identified the engine controller classes from routes and moved them to engines/my_engine/app/controllers/� Routes are defined in startup code or attributes. Routes describe how URL paths should be matched to actions. Routes are also used to generate URLs (for links) sent out in responses. Actions are either conventionally routed or attribute routed. Placing a route on the controller or the action makes it attribute routed.

How I created engines from monolithic Ruby on Rails application , the following route generated in an application layout. link_to "Foo", :controller => "foo", :action => "bar". # when rendered from the action of an engine would. I ran into a nasty little problem today when deploying an application using ASP.NET 4.0 Routing to my live server. The application and its Routing were working just fine on my dev machine (Windows 7 and IIS 7.5), but when I deployed (Windows 2008 R1 and IIS 7.0) Routing would just not work.

Comments
  • What's wrong with main_app? Besides that, why you're introducing a dependency in your engine from the main app, in this way your engine depends on items_path being defined in every app which uses it. This is not a good practice, usually you should use only main_app.root_path, or some other well known routes (for instance if your using devise the sign_in_path).
  • items_path would be defined in the main app which is already built. And I want to have the engine mounted somewhere but integrated into the current app's layout. The engine itself never references items_path at all. I just want the views generated by the engine to get put in the body of the application layout. However, the application layout needs to access to the main_app's routes
  • This comes from the need to have the engine and the application share the same layout. That way when a user goes from a page on the main app, to a page on the engine, there is no visible difference between the layout.
  • you forgot to note, if you remove isolated_namespace you might expose yourself to some name conflicts with the main app or other gems (example: helpers)