How do I fix this routing error in Ruby on Rails? - ruby-on-rails

I've put this line in my routes.db file:
map.mything '/mything', :controller => 'mything', :action => 'list'
But I get this error when I go to http://localhost:3000/mything, I get this error:
Unknown action
No action responded to index. Actions: list
Why is it trying to use index instead of list? I thought that by setting
:action => 'list'
it would use the list action? Thanks for reading.

You have to put named routes above the default routes.
I put named routes like these at the top of routes.rb so they always get evaluated first.
ActionController::Routing::Routes.draw do |map|
map.about 'about', :controller => 'home', :action => 'about'
map.contact 'contact', :controller => 'home', :action => 'contact'
# MORE CONFIG
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end

Agreeing with Jim Schubert, put the named routes above the default routes.
Another likely problem is that you have something like:
map.resources :mything
which is setting an index action on the controller as a result of you scaffolding a model

Sorry for asking a potentially obvious question, but have you tried restarting the app? Certain routes will not register until you restart the application (RESTful resources never need an application restart, but others often do).

Related

Rails route question

I have a login form (/user).
And methods:
-authenticate
-logout
And one view index.html.erb, it contains the login form, authenticate is work fine, but I think I have problems with routing.
Can you give me a sample route?
My router looks like:
map.logout 'logout', :controller => 'sessions', :action => 'destroy'
map.login 'login', :controller => 'sessions', :action => 'new'
In sessions control have destroy method, but when I type /logout it's say: Missing template session/destroy.erb in view path app/view
A sample route in Rails 3
match '/user(/index)' => 'users#index'
It would be helpful if you could clarify the issue you're having (and post relevant code).
All routing system is explain on guides :
http://guides.rubyonrails.org
This one in particular : http://guides.rubyonrails.org/routing.html

Is it possible to create a route like '~:id' in Rails 2.x?

I have been using the following route successfully in my Rails 2.x application:
map.user ':id', :controller => 'users', :action => 'show'
This, as my lowest route, properly catches things like /tsmango and renders Users#show.
I'm now trying to add a second, similar route like:
map.post '~:id', :controller => 'posts', :action => 'show'
Because neither my users or my posts are allowed to contain ~ and because this route will appear above my map.user route, I assumed this would properly catch any call starting with /~ and render my Posts#show action. Unfortunately, I'm having trouble getting this one to work.
What's interesting is that this similar route works perfectly:
map.post ':id~', :controller => 'posts', :action => 'show'
Although, I'm certainly willing to go with ':id~' since it has the same result, at this point I'm really just frustrated and curious as to how you would build a route that matches '~:id'.
It's worth mentioning that I do not want to modify my to_param method or my actual user and post slugs to include the prepended ~. I just want that in a route to indicate which action should handle it. Unless I'm mistaken, this rules out the use of something like:
:requirements => {:id => /\~[a-zA-Z0-9]/}
Thanks, in advance, for any help you can provide!
Update: I'm aware of route priority and stated above that I am placing the '~:id' route above the ':id' route. I receive the following error while trying to generate the url like post_path(#post):
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_sym
Routes are prioritized depending of the order in which they're declared.
When you define first the :id route, the second one is never executed.
In order for this to work, you just have to first define the ~:id route and then the :id one.
map.post '~:id', :controller => 'posts', :action => 'show'
map.post ':id', :controller => 'users', :action => 'show'

Can controller names in RESTful routes be optional?

With a standard map.resource routing mechanics and several nested resources the resultant routes are unnecessarily long. Consider the following route:
site.org/users/pavelshved/blogs/blogging-horror/posts/12345
It's easy to create in routes.rb, and I'm sure it follows some kind of beneficial routing logic. But it's way too long and also seems like it's not intended to be human-readable.
A nice improvement would be to drop controller names, so it looks like:
site.org/pavelshved/blogging-horror/12345
Clear, simple, short. It may become ambiguous, but in my case I'm not going to name any user "users", for instance.
I tried setting :as => '', but it yields routes like this: site.org//pavelshved//blogging-horror//12345 when generating them by standard helpers.
Is there a way to map resources in such a way, that controller names become optional?
You're looking for the :path_prefix option for resources.
map.resources :users do |user|
user.resources :blogs do |blog|
blog.resources :posts, :path_prefix => '/:user_login/:blog_title/:id'
end
end
Will produce restful routes for all blogs of this form: site.org/pavelshved/bogging-horror/posts/1234. You'll need to go to a little extra effort to use the url helpers but nothing a wrapper of your own couldn't quickly fix.
The only way to get rid of the posts part of the url is with named routes, but those require some duplication to make restful. And you'll run into the same problems when trying to use route helpers.
The simplest way to get what you want would be to create a route in addition to your RESTful routes that acts as a shorthand:
map.short_blog ':user_id/:blog_id/:id', :controller => 'posts', :action => 'show'
You'll have to change the URL bits to work with how you're filtering the name of the user and the name of their blog. But then when you want to use the shorter URL you can use all the short_blog_* magic.
Straight out of the default routes.rb:
map.connect 'products/:id', :controller => 'catalog', :action => 'view'
You could write:
map.connect ':user_id/:blog_id/:id', :controller => 'posts', :action => 'show'
But be sure to include that in the very end of the file, or it will try to match every three levels deep url to it.
Try this
map.pavelshved '/pavelshved/', :controller => :users, :action => view or
map.pavelshved '/:id', :controller => :users, :action => show do | blogs|
blogs.bloging '/:id', :controller => :blogs, :action => show do | post|
post.posting '/:id', :controller => :posts, :action => show
end
end
I hope it work :)
Google "rails shallow routes" for information about this.

