Rails resourceful routes all point to index action? - ruby-on-rails

I'm runnng Rails 2.3.8.
I set up map.resources :users in my routes.rb file.
When I run rake routes it shows:
users GET /users(.:format) {:action=>"index", :controller=>"users"}
GET /users(.:format) {:action=>"index", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"index", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"index", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"index", :controller=>"users"}
GET /users/:id(.:format) {:action=>"index", :controller=>"users"}
GET /users/:id(.:format) {:action=>"index", :controller=>"users"}
/:controller/:action/:id
/:controller/:action/:id(.:format)
Sorry about the formatting. But the point is... 1) where are my "PUT", "POST", etc. routes?, 2) Why does everything point to index??
Any help would be much appreciated... Thanks!
UPDATE: Full routes file:
ActionController::Routing::Routes.draw do |map|
map.login "login", :controller => "user_sessions", :action => "new"
map.logout "logout", :controller => "user_sessions", :action => "destroy"
map.resources :users
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
And my users_controller has all the usual new, create, show, edit, update methods...

I think you have one of two problems: either the output from rake routes has been mangled by your terminal screen, or your routes are being overridden by something else you installed, like a rails engine.
The first is easy to check for. it sounds like you have a basic user scaffold setup (and not much else) so fire up script/server, go to http://localhost:3000/users/new. If you see the new user page, you have a terminal display issue, but your routes are fine. If you see the users index page, however, proceed to the next step.
Double-check that the routes file you posted above is indeed the file for your app. This sounds ridiculous, but in some editors it's easy to open the wrong file. In TextMate for example, if you have some gems vendored and open the routes file via command-T, you can have multiple routes.rb files to choose from.
If you're sure you're viewing the correct routes file, the next step is to check your application for any other routes.rb files that may be overriding your main file. From terminal, you can run find ./ -name routes.rb and this will list any other routes files. This is especially likely if you have any rails engines installed.
Let me know how this goes - if you're still having problems, you can zip your application and e-mail it to me, and I'll take a look.

Related

Rails - From RESTFul resource to customized routes

This is a design problem that I am trying to figure out. I will explain what I have right now, and what I would like to have:
1. Actual design
I have a defined a resources :users and by doing so I have defined different actions such as new, create and update in the Users controller. This is working as expected by following urls like users/new , users/:id, etc...
Now I want to go one step forward, and I want to be able to do the following...
2. What am I looking for
I want to be able to have a route like this:
users/overview/profile - This should be equivalent to `users/:id` (show action)
users/overview/network - This should be equivalent to users/:id/network (list of networks for that user)
3. My idea
My first idea was to define something like this:
resource :users do
namespace :overview do
resource :networks
end
end
But this would work for urls like: users/:id/overview/networks and I don't want the user id to be shown in the URL. So my questions are:
1 - How can I deal with users/overview/networks instead of users/:id/overview/networks , assuming that I can get the user id from session.
2 - How can I be able to manage URLs like this: users/overview/profile where actually a profile is just the show method of users/:id Right now I have defined all the actions in the users controller and everything is working fine (new,delete,create,update...) I just don't know how to move into that "namespace" overview/profile
I have tried same thing you tried, and it is returning your desired results only, not sure what is your problem. Posting rake routes result here.
users_overview_networks POST /users/overview/networks(.:format) {:action=>"create", :controller=>"overview/networks"}
new_users_overview_networks GET /users/overview/networks/new(.:format) {:action=>"new", :controller=>"overview/networks"}
edit_users_overview_networks GET /users/overview/networks/edit(.:format) {:action=>"edit", :controller=>"overview/networks"}
GET /users/overview/networks(.:format) {:action=>"show", :controller=>"overview/networks"}
PUT /users/overview/networks(.:format) {:action=>"update", :controller=>"overview/networks"}
DELETE /users/overview/networks(.:format) {:action=>"destroy", :controller=>"overview/networks"}
users POST /users(.:format) {:action=>"create", :controller=>"users"}
new_users GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_users GET /users/edit(.:format) {:action=>"edit", :controller=>"users"}
GET /users(.:format) {:action=>"show", :controller=>"users"}
PUT /users(.:format) {:action=>"update", :controller=>"users"}
DELETE /users(.:format) {:action=>"destroy", :controller=>"users"}
scope :path => 'users/overview' do
match ':id/profile', :to => 'users#show'
match ':id/network', :to => 'users#network'
end

Are default routes broken with Rails 3 engines?

I have a Rails 3 engine gem that is for basic user authentication and authorization. Within that Gem the config/routes.rb defines the following
resources :users
match '/:controller(/:action(/:id))'
When I do a rake routes from the application that requires this gem I get the following routes
rake routes|grep users
users GET /users(.:format) {:controller=>"users", :action=>"index"}
users POST /users(.:format) {:controller=>"users", :action=>"create"}
new_user GET /users/new(.:format) {:controller=>"users", :action=>"new"}
edit_user GET /users/:id/edit(.:format) {:controller=>"users", :action=>"edit"}
user GET /users/:id(.:format) {:controller=>"users", :action=>"show"}
user PUT /users/:id(.:format) {:controller=>"users", :action=>"update"}
user DELETE /users/:id(.:format) {:controller=>"users", :action=>"destroy"}
This is what I expect.
However when I try to access the following routes via a browser
/users/137
/users/137/edit
I get the following error in the logs
AbstractController::ActionNotFound (The action '137' could not be found for UsersController):
actionpack (3.0.0) lib/abstract_controller/base.rb:114:in `process'
actionpack (3.0.0) lib/abstract_controller/rendering.rb:40:in `process'
...
What is interesting is that the following paths do work
/users/show/137
/users/edit/137
Also if I add the following to the routes.rb file in the application that is requiring the gem it all works as expected.
resources :users
Is there something I am missing or is this a bug?
Note that I am also doing the following when I start my application
on the command line when I start the rails I set the following env variable
RAILS_RELATIVE_URL_ROOT="/my_app"
and in config.ru
map '/my_app' do
run MSEL::Application
end
I experienced the same thing with a gem that I was creating. The engine routes are loaded after the application routes and I think this may be your problem. Take a look at rake routes without grepping for user. I suspect that you have a route in your application that takes precedence over the user routes. If you have match '/:controller(/:action(/:id))' in your application routes, then this will take precedence over the gem user route. Might explain why /users/show/137 works and not the RESTful routes. It may be possible to load your routes in the engine initializer to take precedence over the application routes. Post your full rake routes results and that may help us find a solution.
For me in Rails 3.1
root :to => 'ControllerName#Action'
Worked properly.

