Problem with route.rb file

I'm relative novice at RoR and I've just built my first application w/ o a tutorial that allows a user to login, buy products, and read/ create reviews about the product.

So the basic structure is like this......there is a layout page which basically uses <% yield %> to show the product listings and the review listings (listings/index and listings/review). This works fine.

The problem is making the login page(sessions/new) redirect tot he listings/index page. So when submit is clicked to submit username and password, a method called create is called and it can either redirect back to the login( in the case that the username/pw is invalid) or redirect to the "listings/index". In my config/routes.rb i've set the "map.resources :listings" and used redirect_to new_listings_path and redirect_to new_session_path+'?loginError=1' for the redirects. Both cases worked fine. However, now the review link on the index page which redirects to the review page no longer works

This is the error I am getting

Unknown action

No action responded to show

Now that I think about it don't see how the application was working at all since the lisitings wasn't defined in the resources to begin with. Anyone care to give insight or have any online references that better explain the routes.rb file? Any help is much appreciated.

Thanks

Jon

Hey Jon, The default route map.connect ':controller/:action/:id' was taking care of recognizing your route when you started off. It would recognize 'listings/review' to be for the controller 'listings' and the action 'review'.

The thing is that now you have declared the RESTful routes for the resources 'listings': map.resources :listings One of these routes is 'listings/:id' which will call the method 'show' for the listing 'id'. You can see all your declared routes using 'rake routes' in the command line.

Now if you need to add a method to the standard list of REST methods, like 'review', you do the following: map.resources :listings, :collection => { :review => :get } This supposes that your review action works on the collection of listings (not on a specific listing) and is being called with the method 'get'.

If you need a method to act on a specific 'listing', you need to pass the id of the listing in your call, so you declare the method this way: map.resources :listings, :member => { :review => :get }

Note that if your action makes a database change, you should use the methods PUT or POST instead.

Good luck.

Wow, I just added the change to my route file and it worked perfectly. Thanks!

I'm not familiar with the term RESTful route, by the way you describe it, it seems that it means the "default" route though.

So from your explanation, my question is this, since map.connect ':controller/:action/:id' is the equivalent of map.resources :listings , why is it that when I added the latter, my review page didn't work, but when I only had map.connect ':controller/:action/:id', it worked?

Also, i did "rake routes" before adding the collection route and without. When done with the collection route I saw all "listings"/* appear. W/o there was none. I guess this is the same question, but if controller/:action/:id covers that, wouldn't the listings be listed?

Actually...i guess what would be the most helpful is a clear cut definition of map.connect ':controller/:action/:id' . Example, if my controller is listings and i have an action "add_item", is listings/ add_item automatically added to the resources?

Thanks

Jon

Also...

I'm not sure if this is a related issue, but I just put in a 'login' link that simply redirects to another file.

<%= link_to "Login!", :action => :login_redirect %>. In my controller I have

  def login_redirect       redirect_to new_session_path   end

I know the link can be accomplished by <%= link_to "Login!", '../ session/new' %>, but I am curious as to why the controller method is not working. I tried creating a "login_redirect.html.erb"(it should never get called since we're using a redirect). My "new_session_path" is defined in the route.rb file properly ( map.resource :session , as there can only be one session at a time). I also thought about adding map.resources :listings, :collection => { :login_redirect=> :get }, but that would't make sense since "login_redirect" is not an object, and likewise there is no parameter being passed in that pathway.

Jon

Jon, map.resources :listings is not equivalent to ':controller/:action/:id'.

map.resources :listings will make 'Listing' a RESTful resource. This means it can be accessed as a resource with the most common CRUD (Create, Read, Update, Delete) operations. So map.resources :listings just creates the specific routes for accessing a controller 'listings' with default actions 'index', 'show', 'edit', 'update', 'new', 'create' and 'delete'. Only those methods are resolved. These are the standard methods you get when you make a scaffold.

If your controller doesn't have these actions, you're better off just defining map.connect ':controller/:action/:id'. This will resolve any URL of that form and try to find the corresponding controller and action.

So with that defined (and not map.resources :listings), any URL of the form 'listings/some_action' will resolve to your controller 'listings' and try to find an action 'some_action'.

Why do you define an action just to redirect? In your view, you can just call <%= link_to "Login!", :url => new_session_path %> which will directly get you to the action you want.

Ok, sorry, just noticed you already knew that :slight_smile:

The route map.listings :collection => { :login_redirect => :get } should work just fine, though you're right that semantically it's not right.

The point is when you define Listing to be a resource, you actually should only handle actions on that resource in your controller. An action like login_redirect is not an action on the resource 'listings' and has therefore nothing to do in you controller 'listings'. Put this kind of actions in another controller or, as mentioned before remove it entirely as it's useless.

As example of an action you would put in your controller 'listings': an action 'list_recent' that would find recent listings is typically one to put in the :collection option.

Thanks for the insight, haven’t tried it yet, but I’m sure it’ll be interesting.

Any suggestions in regards to good references to learn about resources in general?

Thanks

Jon

The book 'The Rails Way' by Obie Fernandez (Addison Wesley) has a couple of very comprehensive chapters about routing in Rails in general and a specific chapter about RESTful routing (chapters 3-5).

For a general intro in REST just look at the Wikipedia entry: