Reputation: 34943
I'm trying to create a nested resource with a url scheme along the lines of: "http://example.com/username/...
".
What I currently have is this:
ActionController::Routing::Routes.draw do |map|
map.home '/', :controller => 'home'
map.resource :session
map.resources :users, :has_many => :nodes
#map.user '/:id', :controller => 'users', :action => 'show', :has_many => :nodes
map.resources :nodes, :belongs_to => :user
end
This results in URLs like:
http://example.local/users/username
http://example.local/users/username/nodes
How to avoid the "users" prefix is beyond me. Passing a "as: => ''
" option to map.resources
doesn't work and it seems named routes don't support the ":has_many
" or ":belongs_to
" options.
Commenting out the "map.resources :users
" and uncommmenting the "map.user
" line after it seems to work… until you reach a nested resource. Then it spits out the following error:
undefined method `user_nodes_path' for #<ActionView::Base:0x1052c8d18>
I know this problem has come up plenty of times before and is always met with "Why would you want to do that?" responses. Frankly, Twitter does it, Facebook does it, and I want to do it too! ;-D
As for the common criticism of how to avoid usernames from conflicting built-in paths, I've set my minimum username length to 6 characters and plan to make all built-in root-level paths segments paths 5 characters or shorter (i.e. "/opt/...
" for options, "/in/...
" for session log-in, etc.).
Upvotes: 1
Views: 1830
Reputation: 14973
See my answer in this related question
Basically, you can pass :path => ''
as an option to negate the identifying segment (Tested in Rails 3 only) Just be aware that this may clash with other routing patterns, so be careful where and how you place it.
Upvotes: 0
Reputation: 146
As noted in this question:
Default segment name in rails resources routing
You should be able to use this plugin:
http://github.com/caring/default_routing
Alternatively, you could specify them manually with something like
map.users '/users', :controller => 'users', :action => 'index',
:conditions => { :method => :get }
map.connect '/users', :controller => 'users', :action => 'create',
:conditions => { :method => :post }
map.user '/:id', :controller => 'users', :action => 'show',
:conditions => { :method => :get }
map.edit_user '/:id/edit', :controller => 'users', :action => 'edit',
:conditions => { :method => :get }
map.new_user '/users/new', :controller => 'users', :action => 'new',
:conditions => { :method => :get }
map.connect '/:id', :controller => 'users', :action => 'update',
:conditions => { :method => :put }
map.connect '/:id', :controller => 'users', :action => 'destroy',
:conditions => { :method => :delete }
map.resources :nodes, :path_prefix => '/:user_id', :name_prefix => 'user_'
# to generate user_nodes_path and user_node_path(@node) routes
That or something like it should give you what you want from map.resources
.
map.resources doesn't work and it seems named routes don't support the ":has_many" or ":belongs_to" options.
Named routes supports has_many, which is used to add another resource level to the URL path. For example
map.resources :users, :has_many => :nodes
generates all the users_path
and user_nodes_path
routes like /users
, /users/:id
, /users/:id/nodes
and /users/:id/nodes/:id
. It's identical to
map.resources :users do |user|
user.resources :nodes
end
Commenting out the "map.resources :users" and uncommmenting the "map.user" line after it seems to work… until you reach a nested resource. Then it spits out the following error:
undefined method `user_nodes_path' for #<ActionView::Base:0x1052c8d18>
That's because map.resources :users, :has_many => :nodes
generates these routes. Only one named route is generated by map.user '/:id', :controller => 'users', :action => 'show'
and that's user_path
.
Upvotes: 2