I use rails 5 and setting route, type rake routes in console and result is:
Prefix Verb URI Pattern Controller#Action
new_report_templates GET /report_templates/new(.:format) report_templates#new
edit_report_templates GET /report_templates/edit(.:format) report_templates#edit
report_templates GET /report_templates(.:format) report_templates#show
PATCH /report_templates(.:format) report_templates#update
PUT /report_templates(.:format) report_templates#update
DELETE /report_templates(.:format) report_templates#destroy
POST /report_templates(.:format) report_templates#create
It's so weird to see that result routes do not have id in url template. My route:
Rails.application.routes.draw do
resource :report_templates
end
I use gem 'rails', '~> 5.1.6'. So my question is: why my result routes do not contain id in that ?
It's because your are using singular resources:
Sometimes, you have a resource that clients always look up without referencing an ID.
Change your routes to use resources for certain routes to contain the id:
Rails.application.routes.draw do
resources :report_templates
end
Related
I created a new controller and actions for a new model. I have setup the rails routes like below:
namespace :api do
namespace :v1 do
resources :universes
end
end
I am trying to write up some RSpec tests using the path helpers (ex. get(api_v1_universe_path(universe.id))). When I go to look at the post route for invites the route is missing the prefix as shown here:
POST /api/v1/universes(.:format) api/v1/universes#create
new_api_v1_universe GET /api/v1/universes/new(.:format) api/v1/universes#new
edit_api_v1_universe GET /api/v1/universes/:id/edit(.:format) api/v1/universes#edit
api_v1_universe GET /api/v1/universes/:id(.:format) api/v1/universes#show
I know I can manually add a line like post "/", to: "universe#create", as: "create" to get a route with a prefix. However, I wanted to know what was causing prefix to be missing from the post route so I can possibly fix that instead?
I would like to rename my categories URL from https://website.com/categories/apples (#1) to
https://website.com/hi-apples-bye (#2)
I am trying to accomplish two things:
Display the #2 URL in the SITEMAP and PATH
Routes:
resources :categories
get '/hi-:id-bye', to: "categories#show"
However, I get URL https://website.com/categories/apples in the sitemap and https://website.com/hi-apples-bye for the path.
Any help would be appreciated! I am a rookie...
Not sure if you need all category resource routes to have the same route prefix but for the example you have given you could just have:
resources :categories # this is to keep the existing REST routes
# outside categories do ... end
get '/hi-:id-bye', to: "categories#show" # this is to add the route you want
See this section for more details: https://guides.rubyonrails.org/routing.html#non-resourceful-routes
I have a model with uncountable name - class Equipment and in this article (https://markembling.info/2011/06/uncountable-nouns-rails-3-resource-routing) I found that in such cases we get into problems while trying to get model's index path. So article provides tips how to use inflection rules. However, I believe word 'Equipment', just like 'person' is already understood by Rails and I dont even need to define inflection rule, since I still get this path:
equipment_index GET /equipment(.:format) equipment#index
But, for some reason, after I navigate to localhost:3000/equipment_index, I get
No route matches [GET] "/equipment_index"
All other paths works (like localhost:3000/equipment).
Any ideas whats going on..?
p.s. please do not write how to add a custom path. I hope to solve this in the Rails way - convention over configuration. Thanks.
routes:
equipment_index GET /equipment(.:format) equipment#index
POST /equipment(.:format) equipment#create
new_equipment GET /equipment/new(.:format) equipment#new
edit_equipment GET /equipment/:id/edit(.:format) equipment#edit
equipment GET /equipment/:id(.:format) equipment#show
PATCH /equipment/:id(.:format) equipment#update
PUT /equipment/:id(.:format) equipment#update
DELETE /equipment/:id(.:format) equipment#destroy
routes.rb:
resources :users do
member do
get 'generate_raport'
end
end
resources :client_users
resources :clients
devise_for :users, skip: [:registrations]
resources :equipment
root to: 'static#homepage'
equipment_index is a named route, not a url string. The url string that corresponds to this named route is in this part:
GET /equipment(.:format)
When you say:
equipment_index GET /equipment(.:format) equipment#index
you are really saying that equipment_index is a named route (an alias so to say) for the actual url route localhost:3000/equipment. The last part that says:
equipment#index
just says that your request will be routed through the equipment controller and the corresponding index action.
Solution
You can simply navigate to localhost:3000/equipment to get to the index page for your equipment controller.
For example, you would link to this page using a rails link_to helper and the named route discussed above like this:
link_to "My index path", equipment_index_path
Follow up on comments
change add the following line to your routes.rb file directly after the line that contains resources :equipment. It would now look like:
resources :equipment
get 'equipment', to: 'equipment#index', as: 'equipment'
This is convention over configuration!
You're simply reading the output of rake routes wrong or have the wrong expectations about how its supposed to work. The first column is just the name of the route which is primarily used for creating path helpers. The actual paths are in the third column*.
equipment_index_path() # /equipment
equipment_path(1) # /equipment/1
equipment_path() # error due to missing id param
Since equipment is an uncountable noun Rails cleverly avoids an issue where the generated path helpers would be ambiguous - equipment_path could potentially lead to either the index action or the show action. Regular countable nouns don't have this issue so the _index postfix is not usually needed.
# no ambiguity
cats_path() # /cats
cat_path(1) # /cats/1
While you could argue that rails in that case should use the presence of the id param to differentiate that is not how its built and could mask bugs where you pass nil instead of a record.
I am trying to create a separate :show route, to use route globbing on the :id parameter. For this, I created a resource route without the show route and also a separate show route:
resource :test, except: [:show]
get 'test/*id', to: 'test#show', as: :test
the problem is that I receive the error: You may have defined two routes with the same name using the:asoption, or you may be overriding a route already defined by a resource with the same naming.
If I remove as: :test it works. rails routes shows:
tests POST /tests(.:format)
new_test GET /tests/new(.:format)
edit_test GET /tests/:id/edit(.:format)
test PATCH /tests/:id(.:format) <-- WHY??
DELETE /tests/:id(.:format)
GET /tests/*id(.:format)
as you can see, resources renamed the PATCH route to :test. If I remove that route, the DELETE route is named test, and so on. How can I stop resources from using the test route name specifically? I cannot move my globbing route above the resource block obviously because then all other routes are globbed too.
What I want:
tests POST /tests(.:format)
new_test GET /tests/new(.:format)
edit_test GET /tests/:id/edit(.:format)
PATCH /tests/:id(.:format)
DELETE /tests/:id(.:format)
test GET /tests/*id(.:format)
Rails uses the same prefix (say, in your case "test") for all those four routes[show(GET), update(PUT/PATCH), destroy(DELETE)] and it recognises the different routes with the HTTP Verbs.
I don't understand your problem, but if you look on Rails Guides "Singular Resources" you can see:
Path Controller #Action Used for
GET /geocoder/new geocoders#new return an HTML form for creating the geocoder
POST /geocoder geocoders#create create the new geocoder
GET /geocoder geocoders#show display the one and only geocoder resource
GET /geocoder/edit geocoders#edit return an HTML form for editing the geocoder
PATCH/PUT /geocoder geocoders#update update the one and only geocoder resource
DELETE /geocoder geocoders#destroy delete the geocoder resource
show, create, update and destroy use the same route but with different HTTP verbs. And in your case, test wrote with PATCH verb, because this verb earlier in the table, empty name means that it uses the same name as upper line.
First of all,
test PATCH /tests/:id(.:format) <-- WHY??
DELETE /tests/:id(.:format)
GET /tests/*id(.:format)
Patch is for your Update method routes.
Delete is for destroy method route.
that add by your custom route generated by get 'test/*id', to: 'test#show', as: :test
So, here you can make your show route with different alias. Ex like using as :show_test
I have a large number of routes that I would like to separate into different route files.
I created a "routes-secondary.rb" and added some routes there. I then tried to add something like this in the app's main routes.rb:
require "#{Rails.root}/config/routes-secondary.rb"
That does not work however because Rails doesn't recognize the routes in routes-secondary.rb. Is there a way to do this correctly?
(I've updated this answer to take advantage of the RouteReloader for development work)
You can easily accomplish this (even in Rails 4!).
config/routes.rb:
Rails.application.routes.draw do
resources :foo
end
config/routes/included.rb:
Rails.application.routes.draw do
resources :bar
end
config/initializers/routes.rb
Rails.application.routes_reloader.paths.unshift *Dir[File.expand_path("../../routes/**/*.rb", __FILE__)]
This will add all files under config/routes to the application routes, and it'll probably add them in reverse lexical order by filename. If you want to load the routes in a different order, rather than the glob, you can just push or unshift the routes onto routes_reloader.paths in the order desired.
rake routes:
Prefix Verb URI Pattern Controller#Action
foo_index GET /foo(.:format) foo#index
POST /foo(.:format) foo#create
new_foo GET /foo/new(.:format) foo#new
edit_foo GET /foo/:id/edit(.:format) foo#edit
foo GET /foo/:id(.:format) foo#show
PATCH /foo/:id(.:format) foo#update
PUT /foo/:id(.:format) foo#update
DELETE /foo/:id(.:format) foo#destroy
bar_index GET /bar(.:format) bar#index
POST /bar(.:format) bar#create
new_bar GET /bar/new(.:format) bar#new
edit_bar GET /bar/:id/edit(.:format) bar#edit
bar GET /bar/:id(.:format) bar#show
PATCH /bar/:id(.:format) bar#update
PUT /bar/:id(.:format) bar#update
DELETE /bar/:id(.:format) bar#destroy
If you are using Rails 4, you cannot do this out of the box and it's explained here. In rails 3, you can modify your config.paths hash as explained here.