Rails 5 rename single resource route name - ruby-on-rails

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

Related

Rails routes do not contain id in that

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

Rails uncountable model name, no route matches get name_index

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.

Is it possible to include external routes files into the main routes.rb file?

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.

How to pass and receive parameters in url in Ruby on Rails?

I am new to ruby, i would like to pass parameters in the url and receive it in controller.
I am expecting operation like
www.mysite.com/getuser/id/22
where getuser is the param name and 22 is its value.
Please provide me if there is any useful links that i can refer to.
Thanks in advance
Please read everything in the Rails Guide to Routing. There are two main cases there:
RESTful routes: only use GET, PUT, POST, DELETE. Rails maps that by using the method resources. resources :pages will lead to the following routes (and URLs) automatically:
sites GET /sites(.:format) {:action=>"index", :controller=>"sites"}
POST /sites(.:format) {:action=>"create", :controller=>"sites"}
new_site GET /sites/new(.:format) {:action=>"new", :controller=>"sites"}
edit_site GET /sites/:id/edit(.:format) {:action=>"edit", :controller=>"sites"}
site GET /sites/:id(.:format) {:action=>"show", :controller=>"sites"}
PUT /sites/:id(.:format) {:action=>"update", :controller=>"sites"}
DELETE /sites/:id(.:format) {:action=>"destroy", :controller=>"sites"}
Other routes: There is a rich set of methods you can use in your routes file to add additional routes. But keep in mind: If you just want to address a resource, it is better to stick to restful routes. A typical example is_ match ':controller(/:action(/:id))'. This allows URLs like:
localhost:3000/sites/help: controller == SitesController, action == help
localhost:3000/sites/search/something: controller == SitesController, action == search, parameter in params is something under the key id. So inside the action search, you will find params[:id] bound to "something".
In your config/routes.rb file you write:
resources :users
Then you create the controller:
rails g controller users
Inside your controller file you have something(contrived) there like :
def show
my_id_param = params[:id]
end
When you go to:
www.mysite.com/user/22
my_id_param will be 22
I think rails guides are quite good resource, just google for them, has ton of good info there.

Ruby on Rails 3: Change default controller and parameter order in routing

I have a Rails app that has a controller called domain which has a nested controller called subdomain and stats. I have defined them in routes.rb:
resources :domains do
resources :subdomains, :stats
end
I have changed the to_param of the domain and subdomain models to use the name of the domain, e.g.: the routing I get is http://site/domains/foo/subdomains/bar.
I would like to tidy it up to so that instead of using http://site/domains/foo/subdomains/bar I could access it with just http://site/foo/subdomains/bar. I have tried the following in routes.rb:
match "/:id/" => "domains#show", :as => :domain
Which works fine, but it only gives me the ability to use the path http://site/foo but for example http://site/foo/subdomains/bar doesn't. I could create match lines for every respective model and nested model but that does nothing to other helpers besides domain_url - i.e. edit_domain_url points to /domains/foo/edit/ instead of /foo/edit.
Is there a way to change the routing so that the resources generates helpers that point to the root url without the 'domains' part?
The single match in your routes creates only one route. Resource helpers create many routes at once. Luckily there are a lot of options for customisation. If you want to omit /domains/ from your paths, it's as simple as:
resources :domains, :path => "/" do
resources :subdomains, :stats
end
With the above in config/routes.rb, running rake routes says the following:
domain_subdomains GET /:domain_id/subdomains(.:format)
domain_subdomains POST /:domain_id/subdomains(.:format)
new_domain_subdomain GET /:domain_id/subdomains/new(.:format)
edit_domain_subdomain GET /:domain_id/subdomains/:id/edit(.:format)
domain_subdomain GET /:domain_id/subdomains/:id(.:format)
domain_subdomain PUT /:domain_id/subdomains/:id(.:format)
domain_subdomain DELETE /:domain_id/subdomains/:id(.:format)
domain_stats GET /:domain_id/stats(.:format)
domain_stats POST /:domain_id/stats(.:format)
new_domain_stat GET /:domain_id/stats/new(.:format)
edit_domain_stat GET /:domain_id/stats/:id/edit(.:format)
domain_stat GET /:domain_id/stats/:id(.:format)
domain_stat PUT /:domain_id/stats/:id(.:format)
domain_stat DELETE /:domain_id/stats/:id(.:format)
domains GET /(.:format)
domains POST /(.:format)
new_domain GET /new(.:format)
edit_domain GET /:id/edit(.:format)
domain GET /:id(.:format)
domain PUT /:id(.:format)
domain DELETE /:id(.:format)
Looks like all the routes you need!

Resources