I have this route in my routes.rb
resource: session
It generates the following routes
session_path POST /session(.:format) sessions#create
new_session_path GET /session/new(.:format) sessions#new
edit_session_path GET /session/edit(.:format) sessions#edit
I do not require edit_session_path (at least I don't know yet whether I require it or not) and I have a custom route for signin, so I don't want new_session_path.
Is there a way to tell Rails to not generate these two paths?
resources :sessions, :except => [:new, :edit]
Alternatively, if you know which actions you want you can provide it directly via only, instead of excepting them:
resources :sessions, only: [:create]
If you need more than 1 resource to configure
with_options(except: [:new, :edit]) do |opt|
opt.resource :session
opt.resource :another_resource
opt.resources :people
end
like in this post
or like this - similar to the upper answer.
Related
I am using the rails_best_practices gem which tells me i have an error:
overuse route customizations (customize_count > 8)
resources :stores do
collection do
get :api
end
member do
get :printer
get :delete
get :inventory
delete :inventory
get :daysheet
get :detailed_daysheet
get :labels
patch :restore
patch :print_labels
post :daysheet
end
end
Resulting in these paths:
api_stores_path GET /stores/api(.:format) stores#api
printer_store_path GET /stores/:id/printer(.:format) stores#printer
delete_store_path GET /stores/:id/delete(.:format) stores#delete
inventory_store_path GET /stores/:id/inventory(.:format) stores#inventory
daysheet_store_path GET /stores/:id/daysheet(.:format) stores#daysheet
detailed_daysheet_store_path GET /stores/:id/detailed_daysheet(.:format) stores#detailed_daysheet
labels_store_path GET /stores/:id/labels(.:format) stores#labels
DELETE /stores/:id/inventory(.:format) stores#inventory
restore_store_path PATCH /stores/:id/restore(.:format) stores#restore
print_labels_store_path PATCH /stores/:id/print_labels(.:format) stores#print_labels
POST /stores/:id/daysheet(.:format) stores#daysheet
After refactoring, I need it to still function as it does now with get routes such as /stores/7/inventory and /stores/18/printer
How can i compress these get routes to accomplish the same routing goals?
One approach would be to do:
resources :stores do
scope module: :stores do
resource :printer, only: [:show]
resource :daysheet, only: [:show, :create]
resource :detailed_daysheet, only: [:show]
resource :inventory, only: [:show, :destroy]
resources :labels, only: [:index]
resources :print_labels, only: [:update]
resource :restore, only: [:update]
end
collection do
get :api
end
member do
get :delete
end
end
Which gives you:
store_printer GET /stores/:store_id/printer(.:format) stores/printers#show
store_daysheet GET /stores/:store_id/daysheet(.:format) stores/daysheets#show
POST /stores/:store_id/daysheet(.:format) stores/daysheets#create
store_detailed_daysheet GET /stores/:store_id/detailed_daysheet(.:format) stores/detailed_daysheets#show
store_inventory GET /stores/:store_id/inventory(.:format) stores/inventories#show
DELETE /stores/:store_id/inventory(.:format) stores/inventories#destroy
store_labels GET /stores/:store_id/labels(.:format) stores/labels#index
store_print_label PATCH /stores/:store_id/print_labels/:id(.:format) stores/print_labels#update
PUT /stores/:store_id/print_labels/:id(.:format) stores/print_labels#update
store_restore PATCH /stores/:store_id/restore(.:format) stores/restores#update
PUT /stores/:store_id/restore(.:format) stores/restores#update
api_stores GET /stores/api(.:format) stores#api
delete_store GET /stores/:id/delete(.:format) stores#delete
stores GET /stores(.:format) stores#index
POST /stores(.:format) stores#create
new_store GET /stores/new(.:format) stores#new
edit_store GET /stores/:id/edit(.:format) stores#edit
store GET /stores/:id(.:format) stores#show
PATCH /stores/:id(.:format) stores#update
PUT /stores/:id(.:format) stores#update
DELETE /stores/:id(.:format) stores#destroy
Naturally, this requires that you create a number of new, nested controllers, such as Stores::Printers which will reside in app/controllers/stores/printers_controller.rb. But, you're now using standard RESTful routes, which I guess some people thing is a good thing.
Also, for your nested routes, you'll have :store_id in the params instead of id.
That collection api and member delete still seem odd, but I'm not sure what the intention is there.
I have the following:
routes.rb
resources :splashes, only: [:index, :create, :destroy]
get '/splash', to: 'splashes#index'
>rake routes | grep splash
splashes GET /splashes(.:format) splashes#index
POST /splashes(.:format) splashes#create
splash DELETE /splashes/:id(.:format) splashes#destroy
GET /splash(.:format) splashes#index
However, when I try to use splash_url, it generates http://localhost:3000/splashes/1.
I tried
get '/splash', to: 'splashes#index', as: 'splash'
But it gave
rake routes | grep splash
rake aborted!
ArgumentError: Invalid route name, already in use: 'splash'
You may have defined two routes with the same name using the :as option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with resources as explained here:
http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
I tried to use the singular resource, but it doesn't generate an #index action, and you can't DELETE a specific splash row.
Just place your singular routes get statement before the resources statement,
get '/splash', to: 'splashes#index'
resources :splashes, only: [:index, :create, :destroy]
Now, the rake routs will give your the below result,
splash GET /splash(.:format) splashes#index
splashes GET /splashes(.:format) splashes#index
POST /splashes(.:format) splashes#create
DELETE /splashes/:id(.:format) splashes#destroy
By that above approach the delete and get routes get overrided based on the defintion sequence, because they both has the same named helpers spash_path. So, I suggest you to add named helper to custom get /spash routes like below,
resources :splashes, only: [:index, :create, :destroy]
get '/splash', to: 'splashes#index', as: 'splash_index'
So, now you will get a separate named routes splash_index for your custom get route. There's a another solution also,
resources :splashes, only: [:index, :create, :destroy]
resources :splash, only: [:index], controller: :splashes
So, that you will get a different named helper for your /spash routes,
splashes GET /splashes(.:format) splashes#index
POST /splashes(.:format) splashes#create
splash DELETE /splashes/:id(.:format) splashes#destroy
splash_index GET /splash(.:format) splashes#index
My routes.rb file looks like:
resources :contents, only: [:show]
get 'contents/by_hardware', to: 'contents#show_by_hardware'
With this setup I am not able to access the contents/by_hardware route.
But if I setup my routes.rb file in a different order, everthing works.
get 'contents/by_hardware', to: 'contents#show_by_hardware'
resources :contents, only: [:show]
Is the order in the routes.rb file important?
Yes, order matters very much.
It works like this: resources :contents, only: [:show] creates this route
content GET /contents/:id(.:format) contents#show
So when you request, for example, http://localhost:3000/contents/by_hardware, it is this route that matches this url. It invokes ContentsController#show action with params {'id' => "by_hardware"}. Your custom action is not considered, because matching route is already found.
Yes, order does matter. Instead of defining routes for the same controller at two different places, I would recommend you to define routes for the above scenario this way
resources :contents, only: [:show] do
get :show_by_hardware, on: :collection, path: :by_hardware
end
Hope that helps!
Yes it is important, the routes will be matched from top to bottom so you can move your route get 'contents/by_hardware', to: 'contents#show_by_hardware' above resource to fix your problem
yes. router will match first route from the top
Here is code from my routes.rb
Rails.application.routes.draw do
resources :session, only: [:create, :destroy, :new]
end
and the relevant output of rake routes is
session_index POST /session(.:format) session#create
new_session GET /session/new(.:format) session#new
session DELETE /session/:id(.:format) session#destroy
My question is, why does session#create route to session_index, and not simply session?
It should be:
resources :sessions, only: [:create, :destroy, :new]
As per Rails convention, if you use singular resource, then simply use resourceand for plural resource, you should use resources.
Resource Routing
I'm trying to define custom routes to my controller and I need to use some of the default routes too. Is there any simple solution?
So far I've something like this
resources :users do
member do
get 'users/:id', to: 'users#show'
delete 'users/:id', to: 'users#destroy'
end
collection do
post 'users', to: 'users#create'
post 'users/login', to: 'users#login'
end
end
resources :users, :only => [:show, :destroy, :create, :login]
I don't need nor want the index route but with this settings it's still trying to route GET users/ to user_controller index method.
I know that there is probably some simple and obvious answer but I'm not able to find it.
Thank's in advance.
You got your routes wrong. The resources :users generates seven default routes which include the index route as well. You need to tweak the code to below
resources :users, :only => [:show, :destroy, :create] do
collection do
post 'login', to: 'users#login'
end
end
Note:
If you noticed, I've removed the custom routes for show,create and delete as they are generated by default.
Your first line defines the route to the index action. Define a resource once only. Read the routing guide.
resources :users, :except => [:index] do
collection do
post 'users/login', to: 'users#login'
end
end
Run rake routes from the command line in your project root folder to see all your route definitions.