rails routing problem - ruby-on-rails

I have some RESTful controllers and have added a custom method to application_controller.
I have not changed anything in the routes to indicate this new method. The method is poll_memos. I have entered the following URL:
/groups/1234/poll_memos
I get the following error:
Unknown action
No action responded to 1234. Actions: create, destroy, edit, index, new, poll_memos, show, and update
Two questions: Since I didn't modify routes how does rails know about poll_memos? Second, since it seems to know about it, why is it not working?

I don't think thats a restful route that rails automatically generates. This means you'll need to add it yourself.
Look at this question and this one.
And its in the actions because its in the controller, the error message is just printing all actions.

The correct url is /groups/poll_memos/1234. In your example rails thinks that you're trying to call controller method named "1234", which is absent, of course.
Rails knows about poll_memos because the code that prints the error message looks at controller code, not to the routing. You may set routes up in such a way that it will say that there is poll_memos method, but you're unable to access it via URL.

This is because you are most likely triggering the default route:
map.connect ':controller/:action/:id'
Your URL
/groups/1234/poll_memos
would map as follows:
{:controller => "groups", :action => "1234", :id => "poll_memos"}
Also, as you are using a restful style you need to configure the route. To get the poll memos working on the items in the collection you'll need to modify your routes to map as follows:
map.resources :groups, :member => {:poll_memos => :get}

Related

Understanding what's going on with : and # in ruby, rails routes

