This project is archived and is in readonly mode.

#4334 ✓wontfix
garrett

to_param and <resource>_path() escapes forward slashes

Reported by garrett | April 6th, 2010 @ 04:45 PM | in 3.0.2

I've got a problem where I have a model with a to_param method. The to_param returns a string which contains forward slashes such as 'foo/bar'

when the model instance is passed into the url_for() or _path() methods the foo/bar gets escaped to foo%2Fbar which in some instances is undesirable.

Passing url_for(@model, :escape => false) does not work either

Cheers!
Garrett

Comments and changes to this ticket

  • garrett

    garrett April 6th, 2010 @ 04:45 PM

    I should have mentioned this is in Rails 3.0 beta 2

  • José Valim

    José Valim April 10th, 2010 @ 12:45 PM

    • State changed from “new” to “invalid”

    It's correct for the default behavior to be escaping.

  • José Valim

    José Valim April 10th, 2010 @ 01:09 PM

    • Assigned user set to “José Valim”
  • garrett

    garrett April 10th, 2010 @ 02:39 PM

    Hi Jose

    That makes sense alright. But there's no way to disable the escape. The escape on url_for() doesn't seem to work either.

    Thanks
    Garrett

  • José Valim

    José Valim April 10th, 2010 @ 02:50 PM

    • Milestone cleared.
    • State changed from “invalid” to “new”

    A-ha, that makes sense. I'm reopening it. Can you try a patch or a failing test case?

  • Nathaniel Bibler

    Nathaniel Bibler April 11th, 2010 @ 03:47 AM

    I'm curious what the valid use case is for this functionality. Maybe I'm misunderstanding the issue.. but when would it be useful to indicate to Rails that an object's resource identifier has a forward slash? That would adversely affect route generation for a resource and seems to me that this would break the traditional ideas/implementation of REST.

  • garrett

    garrett April 12th, 2010 @ 12:36 PM

    It's a good question Nathaniel and I'm glad to give you my own personal case.

    Basically take any hierarchical model (in my case a set of Areas or Regions) where you're wanting to use some property other than it's database id in the url (to_param).

    Use Dublin as the example. It has inner regions such as Phibsboro, Cabra, Ranelagh, Castleknock, Whitehall, etc. Which could logically be further subdivided.

    basically you want the url for the resource to behave like this:

    /areas/dublin - displays all data for dublin and its inner areas /areas/dublin/whitehall - refines the data for this inner area only

    the fact is, there's more than one city with a region called Whitehall. London would be one.

    /areas/london/whitehall.

    /areas/whitehall actually makes no sense on its own and having a url such as /areas/london_whitehall just isn't the experience you're after.

    You could perhaps argue that these should be split out into separate models but that would mean you need a new model for every level of subdivision?

    As we know, REST has no rules about what an identification must conform to other than that it can uniquely identify the resource. In this case the hierarchical path to the resource is this unique identifier.

    anyways, thats my take on it. Opinions welcomed.

  • Aupajo

    Aupajo April 12th, 2010 @ 01:01 PM

    garret,

    Could you use match "/areas/*locales" => "areas#show" in your routes? That value should then be accessible through params[:locales]. At least, according to the edge docs note on route globbing.

  • Andrew White

    Andrew White April 12th, 2010 @ 01:03 PM

    I think you're digging yourself a big hole trying to do it with resources. What happens to the edit and new actions? e.g:

      # need the :id regex to get the route to be recognized
      resources :areas, :id => /.+/
    
      # GET /areas/uk/england/new 
      # -> {"action"=>"show", "id"=>"uk/england/new", "controller"=>"areas"}
    

    If you are just using it for showing areas then just use standard routes:

      get 'areas/*id' => 'areas#show'
    
  • garrett

    garrett April 12th, 2010 @ 01:16 PM

    Hi Andrew

    I agree completely that in the current mechanism its a bit difficult. It's probably workable with a more sophisticated regex match.

  • José Valim

    José Valim April 25th, 2010 @ 09:26 AM

    So can I mark this as invalid?

  • Andrew White

    Andrew White April 25th, 2010 @ 04:01 PM

    Actually more wontfix rather than invalid as doing the following escapes the path:

    # config/routes.rb
    match "/*path" => "pages#show", :as => :page
    
    # rails console
    >> include Rails::Application.routes.url_helpers
    
    >> page_path("path/to/page")
    => "/path%2Fto%2Fpage"
    
    >> page_path(%w(path to page))
    => "/path/to/page"
    

    However it can't be fixed as the code that does the escaping can't know about type of segment. The best workaround is to override the url helper, e.g:

    # app/helpers/application_helper.rb
    def page_path(path, options = {})
      super(path.split('/'), options)
    end
    
    # rails console
    >> include Rails::Application.routes.url_helpers
    >> include ApplicationHelper
    
    >> page_path("path/to/page")
    => "/path/to/page"
    

    One thing that is surprising to me is that while Rack::Mount does the actual url generation it doesn't appear to do any parameter escaping.

  • José Valim

    José Valim April 25th, 2010 @ 04:02 PM

    • State changed from “new” to “wontfix”
  • Jeremy Kemper

    Jeremy Kemper October 15th, 2010 @ 11:01 PM

    • Milestone set to 3.0.2
    • Importance changed from “” to “Low”

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="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages