This project is archived and is in readonly mode.

#183 ✓invalid
Amol Hatwar (rubygem)

strange link_to behavior on links to controllers in modules

Reported by Amol Hatwar (rubygem) | May 13th, 2008 @ 06:42 PM

This happens in the ERB template in the current edge as well as 2.0.2. This behavior is strange, and shouldn't happen...

First Invocation

<%=link_to('First Link', :controller => 'first/link')%>

# Generated HTML
# <a href="/first/link">First Link</a>

Successive Invocation (in the same ERB Template)

<%=link_to('Second Link', :controller => 'second') %>

# Generated HTML
# <a href="/first/second">Second Link</a>

There's a URL fragment stuck in the second URL which has been actually passed to link_to in the first invocation.

link_to shouldn't be working in this way...

Comments and changes to this ticket

  • Amol Hatwar (rubygem)
  • Amol Hatwar (rubygem)

    Amol Hatwar (rubygem) May 13th, 2008 @ 09:18 PM

    Attached test patch that confirms the said behavior...

  • Amol Hatwar (rubygem)

    Amol Hatwar (rubygem) May 18th, 2008 @ 05:42 AM

    If someone can confirm that this indeed is a *bug*, maybe I can work towards a patch that fixes it...

  • nikz

    nikz August 5th, 2008 @ 12:33 PM

    • Tag set to helper

    Hey Amol,

    The relevant code is in /actionpack/lib/action_controller/routing.rb on line 348:

          # Returns a controller path for a new +controller+ based on a +previous+ controller path.
          # Handles 4 scenarios:
          # * stay in the previous controller:
          #     controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
          # * stay in the previous namespace:
          #     controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
          # * forced move to the root namespace:
          #     controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
          # * previous namespace is root:
          #     controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
          def controller_relative_to(controller, previous)
            if controller.nil?           then previous
            elsif controller[0] == ?/    then controller[1..-1]
            elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}"
            else controller

    From that, it looks the current behaviour is intended. Perhaps bring up a discussion on the mailing list?

    Also, just by the bye, your test fails for me, but not for the reason you describe. The first link_to call just generates "", rather than a route at all. (That's on the latest edge rails).

  • nikz

    nikz August 5th, 2008 @ 12:40 PM

    Actually, upon further investigation, that method isn't called anywhere! (nowhere I can grep for, anyways).

    Regardless, the REAL (slim shady) relevant section is in route_set.rb (line 322).

            # if the controller has changed, make sure it changes relative to the
            # current controller module, if any. In other words, if we're currently
            # on admin/get, and the new controller is 'set', the new controller
            # should really be admin/set.
            if !named_route && expire_on[:controller] && options[:controller] && options[:controller][0] != ?/
              old_parts = recall[:controller].split('/')
              new_parts = options[:controller].split('/')
              parts = old_parts[0..-(new_parts.length + 1)] + new_parts
              options[:controller] = parts.join('/')

    Looks like the intended behaviour is what you're seeing :)

    Maybe someone can close this ticket?

  • Pratik

    Pratik August 5th, 2008 @ 12:59 PM

    • State changed from “new” to “invalid”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>

People watching this ticket