I was viewing an episode in RailsCasts and was looking at the source code for episode 145.
This was his code for the routes.rb file
ActionController::Routing::Routes.draw do |map|
map.resources :orders
map.current_cart 'cart', :controller => 'carts', :action => 'show', :id => 'current'
map.resources :line_items
map.resources :carts
map.resources :products
map.resources :categories
map.root :products
end
I was immediately thrown off. That looked like an entirely different syntax. Then I realized that this source code was published in 2010. I'm wondering if it's now obsolete, because I copied and pasted that code into my Rails Application and it isn't working.
Usually, what I do is
resources 'orders'
root 'products'
I don't know how I would rewrite map.current_cart.
This is the error message I get
NameError at/orders/new
undefined local variable or method 'map' for #<ActionDispatch::Routing::Mapper::0x4d90868>
This line is highlighted
map.current_cart 'cart', :controller => 'carts', :action => 'show', :id => 'current'
Yes it is obsolete now.
Instead of map.resources just use resources.
So you should write
resources :orders
In Rails 4+ it would look something like this:
My::Application.routes.draw do
get '/cart', to: 'carts#show', defaults: { id: 'current' }
end
That may be post if that's how the route is exercised.
The map argument is now gone. My::Application depends on the name of the application in question.
As always, have the routing documentation handy when doing things like this.
If you're working on an older application you will have to follow the older conventions.
Related
Hi!
I have many links like <%= link_to 'Edit', edit_content_path(content) %> but since my Rails update and some other route changes the path is wrong.
It leads to domain/contents instead of the correct domain/subfolder/contents... what is wrong?
Thanks!
Have you nested any routes in your routes.rb file?
If you you will have to add the parent to the path.
edit_parent_content_path(#parent, #content_id)
Something like that. Running ->
$ rake routes
Will help you determine if it is a route problem. (Try to find your current path in the results.)
If you still have a problem, post your routes.rb file.
Here is my routes.rb:
ActionController::Routing::Routes.draw do |map|
map.root :controller => "store"
map.resources :users
map.resources :orders, :controller => 'order'
map.resources :contents
map.resources :products
map.resources :kundservice => "store/kundservice"
map.resources :foretaget => "store/foretaget"
# Install the default routes as the lowest priority.
map.connect 'subfolder/:controller/:action/:id'
map.connect 'subfolder/:controller/:action/:id.:format'
end
Because of the hostcompany where I have my site, I must have it in a subfolder under my domain, www.domain.com/subfolder/store.
Thanks!
In Rails 2.X we have:
map.resources :posts, :controller => 'posts', :as => 'articles'
This essentially creates an alias for our posts routes. For example, this sends "domain.com/articles/" to the posts controller index action.
In Rails3, however, the :as option behaves differently. For example:
resources :posts, :controller => 'posts', :as => 'articles'
sets a named route rather than an alias, and going to "domain.com/articles/" gives an error:
No route matches {:controller=>"posts"}
How do I get the old (Rails 2) :as behavior using the new (Rails 3) api?
PS: Please don't tell me to simply rename my controller. That's not an option for me.
From some cursory reading of the RoR guide on routing, I think you might need to try:
resources :articles, :controller => "posts"
(http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use)
You might also need to add :as => "articles", but that named helper might already be set up since you are adding :articles resources.
You can accomplish this same behavior using the path option:
resources :posts, :path => '/articles/'
Now for example /posts/new becomes /articles/new.
I'm getting the following error:
Unknown action
No action responded to show. Actions: activate, destroy, index, org_deals, search, and suspend
Controller:
class Admin::HomepagesController < Admin::ApplicationController
def org_deals
#organization = Organization.find(:all)
end
Routes:
map.root :controller => 'main'
map.admin '/admin', :controller => 'admin/main'
map.namespace :admin do |admin|
admin.resources :organizations, :collection => {:search => :get}, :member => {:suspend => :get, :activate => :get}
To note: This is a controller inside of a controller.
Any idea why this is defaulting to show?
Update:
I updated what the routes syntax is. Read that article, and tried quite a few variations but its still adamantly looking for a show.
Firstly, it looks like your routes file has the wrong syntax. If you are trying to establish routes for nested resources, you'd do it like so:
map.resources :admin
admin.resources :organizations
end
This would give you paths such as:
/admin/
/admin/1
/admin/1/organizations
/admin/1/organizations/1
The mapping from route to controller/action is done via a Rails convention, where HTTP verbs are assigned in ways that are useful for the typical CRUD operations. For example:
/admin/1/organizations/1
would map to several actions in the OrganizationsController, distinguished by the type of verb:
/admin/1/organizations/1 # GET -> :action => :show
/admin/1/organizations/1 # PUT -> :action => :update
/admin/1/organizations/1 # DELETE -> :action => :destroy
"Show" is one of the seven standard resourceful actions that Rails gives you by default. You can exclude "show" with the directive :except => :show, or specify only the resourceful actions you want with :only => :update, for example.
I recommend you look at Rails Routing from the Outside In, which is a great introduction to this topic.
EDIT
I see I ignored the namespacing in my answer, sorry. How about this:
map.namespace(:admin) do |admin|
admin.resources :homepages, :member => { :org_deals => :get }
end
This will generate your org_deals action as a GET with an id parameter (for the organization). You also get a show route, along with the six other resourceful routes. rake routes shows this:
org_deals_admin_homepage GET /admin/homepages/:id/org_deals(.:format) {:controller=>"admin/homepages", :action=>"org_deals"}
Of course your homepages_controller.rb has to live in app/controllers/admin/
EDIT redux
Actually, you want organizations in the path, I'll bet, in which case:
map.namespace(:admin) do |admin|
admin.resources :organizations, :controller => :homepages, :member => { :org_deals => :get }
end
which gives you:
org_deals_admin_organization GET /admin/organizations/:id/org_deals(.:format) {:controller=>"admin/homepages", :action=>"org_deals"}
By specifying admin.resources ... you are telling Rails you want the seven default different routes in your application. If you do not want them, and only want the ones you specify, do not use .resources. Show is called because that's the default route called for a GET request with a path such as /admin/id when you have the default resources.
Given a simple namespaced route
map.namespace :api do |api|
api.resources :genres
end
how can I reuse this block but with another namespace?
Currently I'm achieving that by writing another routes hacked on the fly
map.with_options :name_prefix => 'mobile_', :path_prefix => 'mobile' do |mobile|
mobile.resources :genres, :controller => 'api/genres'
end
But it seems less than ideal.
I believe the , :controller => 'api/genres' option is your only approach. Only cleanup I can see is: map.namespace :mobile.
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.