Rails 3 route appends _index to route name - ruby-on-rails

I am migrating a Rails 2.3.8 version to Rails 3.0 and so ive rewritten my routes file. When i list the routes using rake routes, i see some route names have _index appended to them. I cant figure out why this is.
Relevant routes:
Rails 2.3.8:
map.namespace "tracker", :path_prefix => "" do |planner|
planner.resources :planner, :collection => {:step1 => :get,
:add => :get,
:unsubscribe => [:get, :post] }
end
Rails 3.0 route:
namespace "tracker", :path => "" do
resources :planner do
collection do
get :step1
get :add
get :unsubscribe
post :unsubscribe
end
end
end
Output from rake routes
Rails 2.3.8
step1_tracker_planner GET /planner/step1(.:format)
add_tracker_planner GET /planner/add(.:format)
unsubscribe_tracker_planner GET /planner/unsubscribe(.:format)
POST /planner/unsubscribe(.:format)
Rails 3.0
step1_tracker_planner_index GET /planner/step1(.:format)
add_tracker_planner_index GET /planner/add(.:format)
unsubscribe_tracker_planner_index GET /planner/unsubscribe(.:format)
POST /planner/unsubscribe(.:format)
Any ideas as to why this _index is being added would be much appreciated.

It is because your resource is named :planner instead of :planners that Rails decided to add the _index to any collection nested underneath. My guess it is there for readability.
The action named in the collection normally translates to a verb, so I can see why this makes sense. Take the typical photos resource example given in the routing docs:
resources :photos do
collection do
get 'search'
end
end
search_photos GET /photos/search(.:format)
But if instead we called the resources 'photo'...
resources :photo do
collection do
get 'search'
end
end
search_photo_index GET /photo/search(.:format)
In the first case, you search the "photos", and in the second case you search the "photo index".

You should be using either resource :planner either resources :planners depending on what you need. To learn about singular resource and it differences check out Rails Guides.

Following on from Semyon Perepelitsa's response, note that resource :planner expects the controller's name is PlannersController, whereas resources :planners expects PlannerController.
If you don't want to rename your controller when changing from resources to resource, you can override the default by specifying resource :planner, controller: :planner.

Related

Named routes inserting a . instead of a /

I've been having trouble with named routes in rails 4 (Named route for non resource nesting).
I've moved onto something else, but still struggling with the same problem of named routes for non resource urls.
This is my route from rake routes:
GET /messages/:id/report/:reply_token(.:format) messages#report
messages POST /messages(.:format) messages#create
and my routes.rb
resources :messages, only: [:create] do
member do
get 'report/:reply_token', :action => 'report'#, :as => :message
end
end
Because of the problem I had in my post linked at the top, I'm trying to get a url to the /messages/:id/report/:reply_token route by doing the following:
"#{messages_url(#message, :host => "localhost:3000")}/report/#{#message.reply_token}"
But it's giving me this:
http://localhost:3000/messages.110/report/6bBw22TdaRYcQ3iVzW1ZwA
Why is there a . between the 'messages' and the '110' (message_id)?
Instead of #message, I've also tried #message.id in the messages_url(). I've also tried this: report_message_path(message_id: #message.id, reply_token: #message.reply_token) but got the same error as in my question linked above. I've also tried message_url() instead but it gives undefined method 'message_url'.
You are mixing up routes. messages_url is to generate a URL for create action which does not have ID in its route. Rails assumes 110 is the format and uses the second route (which is named as messages)
messages POST /messages(.:format)
As a solution, name your route like this and also add show action
resources :messages, only: [:create,:show] do
member do
get 'report/:reply_token', :action => 'report' , :as => :custom_message
end
end
And,
custom_message_url(#message, :host => "localhost:3000")
More about naming routes here.
Answerd here already - Rails _path helper generating path with format not id

Ruby on Rails Route

how can I generate a RoR route like this one:
Prefix: gateway
verb: post
URI Pattern: /region/:id/gateway
Controller#Action: region#gateway
I tried with
resources :region, :only => :show do
post :gateway, :only => :show
end
but is generating by default a route to show the regions
/region/:id(.:format)
I want to skip the regions show action and only keep it the /region/:id/gateway route
post "gateway/region/:id/gateway" => "region#gateway"
Have a look to Rails routing documentation. It's well documented.
If You want to use resources, You may write:
resources :region do
member do
post :gateway
end
end
It will be recognized as:
region/:id/gateway
You can't use "only" because it reduce to one action!

Upgrading routes in Rails 3

Currently I have something like this:
resources :books do
collection do
get 'search'
end
end
and my controller name is also "books" and I have a action method called "search" inside it
I would like that "get search" part to also be a resource, kind of like nested resources... but I don't want to break other peoples codes that are using the current route that this generate, so need to update it in a passive way!
resources :books do
collection do
get 'search'
end
resources :searches
end
...if I'm understanding you correctly, that should be what you want. It won't break other routes, just add new ones.
Run rake routes to make sure you have all the routes you want/need.
Use shallow routes nesting like:
resources :books , :shallow => true do
resources :searches
end
Now you will get the following routes:
/books/1 => books_path(1)
/books/1/searches => books_searches_index_path(1)
/searches/2 => searches_path(2)
Similarly you can get separate routing for defined routes like:
get '(:books)/searches', :to => 'books#index'

RESTful route overriden by named route

When defining a resources in routes.rb in Rails, I have the following problem: My resource supports the standard CRUD operations and has a custom function/route, which allows filtering. Now this custom routes matches the edit route and jumps in before the actual RESTful route.
Is there a way to prioritize the RESTful routes so that they match first?
resources :items do
get ':category(/:level)', :action => :filter, :on => :collection, :as => 'filter'
end
You should just set a simple get route ( if it is a GET request )
get 'filter', :to => "items#filter"
If you have any problems there are always RoR Guides :)
http://guides.rubyonrails.org/routing.html

My routes has resources :home, but rspec is saying routes not defined?

My homecontroller has:
def about()
end
And I have a rspec test that does GET 'about' and it fails saying that there is no route that matches.
doesn't this map all actions in the controller:
resources :home
or do I have to explicitly state each action in the home controller?
resources :home sets up the default RESTful routes - index, show, new, create, edit, update, and destroy. Any additional routes have to be specified. It looks like you're adding a simple collection route, so you'd specify it like this:
resources :home
collection do
get 'about'
end
end
This will give your the route '/home/about'. I assume this is Rails 3. If you're in Rails 2.x, do it like so:
map.resources :home, :collection => {:about => :get}
And from the command line, you can always see what routes you have available with this command:
rake routes
I hope this helps!
EDIT: If you want a default route, you can add this:
match ':controller(/:action(/:id))'
This is a default route that will match any generic requests.
FULL ARTICLE: Routing in Rails 3 is its own beast. There have been a lot of questions about it lately, so I've created a very detailed article with code samples to help others:
Routing in Ruby on Rails 3
I created a companion Rails 3 app that can be downloaded to play around with, as well:
https://github.com/kconrails/rails3_routing
If you have any questions, please hit up my site and ask. Thanks!
resources will give you the 7 CRUD methods for a controller, if you want additional actions, you need to do something like the following:
resources :homes do
collection do
match "about" => "homes#about", :as => "about"
end
end
Then you'll also have an additional about_homes_path/url helper available.

Resources