Resource routes exists but Rails throws a 404 - ruby-on-rails

This is NOT a duplicate of this question, since I'm not using custom routes for this resource, nor slugs. I'm using Rails 5.
This is my router
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :node_categories, only: [:create, :update, :destroy]
resources :edge_categories, only: [:create, :update, :destroy]
resources :nodes, only: [:index, :create, :destroy] do
collection do
match '/bulk' => 'nodes#bulk', via: :post
end
end
Everything seems fine. rake routes prints the routes OK
api_v1_node_categories POST /api/v1/node_categories(.:format) api/v1/node_categories#create {:format=>:json}
api_v1_node_category PATCH /api/v1/node_categories/:id(.:format) api/v1/node_categories#update {:format=>:json}
PUT /api/v1/node_categories/:id(.:format) api/v1/node_categories#update {:format=>:json}
DELETE /api/v1/node_categories/:id(.:format)
The controllers are well namespaced and the tests are passing (not doing route tests in this project though). All other routes seem to work fine. Only this resource is giving troubles. Any request to any action returns 404 but the log shows no such requests, no errors nor exceptions, not nothing.
All client application, Postman and even curl behave the same way, a phantom 404 is returned, along with an empty response, with no record of it in the logs.
Any ideas?

Test
scope '/api' do
scope '/v1' do
...
end
end
Instead of namespace, I use that in my APIs.

The error turned out to be related to Fabio's (my router) route permissions. The new routes needed to be allowed.
It had nothing to do with Rails.

Related

Ruby rails change browser url with resources

I have a nested resources:
resources :topic do
resource :fruits, only: [:edit, :update]
end
I want the browser url to be /topic/:topic_id/fruits(.:format) (without /edit) instead of /topic/:topic_id/fruits/edit(.:format)
In my action controller I see I have these routes
GET /topic/:topic_id/fruits/edit
fruits#edit
PATCH /topic/:topic_id/fruits/
fruits#update
PUT /topic/:topic_id/fruits/
fruits#update
what you are looking for is called a member route and it is well explained here
difference between collection route and member route in ruby on rails?

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.

How do I create a singular GET path for a resource including helpers?

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

Index route not being generates by resource command in routes.rb file

In a ruby on rails app, I have the following routes file:
Rails.application.routes.draw do
get 'pages/index'
get 'pages/about'
root to: 'pages#index'
resource :graphs, only: [:index, :create, :show, :destroy]
end
This generates the routes for graphs#create, graphs#show, graphs#destroy but not for graphs#index. I think the reason for this is that when I generated the controller I used rails g controller Graph, i.e. I used the singular version instead of the plural of Graphs. To fix this I changed the corresponding file and directory names i.e. controller/graphs_controller.rb and views/graphs, and I changed the constant in graphs_controller.rb to GraphsController. Everything seems to work except for the index route not being generated. I can fix it by changing the resource declaration to
resource :graphs, only: [:create, :show, :destroy] do
get :index
end
but this seems messy. It seems I need to change something else to make the transition from graph to graphs. How do I fix this? Note that I have restarted the server several times.
Use resources instead of resource:
Rails.application.routes.draw do
get 'pages/index'
get 'pages/about'
root to: 'pages#index'
resources :graphs, only: [:index, :create, :show, :destroy]
end
It should be resources instead of resource

Rails-Api (4): Namespaced routes, only: actions

I am using the Rails-Api (4) and I want only three routes for my namespaced routes file.
In my routes.rb file, I am trying to do this:
namespace :api do
namespace :v1 do
resources :documents, only: [:get, :create]
resource :system_status, only: [:get]
end
end
rake routes gets me only this:
Prefix Verb URI Pattern Controller#Action
api_v1_documents POST /api/v1/documents(.:format) api/v1/documents#create
If a take the the only: off, it works and gives me all the routes (which I don't want).
I also tried this:
namespace :api do
namespace :v1 do
post '/documents', to: 'documents#create'
get '/documents/:id', to: 'documents#show'
get '/system_status', to: 'system_status#show'
end
end
Gets me this odd output in rake routes:
Prefix Verb URI Pattern Controller#Action
api_v1_documents POST /api/v1/documents(.:format) api/v1/documents#create
api_v1 GET /api/v1/documents/:id(.:format) api/v1/documents#show
api_v1_system_status GET /api/v1/system_status(.:format) api/v1/system_status#show
Not sure what's up with documents#show getting me only api_v1 as it's prefix.
Looks like you're getting mixed up between HTTP verbs and their corresponding Rails actions. There is no resource route for :get, but there are two routes for a GET request, which are :index, and :show
Change your original resource-based routing to this instead:
namespace :api do
namespace :v1 do
resources :documents, only: [:show, :create]
resource :system_status, only: [:show]
end
end
And that should give you the proper routes, plus the correct URL helper prefixes.

Resources