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.
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.
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?
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,
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.
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.
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: