Limit resource routes in rails - ruby-on-rails

I have below routes
resources :analytics do
collection do
get 'group_image'
get 'group_tag'
get 'group_location'
get 'group_time'
end
end
But it also creates default routes, which I don't need. How can I limit routes here?

You can do this:
resources :analytics, only: [] do
collection do
get 'group_image'
get 'group_tag'
get 'group_location'
get 'group_time'
end
end
It will creates your custom routes, but not the default one.

just use namespace instead of resources:
namespace :analytics do
get 'group_image'
get 'group_tag'
get 'group_location'
get 'group_time'
end

You can define like this also by excluding default actions.
resources :analytics, :except => [:new, :create, :destroy, :index] do
collection do
get 'group_image'
get 'group_tag'
get 'group_location'
get 'group_time'
end
end

Related

Overuse route customizations - customize_count (Rails 5)

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.

Getting partial routes

In my config/routes.rb, I have:
resources :landings do
collection do
get 'about'
end
end
Which give me the following routes:
about_landings GET /landings/about(.:format) landings#about
landings GET /landings(.:format) landings#index
POST /landings(.:format) landings#create
new_landing GET /landings/new(.:format) landings#new
edit_landing GET /landings/:id/edit(.:format) landings#edit
landing GET /landings/:id(.:format) landings#show
PATCH /landings/:id(.:format) landings#update
PUT /landings/:id(.:format) landings#update
DELETE /landings/:id(.:format) landings#destroy
I only need the about route, and possibly a couple of other static pages routes. What is the routes.rb syntax for that?
You can use except / only
resources :landings, except: [:show, :new, :edit] do
collection do
get 'about'
end
end
OR
resources :landings, only: [:index] do
collection do
get 'about'
end
end
NOTE: you can skip or allow only specific action.I just given example
You could do something like:
resources :landings, only: [] do
collection do
get 'about'
end
end
Which will give you:
about_landings GET /landings/about(.:format) landings#about
Personally, I don't like about_landings as a path name (aesthetically), so I think I would do:
scope module: :landings do
get 'about'
end
Which will give you:
about GET /about(.:format) landings#about
And then you can just use about_path which IMO is nicer (and, you type fewer characters while building routes.rb thereby adding fractional seconds to your overall lifespan). Also, you get a cleaner (again, IMO) url in the browser address bar.

Rails custom and default routes

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.

Is there a way to set the controller action for resources defined with only: or except:?

I have some nested nested resources:
resources :assessments do
member do
get 'result'
end
resources :respondents, only: [:new, :create] do
collection do
post "invite", to: :invite_all
get "invite", to: :new_invite
end
end
end
For the line resources :respondents, only: [:new, :create] is it possible to set the action for the new and crate actions? You can use to: to set the action for a single resource. I'd like to avoid writing match statements if I can and keep things resourceful.
What motivates me to ask this is I'd like to be able to specify the action for a nested resource rather than have it route to the child resource's action. For example:
If I define
resources :assessments do
resources :respondents
end
the path /assessments/:id/respondents/new will route to respondents#new. The problem with this it forces me to add logic to the new action to determine if the route contains the assessment id or not and then render the correct view. I'd like to be able to send the nested resource to a different action. Is there a "rails way" to do this?
Why not just not nest the resources like this:
resources :assessments do
member do
get 'result'
end
end
resources :respondents, only: [:new, :create] do
collection do
post "invite", to: :invite_all
get "invite", to: :new_invite
end
end
Or to keep nesting for other actions (e.g. index) just define the new and create actions separately.
resources :assessments do
member do
get 'result'
end
resources :respondents
end
resources :respondents, only: [:new], path_names: { new: 'make' } do
collection do
post :generate
post "invite", to: :invite_all
get "invite", to: :new_invite
end
end
This will create these routes:
result_assessment GET /assessments/:id/result(.:format) assessments#result
assessment_respondents GET /assessments/:assessment_id/respondents(.:format) respondents#index
POST /assessments/:assessment_id/respondents(.:format) respondents#create
new_assessment_respondent GET /assessments/:assessment_id/respondents/new(.:format) respondents#new
edit_assessment_respondent GET /assessments/:assessment_id/respondents/:id/edit(.:format) respondents#edit
assessment_respondent GET /assessments/:assessment_id/respondents/:id(.:format) respondents#show
PATCH /assessments/:assessment_id/respondents/:id(.:format) respondents#update
PUT /assessments/:assessment_id/respondents/:id(.:format) respondents#update
DELETE /assessments/:assessment_id/respondents/:id(.:format) respondents#destroy
assessments GET /assessments(.:format) assessments#index
POST /assessments(.:format) assessments#create
new_assessment GET /assessments/new(.:format) assessments#new
edit_assessment GET /assessments/:id/edit(.:format) assessments#edit
assessment GET /assessments/:id(.:format) assessments#show
PATCH /assessments/:id(.:format) assessments#update
PUT /assessments/:id(.:format) assessments#update
DELETE /assessments/:id(.:format) assessments#destroy
generate_respondents POST /respondents/generate(.:format) respondents#generate
invite_respondents POST /respondents/invite(.:format) respondents#invite_all
GET /respondents/invite(.:format) respondents#new_invite
new_respondent GET /respondents/make(.:format) respondents#new
This way you get new and create outside of of nested assessments.
I created these routes real quick locally and this is what was generated when running rake routes.

How can I specify two actions mapped to the DELETE verb in a rails resource?

I have an api tokens controller based on Matteo Melanis blog post. I'd like to add two custom actions register and unregister to the controller, and so the route that looked like this
namespace :api do
namespace :v1 do
resources :tokens,:only => [:create, :destroy]
end
end
has now become this
namespace :api do
namespace :v1 do
resources :tokens do
put 'register', on: :member, as: :register
delete 'unregister', on: :member, as: :unregister
end
end
end
This is the only way I've found that doesn't let unregister suppress the CRUD destroy action, associated with the DELETE verb. I tried to do
resources :tokens, :only => [:create, :destroy, :register, :unregister] do
in the above code, as well as defining resources :tokens,:only => [:create, :destroy] in parallel to the block. Yet, I either get the undesirable all CRUD + custom actions, or one of the custom actions overriding a CRUD action.
In short, I'd like to end up with
register_api_v1_token PUT /api/v1/tokens/:id/register(.:format) api/v1/tokens#register
unregister_api_v1_token DELETE /api/v1/tokens/:id/unregister(.:format) api/v1/tokens#unregister
api_v1_tokens GET /api/v1/tokens(.:format) api/v1/tokens#index
POST /api/v1/tokens(.:format) api/v1/tokens#create
DELETE /api/v1/tokens/:id(.:format) api/v1/tokens#destroy
Is this possible, and if yes: how can I make it so?
This should work:
resources :tokens, only: [:create, :destroy] do
member do
put 'register'
delete 'unregister'
end
end

Resources