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.

Namespaced controllers only work with namespaced routes

#7

I have two resources:

map.resources :events do |event| event.resources :participants, :controller => 'events/participants'
end

As you can see Participants controller is namespaced under 'events' just to keep things organized (I've got many other controllers like that). The route is not namespaced but only nested.

When I access '/events/4/participants', it blows up with 'wrong constant name 4' trying to classify '4'. The reason is that RequestPathIntrospection#namespace_segments assumes that controller's namespace will be present in the request_path as a static prefix, just like namespaced routes do it. It is not true in the case above.

The fix:

I think that #namespace_segments should be more selective and only assume that the namespace prefix is in the path if it is immediately followed by the current segment. See the implementation below.

The catch:

If parent resource ('events' in my case) is a singleton, this would still not work as request path would exactly match namespaced controller's path and '/event' would get chopped off. I do not have a better solution at this point, and I am not likely to look for it, as it is not the case in my application.

      def namespace_segments
        namespace = controller_path.sub(%r(#{controller_name}$), '')
        request_path =~ %r(^/#{namespace}/#{current_segment}) ? namespace.split('/') : []
      end

Reported by sserdyuk · September 29th, 2009 @ 11:11 PM

State: new
Milestone: none
Assigned to: Ian White Ian White

Activity

  1. Ian White
    Ian White

    Yes, this feature is designed with the :namespace option in mind. I can see that your intended use should be supported though.

    How about an option :extract_namespace, which defaults to true, but could be turned off

    
      class Events::Participants < ApplicationController
        resources_controller_for :participants, :extract_namespace => false
      end
    

    September 30th, 2009 @ 07:32 AM

  2. Ian White
    Ian White

    I think that #namespace_segments should be more selective and only assume that the namespace prefix is in the path if it > is immediately followed by the current segment. See the implementation below.

    I don't think this approach will work in the case where a controller is invoked with a wildcard nesting path (a common use case)

      map.namespace :admin do |admin|
        admin.resources :forums 
        admin.resources :users, :has_many => :forums
      end
    
      class Admin::ForumsController
        resources_controller_for :forums
        # this controller handles /admin/forums, and /admin/users/:id/forums
      end
    

    When requesting '/admin/forums/1' your proposal works fine, but when requesting '/admin/users/1/forums' it will break as the namespace won't be processed.

    So, would you be happy for an option which turns namespacing off completely? (as outlined above)

    September 30th, 2009 @ 07:47 AM

  3. Ian White
    Ian White

    btw. namespace processing is required for routes created with :namespace, because of the name prefixes routing creates for named routes.

    September 30th, 2009 @ 07:49 AM

  4. sserdyuk
    sserdyuk

    ':extract_namespace => false' seems like a bad hack to me, especially because all this specified in routes. Have you ever considered aliasing ActionController::Routing::Routes#draw and getting the real picture from the source? I just tried it in 2.3.4 and aliasing from plugin's init.rb worked.

    October 2nd, 2009 @ 11:46 PM

  5. Ian White
    Ian White

    Hi,

    I have been trying to move away from relying on rails routing internals for rc, since these are part of the private API, and subject to change resulting in weird breakage.

    But, perhaps my approach is not the same as yours. Could you make a fork on github with the changes you mention above, as a proof of concept please?

    Cheers,
    Ian

    October 8th, 2009 @ 02:01 PM

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.