Rails 2 Namespace and Shallow Routes Issue

I've written the admin area of a particular rails app and now I'm ready to set it as own section within the website.
Therefore, it will be /admin
However, I didn't want to have it as /admin within the route itself I wanted to have something less common, so I added a couple of hyphens before and after it.
So the route is /-admin-/ and the namespace is Admin.
After setting this up using :path_prefix => "/-admin-", I have the following code block:
map.namespace "/-admin-/", :name_prefix => "", :path_prefix => "/-admin-" do |admin|
This works for all but shallow routes, instead, in the rake routes output the output is:
new_page GET /-admin-/areas/:area_id/pages/new(.:format) {:action=>"new", :controller=>"admin/pages"}
edit_admin_page GET /admin/pages/:id/edit(.:format) {:action=>"edit", :controller=>"admin/pages"}
admin_page GET /admin/pages/:id(.:format) {:action=>"show", :controller=>"admin/pages"}
PUT /admin/pages/:id(.:format) {:action=>"update", :controller=>"admin/pages"}
DELETE /admin/pages/:id(.:format) {:action=>"destroy", :controller=>"admin/pages"}
areas GET /-admin-/areas(.:format) {:action=>"index", :controller=>"admin/areas"}
POST /-admin-/areas(.:format) {:action=>"create", :controller=>"admin/areas"}
new_area GET /-admin-/areas/new(.:format) {:action=>"new", :controller=>"admin/areas"}
Notice how the shallow-routed routes are prefixed as /admin/ and not as /-admin-/ (as are their parent routes).
Any ideas on how to get around this? Is this a bug in rails or do I need to work around it? I tried adding the :path_prefix to each nested route but it doesn't do anything?
Any ideas?
I'm not sure about your rationale on not using /admin - security through obscurity isn't really security - you should be using something like authlogic to keep out unauthorised users.
Try the following to namespace your admin controllers:
map.namespace :admin, :path_prefix => "-admin-" do |admin|
admin.resources :users
admin.resources :pages
end
A sample generated route:
admin_users GET /-admin-/users(.:format) {:controller=>"admin/users", :action=>"index"}
There is no way to get around this. Turns out that all versions of Rails will break down the URL and its resource names to their lowest points when they're set to shallow. The only solution to this is to set all of your resource routes manually without using map.resources.

How to add :format options to a named route in Rails?

I've got a named route called profile and I would like to be able to access it as json. But when I look at my rake routes output I see that the (.:format) is missing. How do I add it to a named route?
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
profile /:username {:action=>"show", :controller=>"users"}
Thanks in advance!
Add .format in your path specification, like this:
map.profile '/:profile.:format', :controller => 'users', :action => 'show'
Then you'll end up with:
profile /:profile(.:format) {:action=>"show", :controller=>"users"}

in Ruby on Rails, does map.resources :stories immediately make Story RESTful?

I was reading Simply Rails by Patrick Lenz... maybe I missed something, it seems that whenever we put
map.resources :stories
in routes.rb
then immediately, the controller will have special convention and now Story is a RESTful resource? Maybe the author used the word resource but didn't mention that it is RESTful but they are the same thing?
Having that in routes means that you automatically get some standard routes that help you build a restful application. For example:
new_story GET /story/new(.:format) {:action=>"new", :controller=>"stories"}
edit_story GET /story/edit(.:format) {:action=>"edit", :controller=>"stories"}
story GET /story(.:format) {:action=>"show", :controller=>"stories"}
PUT /story(.:format) {:action=>"update", :controller=>"stories"}
DELETE /story(.:format) {:action=>"destroy", :controller=>"stories"}
POST /story(.:format) {:action=>"create", :controller=>"stories"}
Just having this one line in your routes file, gives you all these paths to use. You just have to make sure you provide the right functionality in new, edit, show, update, destroy and create actions of your stories controller and you will have a restful design.
In order to see what is available route-wise, you can go to your application folder and give the command:
rake routes
This is going to output all the paths available to you, based on what you have entered in your routes file.
BUT!!! If you have other actions in your controller they will NOT be found unless you introduce additional routes ABOVE that .resources line!
So if you have an action called turn_page in the stories controller you need to include a map.connect line before the map.resources line - as in this snippet:
map.connect 'stories/turn_page', :controller => 'stories', :action => 'turn_page'
map.resources :stories
Hope that helps someone! I got stuck for hours working on this one as all the examples are EITHER "regular" routes OR the REST set defined via the .resources statement!
Yes. Once you add that to your routes your Story controller will respond to the common REST verbs in the expected ways.

Resources