SitePoint Sponsor

User Tag List

Results 1 to 11 of 11
  1. #1
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    More Routes (Named Routes)

    I have the below routes defined:

    Code:
      	map.platform_first 'software/:platform/:software/:version/',
     		 			:controller => 'user/version',	
     		 			:platform => /windows|macintosh|unix|linux/,
     		 			:action => 'show'
     						
      	map.version_first 'software/:software/:version/:platform',
     		 			:controller => 'user/version',
     		 			:platform => /windows|macintosh|unix|linux/, 	
     			 		 :action => 'show'
    What I'm trying to accomplish, is to be able to change where the platform part of the url is depending on how they navigate to a particular part of the site.

    If they navigate like so:
    view_all_software->software_x->version_x_platform
    I want the url to look like:
    /software/thunderbird/1.1/windows

    But if they navigate like this:
    view_windows_software->software_x->version_x
    I want the url to look like:
    /software/windows/thunderbird/1.1

    I thought named routes would be the solution. If I explicitly call:
    Code:
      <%= version_first_url(:controller => 'version', 
     							 :action => 'show',
     	 		 		 :software => url_case(@software.name), 
     	 		 		 :version => url_case(v.name), 
     	 		 		 :platform => url_case(v.platform.name)) %>
    The router ends up using platform_first instead. It looks like with routes, even if you use a named route, the first route to match, gets used? Is this how routes are supposed to work?

    Thanks,

    -Steven

  2. #2
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am new to Rails. Loving it, but still very much on the steep part of the learning curve. However, Routing is the part of "Agile Web Development with Rails" that I've just read, so....

    I think the easiest way to achieve what you are doing is to use regular expressions to define the correct route. What deferentiates the two url parterns is the position of the 1.1. If the version number is always numbers you should be able to define a regex patern for that part of the url. So perhaps:
    Code:
      	map.platform_first 'software/:platform/:software/:version/',
     		 			:controller => 'user/version',	
     		 			:platform => /windows|macintosh|unix|linux/,
     		 			:version => /[0-9]?\.[0-9]?/,
                                            :action => 'show'
     						
      	map.version_first 'software/:software/:version/:platform',
     		 			:controller => 'user/version',
     		 			:platform => /windows|macintosh|unix|linux/,
                                            :version => /[0-9]?\.[0-9]?/ 	
     			 		:action => 'show'
    I haven't tested that, but I think using Regular Expressions to detect the position of the :version is the way to go. You may have to experiment to get the right syntax.

  3. #3
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What Reggie says is correct - in your example your two routes are essentially the same, just with different parameter names - they are both pointing to the same location though so there is no way for the routing system to distinguish them - therefore the first matching route is used which is normal behaviour.

    As Reggie says you need to distinguish your routes and Reggie's solution of using the fact that the version is a number seems like the best way.

  4. #4
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not so hot with regular expressions but the suggestion does make sense. I'll give it a try.

    Thanks!

    -Steven

  5. #5
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Regular Expressions are very powerful once you get the hang of them. The syntax isn't as daunting as it first appears once you get the hang of it. There are a number of useful resources on the web such as this:

    http://www.greggriffiths.org/webdev/...ex/tester.html

    which is a nice little regular expression tester. There are plenty of other such tools on the web and a some little applications that do the same.

  6. #6
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I've brushed up on regular expressions, and now I can't figure out how the above will help me. As far as I can tell all it does is make sure that the :version portion of the url fits a certain format. How does this hook into the :version location relative to the url?

    BTW, thanks for the link to the regex tester site.....cool

    -Steven

  7. #7
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The map operation lets you define the layout of the URL. So you can say if the url is like this:

    a/b/c

    interpret it like this......

    If it is like this:

    a/c/b

    interpret it like this.....

    However, for the example above the problem the program has is how does it differentiate between the two patterns. Unless you define what makes b different to c, the program can't tell the difference between george/22/mable and george/mable/22.

    In the section after the initial pattern description you have the opportunity to effectively say "and by the way this is what a c is like, and/or this is what b is like".

    So if in both map definitions, you then define
    :c => /[0-9]*/

    this is saying c must contain at least one numeric character. (in Javascript something like this would mean c must contain a numeric character. You would have to add start of string and end of string definitions to say "the whole of c must only contain numbers". If this is what is required this would be a better pattern to use:
    :c => /^[0-9]*$/

    I'm not sure how specific you would need to be with Rail's map object. You may have to experiment. In general you are better being more specific with your patterns)

    Now the system knows what a c element looks like. So when it sees:

    george/22/mable

    only the second element has numbers, so this must be the c element, and therefore this must be an a/c/b mapping.

    george/mable/22 must be an a/b/c mapping.

    george/henry/mable doesn't fit either mapping. So the system will look for another mapping or revert to default.

    george/22/33 could be either a/b/c or a/c/b, so the system will pick the first.

  8. #8
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I this makes sense. But if I use the link_to method in a view:

    Code:
       <%= link_to('link', :a=>'george', :b=>'22', :c=>'marble') %>
    No matter what I do, link_to will always match on the first one and generate the link to look like "/george/marble/22" .....unless I hard cod the link and I would like to avoid that. What I was hoping, was to be able to have something like:

    Code:
       map.link1 '/:controller/:action/:id',
       	  :action=>/[a-z]/,
       	  :id=>/\d+/
       
       map.link2 '/:controller/:id/:action',
        	  :action=>/[a-z]/,
        	  :id=>/\d+/

    then my view do:
    <%= link_to('link', link2_url( :id=>'22', :action=>'george'))

    the rules for :action and :id will always be the same, however sometimes when using the link_to method or the xxxx_url method, I want to be able to get it to match on the map.link2 instead of the map.link1. If I am understanding how this work correctly, then I don't think it is possible. Either way, I really appreciate your help.

  9. #9
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The good news: I think I understand what you are saying.

    If you view a page via an a/b/c URL, you want links in that page to preserve that format. So if a user clicks on a link in that page they go to another a/b/c formatted URL.

    However, if you get to the page via an a/c/b URL the links in the page should use the same URL format. Click on them will take you another a/c/b URL.

    Bad news: I don't know how to achieve that without interogating the URL and using an If statement.

  10. #10
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It might be worth looking at the options for url_for rather than link_to. That might give you some more flexibility.

  11. #11
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, that's exactly what I'm trying to do. If I figure out a solution, I'll post it. Thanks for all the help!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •