routing is too verbose - rails - ruby-on-rails

Suppose I have a model User and I want to add some dashboard namespace. So I create dashbord directory and put inside private_users_controller.rb. Now for routing I put
namespace "dashboard" do
resources :users do
member do
get "show" => "private_users#show"
end
end
end
the problem is that I only want to route the get request having this route /dashboard/users/:id/show. But rake routes shows a bunch of post, delete... routes.
How can I cut those ?

seems like you don't need any of the method from resources definition, so just add a match will be ok.
namespace "dashboard" do
match 'users/:id/show', :to => 'private_users#show'
end
if you insist using resource, then the following will work
scope '/dashboard' do
resources :users, :only => :show, :module => 'private'
end
the 'rake routes' output is like this
GET /dashboard/users/:id(.:format) private/users#show
the trailing 'show' inside the url is not needed.

namespace "dashboard" do
get "users/:id/show" => "private_users#show"
end

Related

need help on rails nesting routes

I want to get a route like
GET /example/notifications/status, to: example/notification#status
POST /example/notifications/disable to: example/notification#disable
Here is what I did
resources :example, only => %i[index] do
collection do
resources :notifications, :only => [] do
collection do
get :status
post :disable
end
end
end
end
it get the right path but it point to notification#status not example/notification#status
is there any way I can get both right path and controller expect code like
get "notifications/status", :to => "example/notifications#status"
You can use namespace for this purpose like below,
in you config/routes.rb file
namespace :example do
collection do
get :status
post :disable
end
end
It will hit the example/notification#status action.
for more information see here
Don't use resources since you don't want (aparently) any param on your routes. Go for namespace instead:
namespace :example do
namespace :notifications do
get 'status'
post 'disable'
end
end
Gives you:
$ rails routes -g example
Prefix Verb URI Pattern Controller#Action
example_notifications_status GET /example/notifications/status(.:format) example/notifications#status
example_notifications_disable POST /example/notifications/disable(.:format) example/notifications#disable

Abstracting rails route

I want to replace the normal /users/:id route that is created by the resources command, with a more abstract /profile route. It won't be possible to view other users profiles in my app, and therefor the current route is unnecessary specific.
I have tried to overwrite the route created by 'resources :users' with:
get '/profile', to: 'users#show'
and other variances and combinations, but can't seem to get it right. Either the controller can't find the user because of a missing id or it simply can't find the route.
Thanks for the help!
You can use this code in routes.rb file:
resources :users, :except => :show
collection do
get 'profile', :action => 'show'
end
end
It will generate url "/users/profile".
But, if u want to use only '/profile', then don't create route as collection inside users resources block.
resources :users, :except => :show
get 'profile' => "users#show", :as => :user_profile
It will redirect '/profile' to show action in users controller.
I suggest simply adding a users/me route pointing to the show action of your UsersController like so:
resources :users, only: [] do
collection do
get 'me', action: :show
end
end
You can also use the match keyword in routes.rb file.
match 'users/:id' => 'users#show', as: :user_profile, via: :get

Upgrading routes in Rails 3

Currently I have something like this:
resources :books do
collection do
get 'search'
end
end
and my controller name is also "books" and I have a action method called "search" inside it
I would like that "get search" part to also be a resource, kind of like nested resources... but I don't want to break other peoples codes that are using the current route that this generate, so need to update it in a passive way!
resources :books do
collection do
get 'search'
end
resources :searches
end
...if I'm understanding you correctly, that should be what you want. It won't break other routes, just add new ones.
Run rake routes to make sure you have all the routes you want/need.
Use shallow routes nesting like:
resources :books , :shallow => true do
resources :searches
end
Now you will get the following routes:
/books/1 => books_path(1)
/books/1/searches => books_searches_index_path(1)
/searches/2 => searches_path(2)
Similarly you can get separate routing for defined routes like:
get '(:books)/searches', :to => 'books#index'

