Search code examples
ruby-on-railsruby-on-rails-3routesruby-on-rails-pluginsrails-engines

How to override Rails app routes from an engine?


I have a Rails app that I am trying to integrate a Rails engine in to.

The host app has some catch all routes:

  # magic urls
  match '/' => 'admin/rendering#show'
  match '*path/edit' => 'admin/rendering#show', :defaults => { :editing => true }
  match '*path' => 'admin/rendering#show'

It looks like the engine routes are loaded after the application catches all routes.

/sitemap.xml(.:format)                                            {:format=>"xml", :controller=>"admin/sitemaps", :action=>"show"}
                              /(.:format)                                                       {:controller=>"admin/rendering", :action=>"show"}
                              /*path/edit(.:format)                                             {:controller=>"admin/rendering", :action=>"show"}
                              /*path                                                            {:controller=>"admin/rendering", :action=>"show"}
           engine_envs GET    /engine/envs/:id(.:format)                                       {:controller=>"engine/envs", :action=>"show"}
                       PUT    /engine/envs/:id(.:format)                                       {:controller=>"engine/envs", :action=>"update"}
                jammit        /assets/:package.:extension(.:format)                             {:extension=>/.+/, :controller=>"jammit", :action=>"package"}

So far, everything is hitting the /engine/envs routes are getting caught by the application catch all routes. However I see that the jammit route is loaded after the engine and I don't believe those are getting caught. Any way to override the app routes?


Solution

  • You could stick your engine routes in a method and then call that in your host app.

    # engine routes.rb
    module ActionDispatch::Routing
      class Mapper
        def engine_routes
          engine_envs GET    /engine/envs/:id(.:format)
          # ...
        end 
    # ...
    

    and then in your host app add the method before the catch-all route

    # host app routes.rb
    MyTestApp::Application.routes.draw do
      # ... 
    
      engine_routes
    
      match '/' => 'admin/rendering#show'
      match '*path/edit' => 'admin/rendering#show', :defaults => { :editing => true }
      match '*path' => 'admin/rendering#show'
    end