Rails Routing - :resource_id vs :id - ruby-on-rails

In my routes.rb:
resources :posts do
get "test"
end
This produces the usual RESTful routes with /post/:id/.... However, I also get /post/:post_id/test.
Now my problem is that sometimes the parameter is named :id and sometimes it is :post_id. How can I make it uniform?
Thank you!

Specify :on => :member, otherwise it is acting as a nested resource.
resources :posts do
get 'test', :on => :member
end

You shouldn't make it uniform. It's :id when it's the target resource and :post_id when it is the parent of some other target resource (i.e. nested resources). This is a Rails convention.

Related

what does this rails code do? :on => :member

please can you explainme what does this code do?
resources :products do
get :who_bought, :on => :member
end
the code complete is from the book pragmatig programing, but it not explain why we use that code, ":on => :member""
Depot::Application.routes.draw do
resources :orders
resources :line_items
post 'line_items/decrease'
resources :carts
get "store/index"
resources :products do
get :who_bought, :on => :member
end
root :to => 'store#index', :as => 'store'
thanks
passing :on => :member means that you are working on a specific record in the database, in this case products. so the url that route generates is
/products/:id/who_bought
which means that you want the get the product whose id is :id and process the who_bought action. the counterpart, :on => :collection, expects the action to work on a list of products so the url will look like
/products/who_bought
if you change member to collection. you can see that the route doesn't require an :id passed because it doesn't expect you to work on a single record.

Simple Rails routing, doing a get 'action' inside resource block

Consider this in routes.rb
resource :places do
resource :people
get 'search'
end
When I do this in browser:
localhost:3000/places/search
It gives me invalid id for place error.
I'm looking to do this without using a "match"
You need to specify that the get applies to the collection:
resource :places do
resource :people
get 'search', :on => :collection
end
See the documentation on collection routes for details.
resources :places do
resources :people
get 'search', :on => :collection
end

Rails Specific Resources

I know in rails i can say
resources :articles do
post :something
end
but this would give the regular routes, plus :something, what if i wanted to specify only post :something, or what if wanted to exclude a particular resource, but keep the rest (in my case i am trying to kick out delete)
resources :articles, :except => :destroy do
post :something
end
I think you can just use except
resources :articles, :except => [:destroy]
The other answers are right, but you should check the Guide to Rails Routing (linked you to the section on restricting routes) for more information on what options are available.

Exposing a Specific Action of a Nested Route

Using this as an example contexted:
Post has_many comments
Comment belongs_to post
I have a route that looks like:
resources :posts do
resources :comments
end
How do i create a route that exposes comments#index?
An example use case would be... I want to list ALL comments in the system on a page. Essentially using the comments resource as if it's not nested when a user hits /comments
thank you!
Try this.
resources :posts do
resources :comments, :except => :index
end
match 'comments' => 'comments#index', :as => :comments
That said, I usually look to avoid routes like this because I like a tidy RESTful routes file, but sometimes it can't be helped.
Second option:
resources :posts do
resources :comments, :except => :index
get :comments, :on => :collection
end
In the second option, you'd want to remove the index action from the comments controller and create a comments action in your posts controller.

How do you add a custom route to a singleton resource?

map.resource :basket, :collection => { :checkout => :post }
The above does not work for a resource, as you would expect since basket is a resource (ie. singular) not resources, so there is no concept of a collection, everything should be scoped to the current_user. In this case User has_one Basket.
However I would like to specify a custom route without having to resort to adding another line in routes, eg:
map.checkout 'basket/checkout', :controller => 'baskets', :action => 'checkout'
Is this possible?
Of course my other option is to add a checkouts controller.
Just use :member option instead of :collection:
map.resource :basket, :member => {:checkout => :post}
If the basket is scoped to the user I'd make it a nested resource:
map.resources :users do |users|
users.resource :basket, :member => { :checkout => :post }
end
... or in Rails 3 ...
resources :users do
resource :basket do
post :checkout, :on => :member
end
end
This way you'll be able to scope the basket to the user who's checking out. The URL will end up looking like this:
/users/5/basket/checkout
You also get the nicely worded named route 'checkout_user_basket'.

Resources