How to add additional rest routes to a nested resource in rails - ruby-on-rails

I have a widget that has many links. In the routes file:
map.resources :widgets, :has_many => [:links]
I want to add a "sort" action to links. What do I need to add to the routes file, so I can write sort_widget_links_path(widget)

You can define it using a block:
map.resources :widgets do |widget|
widget.resources :links, :member => {:sort => :get}
end

Related

How can I alter url paths?

For example, because my controller is called listings, whenever I post a new listing it is for example domain.com/listings/listing-name however I would like it to be domain.com/businesses/listing-name instead.
How can I do this?
Current routes for this controller:
resources :listings do
member do
post :leadcreate
post :storycreate
end
end
Use path option
resources :listings, :path => "businesses" do
end
If you also want to rename the route helpers, then
resources :listings, :path => "businesses", :as => "businesses" do
end

scope accessible rails 3.1

I have this scope:
scope ":user_id", :as => "user" do
resources :boards, :controller => 'users/boards'
end
I get this route:
http://localhost/hyperrjas/boards/
I want a url without boards then on routes.rb I add:
scope ":user_id", :as => "user" do
resources :boards, :controller => 'users/boards', :path => '/'
end
That works great, but it is still accessible via "/boards" ... How do I prevent that? (I'm using Rails 3.1)
You shouldn't have to specify the controller names when using resources and in this caseI would use nested resources:
resource :user, only: :show do
resources :boards
end
This should give you the following:
/:user_id
/:user_id/boards
/:user_id/boards/new
/:user_id/boards/:id/
/:user_id/boards/:id/edit
and of course your restful routes!

Exposing a Specific Action of a Nested Route

Using this as an example contexted:
Post has_many comments
Comment belongs_to post
I have a route that looks like:
resources :posts do
resources :comments
end
How do i create a route that exposes comments#index?
An example use case would be... I want to list ALL comments in the system on a page. Essentially using the comments resource as if it's not nested when a user hits /comments
thank you!
Try this.
resources :posts do
resources :comments, :except => :index
end
match 'comments' => 'comments#index', :as => :comments
That said, I usually look to avoid routes like this because I like a tidy RESTful routes file, but sometimes it can't be helped.
Second option:
resources :posts do
resources :comments, :except => :index
get :comments, :on => :collection
end
In the second option, you'd want to remove the index action from the comments controller and create a comments action in your posts controller.

How do you add a custom route to a singleton resource?

map.resource :basket, :collection => { :checkout => :post }
The above does not work for a resource, as you would expect since basket is a resource (ie. singular) not resources, so there is no concept of a collection, everything should be scoped to the current_user. In this case User has_one Basket.
However I would like to specify a custom route without having to resort to adding another line in routes, eg:
map.checkout 'basket/checkout', :controller => 'baskets', :action => 'checkout'
Is this possible?
Of course my other option is to add a checkouts controller.
Just use :member option instead of :collection:
map.resource :basket, :member => {:checkout => :post}
If the basket is scoped to the user I'd make it a nested resource:
map.resources :users do |users|
users.resource :basket, :member => { :checkout => :post }
end
... or in Rails 3 ...
resources :users do
resource :basket do
post :checkout, :on => :member
end
end
This way you'll be able to scope the basket to the user who's checking out. The URL will end up looking like this:
/users/5/basket/checkout
You also get the nicely worded named route 'checkout_user_basket'.

Namespaced resources

This is an excerpt from my config/routes.rb file:
resources :accounts do |account|
account.resource :profile, :except => [:new, :create, :destroy]
account.resources :posts,
:collection => { :fragment => :get },
:has_many => [:comments, :likes]
# even more code
end
I would like that each nested resource to be loaded from from the account namespace such as Account::PostsController instead of PostsController.
Using resources :accounts, :namespace => 'account' tries to load AccountPostsController.
Trying to nest the structure doesn't really work all that well:
map.namespace :account do |account|
..
end
The previous code will load the files from the locations I want, however it does add the namespace to the url and the generated paths so I'll have methods such as account_account_posts_url and similar paths.
Another alternative is to use something like:
account.resource :profile, :controller => 'account/profile'
I really don't like this as it involves both code duplication and forces me to remove some of the rails magic helpers.
Any thoughts and suggestions?
Changing my routes.rb and running rake routes I came up with the following:
map.resources :accounts do |accounts|
accounts.namespace :account do |account|
account.resource :profile, :except => [:new, :create, :destroy]
end
end
This gets you what you want. The correct url and pointing to account/... controller.
See Rails Routing for more detailed info and options on what can be done with Rails Routes.
So what's specifically wrong with namespacing? I think this is what you're trying to do:
map.namespace :account do |account|
account.resource :profile
end
This will try to load the controller at app/controllers/account/profiles_controller.rb and will generate routes such as account_profile_path.
Updated based on comment:
map.resources :accounts do |account|
account.resource :profile
end
Will give you /accounts/22/profile.

Resources