Warning: Creating default object from empty value in /homepages/39/d161420129/htdocs/p373.net/wp/wp-content/themes/p373b/admin/functions.php on line 183
Forget pretty urls, how about vain gorgeous urls

Forget pretty urls, how about vain gorgeous urls

In Rails, resource based urls are by default not pretty.  For example, say you have the following routing

     resources :projects do
       resources :users
     end

This yields urls

     /projects
     /projects/1
     /projects/1/users
     /projects/1/users/1

So to make pretty urls, its pretty trivial.  Just implement #to_param on the project model and user model

     #app/models/project.rb
     class Project < ActiveRecord::Base
       …
       def to_param
         slug #selected by user
       end
     end

     #app/models/user.rb
     class User < ActiveRecord::Base
       …
       def to_param
         slug #selected by user
       end
     end

This will now yield urls as

     /projects/sony
     /projects/sony/users/mary

However, it seems silly to me always have “projects” and “users” in the url.  Can’t we just have

      /sony/mary

Of course we can.  Here’s the full code and below I’ll explain in detail below

     # routes.rb
     match "/projects" =&gt; "projects#index", as: "projects" 
     match "/users" =&gt; "users#index", as: "users" 
     resources :projects, path: "", path_names: {new: "projects/new", create: "projects/create"}, except:[:index] do
       resources :users, path: "", path_names: {new: "users/new"}, except:[:index, :create]
     end

<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">So, the main idea here is that we change the path argument to an empty string which gets rid of "projects" and "users" from the url.  However, this presents a couple of problems with the index, new, and create actions as these are not scoped to an object and need to have the "/projects" and "/users" in the url so the request knows what controller we're talking about.  </span>

This is easily achieved by changing the “path_names” argument for the new and create actions.  For some reason, the index action needs to be listed as a separate route.  I’m not sure why but this is what I did to get it to work.

Voila, gorgeous urls.

GOTCHA: if you add extra member or collection routes or even other nested resource routes, they must be listed ABOVE the resources that will be utilized in this fashion, otherwise, that resource name will be matched as the id for a user.

     # routes.rb
     match "/projects" => "projects#index", as: "projects" 
     match "/users" => "users#index", as: "users" 
     resources :projects, path: "", path_names: {new: "projects/new", create: "projects/create"}, except:[:index] do
       resources :users, path: "", path_names: {new: "users/new"}, except:[:index, :create]
       resources :tasks #WRONG! /sony/tasks will think that "tasks" is a username…put above the "resources :users, …" line
     end

 

    This entry was posted in Coding, Ruby/Rails, Technology. Bookmark the permalink. Both comments and trackbacks are currently closed.