In the answer to this question about routes in Devise: Devise & Custom Rails User URLs
There is a line of code:
match '/:user' => "users#show", :as => :user_profile
That apparently works for the question asker, but not for me. I end up with
NoMethodError in UsersController#show
undefined method `books' for nil:NilClass
when I go to localhost:3000/username instead of localhost:3000/user/username. I assume because the match line above isn't working correctly and that url does not refer to any user, according to my routes file.
The second url routes me to the user's show page, but I don't want the extra /user in the url.
So I'm trying to figure out exactly what '/:user', :as, and :user_profile mean because I think I'm supposed to substitute a few things here specific to my app. I think :as is some kind of aliased method. I can't find anything in the Devise documentation about a route called user_profile. And I don't know what '/:user' is referring to. An instance of the User object? A user attribute/unique column in my database that I use to refer to specific users? (I use permalink for my user-defined urls).
The route is working for you. Thats why ur getting error from users_controller#show.
In your show action you must be doing something like User.where(:id => params[:id]). But in this case, the attribute in your params is called :user . So to make make both routes work, without any change in the show action, change the route to
match '/:id' => "users#show", :as => :user_profile
Devise documentation won't refer to a 'user_profile' because it is a custom route being used to help address the issue that the questioner (in the linked question) was asking.
match '/:user' => "users#show" means "match any route with a single parameter after / that doesn't match a previously defined route, pair this route to the UsersController 'show' action (passing along the singe parameter as 'user')"
Modifying a route using :as => :anything will provide several helper methods to refer to this route that may be used in controllers, views, and mailers (in this case anything_path and anything_url).
As far as why this won't work for you, this is likely do to a problem with this entry in regard to the rest of your routes or because of your controller action itself. Posting these can help someone track down the exact reason...

Rails always routes an action to show action, and the action it self becomes the id

There's a strange behavior in rails I found recently related to routes and actions, specifically, it's on rails 2.3.5. I have a controller, let's call it Users. In the routes, I declare Users as a resources.
map.resources :users
And within the controller, I have the standard action: index, show, edit, update & destroy. Also, I added other action to fullfil certain requirements.
def generated_pdf_report
# do something
end
The problem is, when I go to page /users/generated_pdf_report, I get this on the console:
Processing UsersController#show (some timestamps) [GET]
Parameters: {"action"=>"show", "id"=>"generated_pdf_report", "controller"=>"users"}
As you can see, the server route the request to method show rather than to method generated_pdf_report. What's interesting, is that I have other controllers having similar action and is working fine.
The solution to the above problem is easy enough, make sure the added feed is above the resources:
map.feed 'users/generated_pdf_report', :controller => 'users', :action => 'generated_pdf_report'
map.resources :users
My question is: Anyone knows why rails behaves like that? The above solution is kind of sloppy, what do you think the best practices for such problem like one mentioned above.
As outlined in the Rails 2 routing guide, you can add collection routes like so:
map.resources :users, :collection => { :generated_pdf_report => :get }
When rails looks at
/users/generate_report
That is exactly the path it would use to show a user whose id was generate_report, so that is what it does, assuming you haven't told it otherwise.
A shorter alternative to what you wrote is
resources :users, :collection => {:generate_report => :get}
Which tells rails to map a GET to /users/generate_report to your generate_report action

Rails routing of a controller's functions query

So I've got a Users controller, and it has (amongst others) a function called details.
The idea is that a user can go to
localhost:3000/user/:user_id/details
and be able to view the details of :user_id.
For example, I have a user called "tester".
When I go to the uri: http://localhost:3000/users/tester/details
I'd want the details function to be called up, to render the details view, and to display the information for the user tester.
But instead I get an error saying that
No action responded to tester. Actions: change_password, create, current_user, details, forgot_password, index, login_required, new, redirect_to_stored, show, and update_attributes
And I understand that to basically mean that if I wanted to access details, I should really be using
http://localhost:3000/users/details
Except that that isn't really working either... >.<
That is instead bringing me to http://localhost:3000/users/details/registries
(which is the default path that I'd stipulated for anybody trying to view users/:user_id, so again, that's working the way I wanted it to)
Point is: Can anybody help and tell me how I can go about getting
users/:user_id/details to work the way I want it to and display the details of :user_id?
Thanks!
Are you using resources? If your routes look like:
map.resources :users
You could make it:
map.resources :users, :member => { :details => :get }
That would allow GET requests for the URL /users/:id/details
More info here: http://guides.rubyonrails.com/routing.html#customizing-resources
I think that your problem is with setting routes in such way, that instead of :user_id you have :login (or whatever) in url /users/tester instead of /users/34. Probably you should take a look at to_param (1st example, 2nd example, 3rd example).
If you want to have another option in routes (besides default REST routes), you can add :member => {:details => :get} if you are using map.resources (#dylanfm answer) or just map it like in #Salil answer.
In order to get routes like "users/:user_id/details" change following in routes.rb
map.users 'users/:user_id/details', :controller => 'users', :action=>'details'

Ruby on rails paths and routes

I'm trying to get the hang of basic Rails routing.
I have a model called page which I generated with a scaffold.
I have added a method called addchild which I would like to access through
'pages/addchild/:id'
So far so good. However, I want to set up a link to this method like so:
<%= link_to 'Add child page', addchild_page_path(page) %>
Passing the ID of the current page as a parameter.
When I load my index view (where the link is), I get the following message:
undefined local variable or method `addchild_page_path' for #<ActionView::Base:0xb67797d0>
Have I misunderstood how the path/link_to method works?
My routes file looks like this:
map.resources :pages
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
Any advice would be greatly appreciated.
Thanks.
You need to add a route to it to be able to use the named path methods.
Since you mentioned you used scaffolding, you probably have the route setup as a resource, so all that you need to do is add the method:
map.resources :pages, :member => {:addchild => :get}
Would give you an addchild_pages_path (and the actual created path would look like /pages/:id/addchild
You then use it like this: addchild_pages_path page, don't call the id method directly since it is not resourceful (you won't use the to_param in the page class, which you might want to do later).
If you really want the url to show up as /pages/addchild/:id (which I don't recommend) you can add
map.addchild_page "/pages/addchild/:id", :controller => :pages, :method => :addchild
before the map.resources :pages row in your routes.rb, and then use the path method as above.

New Action Not Working

I have a standard User controller with the normal set of actions (index, show, new, edit, etc) and I'm trying to add a new action named 'profile'. I added the following code:
def profile
#user = User.find(session[:user_id])
end
I also created a new view for the action (app/views/users/profile.html.erb), but whenever I try to view that page I get an error:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with ID=profile
...
Apparently it's hitting the show action. I'm guessing that means I need to add something to my routes to make this work, but I don't know what. So far I just have the two default routes and the map.root line which I uncommented:
map.root :controller => "home"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
So really I have two questions:
What do I have to do in order to enable my new action?
Why don't the existing routes cover this situation? Other urls consisting of just the controller and action work just fine (e.g. http://localhost:3000/users/new). Why not this one? Shouldn't it just evaluate to :controller = users, :action = profile, :id = nil?
Try putting something like this in your routes.rb file:
map.user_profile '/users/:id/profile', :controller => "users", :action => 'profile', :conditions => {:method => :get}
I think possibly the reason it's doing this is because you are not matching either of the defaults, because you are not setting :id (even though it is detecting your action as the id). I don't know what your URL looks like, but I have a feeling that if you tried http://localhost:3000/users/123124124/profile, it MIGHT work, even without the new line in routes.
Are you intentionally trying to get the id from session[:user_id] instead of params[:id]? Is this supposed to be displaying a public profile?
Are you sure, that the session contains the user_id the first time you load the page?
Hard to say without seeing all the code, but my guess is there may be some strangeness because your model and controller have the same name. I'd try renaming the controller before changing anything else (remember to change the name of the views/users directory too).
See also this other stack overflow post: Rails cannot find model with same name as Ruby class
Long shot maybe.
Solution for your problem configure your routes.rb in such a way that id should be passed as the parameter .
configure in routes.rb as below
map.profile '/profile/:id',:controller=>'users',:action=>'profile'
when you want to access your profile page use it with the following URL
http://localhost:3000/profile
Make sure once you login , u handle the session and store the userid in the session variable .
Good luck !

Resources