Routes: How would default routes be defined manually?

I am quite new to rails and even after reading the docs to routes I still do not manage to simply duplicate the new route: <%= link_to ‘New Priority’, new_priority_path %> → <%= link_to ‘Add Priority’, add_priority_path %>

resources :priorities do member do get ‘add’ end

rake routes: add_priority GET /priorities/:id/add(.:format) vs. new_priority GET /priorities/new(.:format)

Is there any doc how the 7 default routes would be declared, especially new and create, if I would want to duplicate them (I don’t, I just want to understand :wink: )

I think you forgot end over there …

resources :priorities do

member do

get ‘add’

end

end

also to check your routes, do

rake routes

on your rails root

Ahmy Yulrizka

No, I just failed on copy/paste and lost the end in the original post when removing the up-route :confused:

resources :priorities do member do get ‘up’ get ‘add’ end

collection do
 
end 

end

rake routes (complete) up_priority GET /priorities/:id/up(.:format) {:controller=>“priorities”, :action=>“up”} add_priority GET /priorities/:id/add(.:format) {:controller=>“priorities”, :action=>“add”} priorities GET /priorities(.:format) {:controller=>“priorities”, :action=>“index”} priorities POST /priorities(.:format) {:controller=>“priorities”, :action=>“create”} new_priority GET /priorities/new(.:format) {:controller=>“priorities”, :action=>“new”} edit_priority GET /priorities/:id/edit(.:format) {:controller=>“priorities”, :action=>“edit”} priority GET /priorities/:id(.:format) {:controller=>“priorities”, :action=>“show”} priority PUT /priorities/:id(.:format) {:controller=>“priorities”, :action=>“update”} priority DELETE /priorities/:id(.:format) {:controller=>“priorities”, :action=>“destroy”} root /(.:format) {:controller=>“priorities”, :action=>“index”}

Im trying to figure out what is it that you want. And if im not mistaken, you want to add priority to behave the same as new_priority. when you declare resource , rails automaticly assign 7 route respect to REST the member method inside of the resource would apply to single instance of the resource so you get for examlpe when you define member do get ‘up’ get ‘add’ end you will get: /prioriteis/:id/add but when you define collection do get ‘add’
end you will get /priorities/add also if you dont specify aditional parameter, rails would create a route name same as the get paramter get ‘add’ would create add_priorities route and map it to priorites#add add is referring to the get parameter and _priorities referring to the resource you could also specify a parameter to custom map your route. for example if you want the add route is handled by create action on priorities controller, then you could specify the method like this

get ‘add’ => ‘priorities#create’

you could also custom the name of the path using :as parameter

get ‘add’ => ‘priorities#create’, :as => my_custom_add

Hope its help

Thank you! Your post is really helpful. As mentioned above, I just want to understand how I would declare the 7 REST routes if they would not have been declared for me, e.g. new1 (add in my example), edit1, … If I declare add as a collection route, this statement throws an error <%= link_to ‘Add Priority’, add_prioritypath %> (taken from originally created code : <%= link_to ‘New Priority’, new_priority_path %>) <%= link_to ‘Add Priority’, addpriorities_path %> works as expected.

My original question was: what is my definition missing compared to the original new?

Second, I find this very interesting: get ‘add’ => ‘priorities#create’, :as => my_custom_add In this form I get an error, the same with :my_custom_add.

when you specify route inside resource, AFAIK

if you specify the route inside “collection”, rails will always append ies like priorities

if you specify the route inside “member”, rails will always use the singular word liake priority

so in that way, one solution (but i dont know if this the best way to do it). is define custom route outside the resource block. such as.

resources :priorities do

end

get ‘/priorities/add’ => ‘priorities#new’, :as => :add_priority

this will give routes

priorities GET /priorities(.:format) {:action=>“index”, :controller=>“priorities”}

POST /priorities(.:format) {:action=>“create”, :controller=>“priorities”}

new_priority GET /priorities/new(.:format) {:action=>“new”, :controller=>“priorities”}

edit_priority GET /priorities/:id/edit(.:format) {:action=>“edit”, :controller=>“priorities”}

priority GET /priorities/:id(.:format) {:action=>“show”, :controller=>“priorities”}

PUT /priorities/:id(.:format) {:action=>“update”, :controller=>“priorities”}

DELETE /priorities/:id(.:format) {:action=>“destroy”, :controller=>“priorities”}

add_priority GET /priorities/add(.:format) {:action=>“new”, :controller=>“priorities”}

btw, im using rails 3, i don’t know if there’s different with the 2.x version

Ahmy Yulrizka

Bourne,

In your example, add is like new. It should not be a member action, it is a collection one.

I think what you are asking for is a bit more elaboration of the default REST routes.

When you do:

resources :priorities

This will generate the 7 default routes. which are two types:

  1. Member (you are operating on a specific instance of the priorities). and those are: Show, Edit, Update, Destroy
  2. Collection, Where you operate on prorities in general, but not an existing one of them. which is :index, :new, :create

for member based actions, the paths generated in a singular form and expects the ID to be passed. so

add_priority_path # wrong, you have not provided an id or an instance of Priority

add_priority_path(object) # should work, but this is not what u want.

new_priority_path is actually a collection. the route will be /priorities/new

Given that you already know what we mentioned. and the correct usage is

resources :priorities do

collection do

get ‘add’

end

end

I think what confuses you is: “why is it add_priorities_path and not add_priority_path like the new_priority_path” (in a singular form)?

is that right ?

Correct :slight_smile: (I know that this behaviour is fine for collections but I want to understand why new is different and how to declare it to be identical)

that’s interesting, apparently there is 3rd type other than collection and member that is specific to the new.

if u checked at actionpack-3.0.3/lib/action_dispatch/routing/mapper.rb:953

you can how the default routes are added:

collection do

get :index if parent_resource.actions.include?(:index)

post :create if parent_resource.actions.include?(:create)

end

new do

get :new

end if parent_resource.actions.include?(:new)

member do

get :edit if parent_resource.actions.include?(:edit)

get :show if parent_resource.actions.include?(:show)

put :update if parent_resource.actions.include?(:update)

delete :destroy if parent_resource.actions.include?(:destroy)

end

I’m not sure if you can use the “new” on your own. try it and let me know how it goes :slight_smile:

it won’t work, it will be

add_new_priority GET /priorities/new/add(.:format) {:action=>“add”, :controller=>“priorities”}

however, the collection plural form seems more logical to me, you are adding a priority to priorities. so you are actually acting on priorities

This is interesting,

it doesn’t work because if you call

member,

the resource mapper call member_scope, which in turn yield

# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 503

def member_scope
  "#{path}/:id"
end

but the new is very special method, it call new_scope which in turn yield

# File 'actionpack/lib/action_dispatch/routing/mapper.rb', line 507

def new_scope(new_path)
  "#{path}/#{new_path}"
end

http://rubydoc.info/docs/rails/3.0.0/ActionDispatch/Routing/Mapper/Resources#shallow-instance_method

Ahmy Yulrizka