RoR routing problem. Calling custom action, but getting redirected to show action

I am working on a project in ruby on rails and I am having a very difficult time with a basic problem. I am trying to call a custom action in one of my controllers, but the request is somehow getting redirected to the default 'show' action and I cannot figure out why.
link in edit.html.erb:
<%= link_to 'Mass Text Entry', :action=>"create_or_add_food_item_from_text" %>
Error from development.log:
ActiveRecord::RecordNotFound (Couldn't find Menu with ID=create_or_add_food_item_from_text): app/controllers/menus_controller.rb:20:in `show'
routes.rb file:
ActionController::Routing::Routes.draw do |map|
map.resources :nutrition_objects
map.resources :preference_objects
map.resources :institutions
map.resources :locations
map.resources :menus
map.resources :food_items
map.resources :napkins
map.resources :users
map.resource :session, :controller => 'session'
map.root :controller=>'pages', :action=>'index'
map.about '/about', :controller=>'pages', :action=>'about'
map.contact '/contact', :controller=>'pages', :action=>'contact'
map.home '/home', :controller=>'pages', :action=>'index'
map.user_home '/user/home', :controller=>'rater', :action=>'index'
map.user_napkins '/user/napkins', :controller=>'rater', :action=>'view_napkins'
map.user_preferences '/user/preferences',:controller=>'rater', :action=>'preferences'
map.blog '/blog', :controller=>'pages', :action=>'blog'
map.signup '/signup', :controller=>'users', :action=>'new'
map.login '/login', :controller=>'session', :action=>'new'
map.logout '/logout', :controller=>'session', :action=>'destroy'
# Install the default routes as the lowest priority.
map.connect ':controller/:action'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Menus_controller.rb:
class MenusController < ApplicationController
...
def create_or_add_food_item_from_text
end
...
end
create_or_add_food_item_from_text.html.erb simply has a div to show a form with a text box in it. I have the rest of my app working fine, but this is stumping me.
Any help is appreciated.
Try adding the route to your file explicitly, before the :menus resources:
map.connect "/menus/create_or_add_food_item_from_text",
:controller => "menus", :action => "create_or_add_food_item_from_text"
map.resources ...
Routes declared earlier have higher priority, and the problem here is that map.resources actually prevents certain paths from being routed.
Even regardless of this issue, it's good practice to map all paths explicitly, either through resources or named/unnamed routes, and ultimately eliminate the generic :controller/:action and :controller/:action/:id routes from your app.
link_to expects the path to your action as the second parameter - it looks like you are passing link_to the wrong path value. Check the development log to see what path rails thinks you are looking for.

How can i visit urls with .html suffix

My rails version is 2.3.5(2.3+)
How can I visit urls with .html suffix?
Just like localhost:3000/welcome.html (welcome is a controller).
I got routing errors when I visit urls above.But it works if the url with format param like this:
localhost:3000/welcome?format=html
In routes.rb:
ActionController::Routing::Routes.draw do |map|
map.root :controller => "welcome"
map.resources :users
map.resource :session
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
But but but I found localhost:3000/users.html works.
Use this route to connect to an controller:
map.connect "welcome.html", :controller => :welcome, :action => :index
Whether there is .html does not matter for routing purposes, it is just like any other path connecting to any other controller. So no need to modify your controller for this.
Using the format=html results in a parameter, so a controller can return the specific type of result, which is not what you want according to your question.
According to your information this (allowing .html in your paths) is automatically implemented when creating routes with the map.resources method. Since it is working for users in your example.
You could try this:
map.connect ':controller.:format', :action => :index

Resources