No route matches error. Whats wrong with this code?

I'm newbie on rails and getting an error while try to add new method on my controller :(
I have a controller under admin path;
Admin::MyUsersController < ApplicationController
before_filter :......
def index
redirect_to :action => :show_my_action
end
def show_my_action
...
...
end
My controller like this but not this exactly.
In my routes.rb
namespace "admin" do
resources :my_users do
get "show_my_action"
end
end
When my routes.rb is like this, im getting error => No route matches {:action=>"show_my_action", :controller=>"admin/my_users"}
namespace "admin" do
resources :my_users do
get "show_my_action", :on => :collection
end
end
when my routes.rb like this then no error :S
Why im getting this error. I can use first declaration for other controllers which is on root path.
You are adding actions to RESTful actions, if you don't specify a collection, or a member, the route can't know what you want. If you define like this:
namespace "admin" do
resources :my_users do
get "show_my_action"
end
end
How can routes know which route you want:
my_users/show_my_action, or my_users/:id/show_my_action
So, you need to specify it's member or collection:
namespace "admin" do
resources :my_users do
get "show_my_action", :on => :collection
end
end
will have route: my_users/show_my_action, and:
namespace "admin" do
resources :my_users do
get "show_my_action", :on => :member
end
en
will have route: my_users/:id/show_my_action
You can check at Adding More RESTful Actions.
You need to specify whether the action is on a member or a collection. If it's on a member then your URL is admin/my_users/:id/show_my_action. If it's on a collection then it's admin/my_users/show_my_action. Read up on it here: http://edgeguides.rubyonrails.org/routing.html

How to declare a rails resource with a parameter for new action?

I have a model named Entree for which the new action needs a parameter, the id of another model named Cave. I don't want to nest Entree in Cave since Cave is already nested.
What I did was declaring the resource Entree as follow in routes.rb:
resources :entrees, :except => [:new]
match "/entrees/new/:id", :to => "Entrees#new", :as => 'new_entree'
That works, but the problem is when there's an error in the create action, I want to display the page again with the invalid input. But since there's no new action, I must do a redirect_to new_entree_path, which does not keep the user input.
I have tried the following (simplest) route:
resources :entrees
But then the path http://localhost:3000/entrees/new/32 returns an error:
No route matches [GET] "/entrees/new/32"
The question is, how can I declare the Entree resource in the routes file with a parameter for the new action ?
I'm not sure if that's a hack or not, but the following works and seems cleaner than 2-levels nesting.
resources :entrees, :except => [:new] do
collection do
get 'new/:id', :to => "entrees#new", :as => 'new'
end
end
Now I can do a render "new" instead of a redirect_to.
I must say that I must have asked my question wrongly, my bad.
Rails has a route helper called path_names that does this:
resources :entrees, path_names: { new: 'new/:id' }
To improve gwik 's solution (which in fact didn't work for me):
resources :things, except: [:new] do
new do
get ':param', to: 'things#new', as: ''
end
end
It gets you new_thing_* helpers (instead of new_things_*) for free.
If you want to use Rails resource routes, you will have to nested them according to how they work
resources :caves do
resources :entrees
end
to get the route /caves/70/entrees/new
Otherwise, you are in a world of creating manual match routes.
match "/entrees/new/:id", :to => "entrees#new", :as => 'new_entrees'
I do not understand why you are forced to use a redirect? The new_entrees route is valid. You will not be able to use the form_for helper, since it is not a resource, but the form_tag helper will work.
UPDATE: Render and Route
The Route does not directly change what view is rendered in the Controller. That is determined by the controller itself. Render examples:
render :new will render the new action's view
render 'entrees/new' will render the entrees/new template
I found this generates the correct new_thing_path method not new_things_path as Antoine's solution.
resources :things, :except => [:new] do
with_scope_level(:new) do
get 'new/:param', :to => "things#new", :as => ''
end
end

Resources