starfry
starfry

Reputation: 9943

Is there a way to create a Rails resource route called `index`?

I want to add a resource route called index to a Rails 4 application but the generated routes aren't as expected. However, if I use another name (such as show_index), they are. To demonstrate, I'll begin with a vanilla Rails app that has no routes:

$ rake routes
You don't have any routes defined!

I add the below into config/routes.rb:

  resources :items

Which produces the following resourceful Rails routes:

   Prefix Verb   URI Pattern               Controller#Action
    items GET    /items(.:format)          items#index
          POST   /items(.:format)          items#create
 new_item GET    /items/new(.:format)      items#new
edit_item GET    /items/:id/edit(.:format) items#edit
     item GET    /items/:id(.:format)      items#show
          PATCH  /items/:id(.:format)      items#update
          PUT    /items/:id(.:format)      items#update
          DELETE /items/:id(.:format)      items#destroy

The application has a show action that can render a so-called index if the parameter hash contains {with: 'index'} (this index is an application-specific thing, rather than a collection of items or anything like that).

I add a custom index route to invoke the show action with the additional parameter:

  resources :items do
    get 'index' => 'items#show', with: 'index'
  end

This produces a new route but it has item_id instead of the expected id (compare with edit_item in the list above):

item_index GET    /items/:item_id/index(.:format) items#show {:with=>"index"}

The Routing documentation explains that the way to get :id is to use on: :member, so the route would need to be

get 'index' => 'items#show', with: 'index', on: :member

but that doesn't produce the expected results. It adds the expected route but it steals the item method prefix from the default show action instead of using its own index_item (again, compare with edit_item in the list above):

item GET    /items/:id/index(.:format) items#show {:with=>"index"}
     GET    /items/:id(.:format)       items#show

However, had I used something other than index, such as show_index, then it would work as expected:

get 'show_index' => 'items#show', with: 'index', on: :member

produces

show_index_item GET    /items/:id/show_index(.:format) items#show {:with=>"index"}

So there is a difference in behaviour when the route is called index. I expect this is because the implied resources routes use that name, although I don't think they use it in a way that would clash. It looks to me like I should be able to add a new index route which would become index_item (similar to the exisitng edit_item and in contrast to the existing item_index).

I know I can work around the problem, as I have demonstrated, by using a different name. But index reads better than show_index.

So my question asks is it possible to specify a resource route with index that is keyed off :id ? `

Upvotes: 0

Views: 1282

Answers (1)

Малъ Скрылевъ
Малъ Скрылевъ

Reputation: 16507

To set specific url use as key word, so try something like:

get 'index' => 'items#show', with: 'index', on: :member, as: 'item_index'

or one of course on your wish.

Upvotes: 1

Related Questions