Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Add an API for plugins to register routes

#329

This change allows plugins to register routes while maintaining control for the developer using the plugin.

This is how a plugin registers it's routes:

config.draw_for do |map|
  map.connect ...
  map.resources ...
end

# or

config.draw_for :my_plugin_admin do |map|
  map.connect ...
  map.resources ...
end

This is how a developer would install the plugin routes:

ActionController::Routing::Routes.draw do |map|
  # Install every registered plugin route.
  map.plugin_routes
  
  # Same as above.
  map.plugin_routes :all
  
  # Install the listed plugin routes.
  map.plugin_routes :hobo, :active_scaffold, :restful_authentication
  
  # The above approach could also be used multiple times
  # to handle order sensitive routes.
  map.plugin_routes :hobo
  map.connect '/something', ...
  map.plugin_routes :active_scaffold, :restful_authentication
  
  # Install every registered plugin route execept the listed plugins.
  map.plugin_routes :except => [:hobo, :something]
end

There are currently no tests for these changes. I will add tests soon. This patch includes the suggestions from DHH and technoweenie on #rails-contrib

Reported by Rich Cavanaugh · June 4th, 2008 @ 02:26 AM

State: duplicate
Milestone: 2.x
Assigned to: Rick Rick
Importance: none

Activity

  1. Rich Cavanaugh
    Rich Cavanaugh

    Attaching the patch would probably help it make it into Rails.

    June 4th, 2008 @ 02:27 AM

  2. Rick
    Rick
    • State changed from new to open
    • Assigned user set to Rick

    June 4th, 2008 @ 02:29 AM

  3. Rick
    Rick

    Just a nitpick, but config.draw_for with no arguments looks weird. That's why I suggested config.plugin_routes or something to that effect in #rails-contrib. It's something that looks fine with or without a given plugin name.

    June 4th, 2008 @ 03:36 AM

  4. Rich Cavanaugh
  5. Rich Cavanaugh
    Rich Cavanaugh

    You're absolutely right, I should have caught that. I've changed the method name to plugin_routes but, I also setup an alias for draw_for so you could still do:

    config.draw_for :plugin_admin do |map|
    end
    

    The unadorned approach is now:

    config.plugin_routes do |map|
    end
    

    June 4th, 2008 @ 07:27 PM

  6. Rich Cavanaugh
    Rich Cavanaugh
    • Tag set to actionpack, edge, enhancement, patch, railties, routing

    I've attached the finalized patch updated for edge and added tests.

    August 12th, 2008 @ 09:06 AM

  7. voxdolo
    voxdolo

    This looks like a great enhancement. I've wanted this functionality as a plugin developer several times. +1 here.

    August 13th, 2008 @ 01:57 AM

  8. Bruno Miranda
    Bruno Miranda

    This would be awesome to have. +1

    August 14th, 2008 @ 08:26 PM

  9. RSL
    RSL

    Question: is it really a good idea for routing information to be spread all over the rails app? and potentially conflicted between plugins? I'm much more comfortable with rake tasks and generators adding code to the routes.rb where you can easily see what's what. I'm all for this if someone could assuage those fears.

    August 15th, 2008 @ 10:34 PM

  10. Rich Cavanaugh
    Rich Cavanaugh

    This change simply allows plugins to define their routes but does not automatically inject them into the actual routing.

    They are then inserted by the developers into config/routes.rb using code like:

    
      map.plugin_routes :hobo
      # or more automated
      map.plugin_routes :all
    

    So control remains entirely in the rails app developer's hands. They can control the precise order that all of the plugin routes are injected to avoid conflicts.

    At that point it's just a matter of the developer knowing what the plugins they're using are doing. If they don't, conflicts could happen in many places between plugins, not just routes.

    August 15th, 2008 @ 11:09 PM

  11. azimux
    azimux

    I don't know if anybody has looked at the engines plugin, but it uses the syntax:

    map.from_plugin :some_plugin

    Then the plugin has a routes.rb in it's root directory and the routes in this file are evaled by the above call

    August 16th, 2008 @ 10:26 AM

  12. RSL
    RSL

    rich, i misread developer to mean the plugin developer [my fault for reading too quickly]. great patch. +1

    August 16th, 2008 @ 05:17 PM

  13. Ramon Salvadó
  14. Michael Koziarski
    Michael Koziarski
    • Milestone set to 2.x

    I like this, or something like it, for the 2.3 stream.

    But for now I'm just moving it off the radar for 2.2

    September 13th, 2008 @ 12:23 PM

  15. James Adam
    James Adam

    The engines plugin does indeed implement this, but in a much simpler, low-tech way. If this is going into core, it probably needs to work nicely with things like namespaces.

    Additionally, is there any way to avoid the 'currently_loading_plugin' attribute? It's a bit inelegant.

    September 14th, 2008 @ 11:31 PM

  16. DHH
    DHH
    • State changed from open to duplicate

    I've added auto-loading of config/routes.rb from all plugins now.

    November 26th, 2008 @ 07:38 PM

  17. James Adam
    James Adam
    • Tag changed from actionpack, edge, enhancement, patch, railties, routing to actionpack, edge, engines, enhancement, patch, plugin, railties, routing

    I think this functionality has real-world use, and would love to see it implemented. I've come up with a simple but clear example of a routing issue which is realistic and problematic given the current simplistic plugin route loading, in this gist

    I spiked locally and came up with a very similar patch, with a bit more flexibility and a few caveats; essentially a plugin (or any loading file) can register one or more 'bundles' of routes, and then the developer can load them at the point they choose.

    In a plugin

    
    ActionController::Routing::Routes.bundle(:my_plugin) do |map|
      map.connect "/login", :controller => "session", :action => "new"
      map.resource :session
      map.resources :users
    end
    

    and in the app

    
    ActionController::Routing::Routes.draw do |map|
       map.bundle :my_plugin
    end
    

    I'm not a huge fan of the currently_loading_plugin stuff, and prefer the explicit naming, but that's a minor quibble.

    There are two hiccups, as far as I can see. The first is that there's no clean way to generate a set of routes without having them append to the RouteSet; this means that when a bundle is mapped, it actually appends the routes to the end of the app routes, and then we have to slice them off and insert them where the bundle placeholder is.

    Secondly, again because of the current architecture of the Mapper/RouteSet, there's no way to pass options into a Mapper. This means that you can do, for example:

    
      map.with_options(:name_prefix => "admin_") do |map|
        map.bundle :my_plugin
      end
    

    because there's no way to pass the options into the Mapper instance.

    However, even with these shortcomings, it feels like useful functionality for developers wanting to share routes in a flexible way.

    May 1st, 2009 @ 06:23 PM

  18. James Adam
    James Adam

    See also #1450 Add way for plugins to map routes - this kind of mechanism could cover the desired "manual when I want it, automatic when I don't care" functionality.

    May 1st, 2009 @ 06:30 PM

  19. James Adam
    James Adam

    Here's my patch, with tests. Works pretty well, I think. The only thing I haven't changed is the doc at the top.

    This patch incorporates functionality from ticket #349 ActiveResource prefix_parameters don't update which describes wanting to manually load routes when specified, and automatically when not.

    May 1st, 2009 @ 06:54 PM

  20. James Adam
  21. jesse (at jesseclark)
    jesse (at jesseclark)

    I like the idea of giving the app developer control over how the plugin routes get integrated instead of automatically having plugin routes override application routes.

    May 18th, 2009 @ 06:58 PM