P Shved
P Shved

Reputation: 99384

Can controller names in RESTful routes be optional?

With a standard map.resource routing mechanics and several nested resources the resultant routes are unnecessarily long. Consider the following route:

site.org/users/pavelshved/blogs/blogging-horror/posts/12345

It's easy to create in routes.rb, and I'm sure it follows some kind of beneficial routing logic. But it's way too long and also seems like it's not intended to be human-readable.

A nice improvement would be to drop controller names, so it looks like:

site.org/pavelshved/blogging-horror/12345

Clear, simple, short. It may become ambiguous, but in my case I'm not going to name any user "users", for instance.

I tried setting :as => '', but it yields routes like this: site.org//pavelshved//blogging-horror//12345 when generating them by standard helpers.

Is there a way to map resources in such a way, that controller names become optional?

Upvotes: 3

Views: 385

Answers (5)

EmFi
EmFi

Reputation: 23450

You're looking for the :path_prefix option for resources.

map.resources :users do |user|
  user.resources :blogs do |blog|
    blog.resources :posts, :path_prefix => '/:user_login/:blog_title/:id'
  end
end

Will produce restful routes for all blogs of this form: site.org/pavelshved/bogging-horror/posts/1234. You'll need to go to a little extra effort to use the url helpers but nothing a wrapper of your own couldn't quickly fix.

The only way to get rid of the posts part of the url is with named routes, but those require some duplication to make restful. And you'll run into the same problems when trying to use route helpers.

Upvotes: 4

Ahmad Ramdani
Ahmad Ramdani

Reputation: 208

Try this

map.pavelshved '/pavelshved/', :controller => :users, :action => view or
map.pavelshved '/:id', :controller => :users, :action => show do | blogs|
  blogs.bloging '/:id', :controller => :blogs, :action => show do | post|
    post.posting '/:id', :controller => :posts, :action => show
  end
end

I hope it work :)

Upvotes: 1

gdelfino
gdelfino

Reputation: 11181

Google "rails shallow routes" for information about this.

Upvotes: -1

Toms Mikoss
Toms Mikoss

Reputation: 9457

Straight out of the default routes.rb:

map.connect 'products/:id', :controller => 'catalog', :action => 'view'

You could write:

map.connect ':user_id/:blog_id/:id', :controller => 'posts', :action => 'show'

But be sure to include that in the very end of the file, or it will try to match every three levels deep url to it.

Upvotes: 1

plainprogrammer
plainprogrammer

Reputation: 594

The simplest way to get what you want would be to create a route in addition to your RESTful routes that acts as a shorthand:

map.short_blog ':user_id/:blog_id/:id', :controller => 'posts', :action => 'show'

You'll have to change the URL bits to work with how you're filtering the name of the user and the name of their blog. But then when you want to use the shorter URL you can use all the short_blog_* magic.

Upvotes: 2

Related Questions