Rails routing conditions for a DRY routes.rb file
Stefan Natchev | 15 April 2013
Rails routing gives you the ability to set any number of scopes and constraints on your routes. These conditions must all match for the route to match. Sometimes, we want to have any one of the conditions to be true in order to match a route.
For example, we want both of these urls to route to the same actions:
- With a path prefix
- With a subdomain
Unfortunately, the following mapping produces a condition on both having the subdomain and path prefix.
constraints subdomain: "api" do scope "/api" do controller :api do post :register end end end
That route will only match
http://api.example.com/api/register. Not quite what we are looking for.
Initially, we would have to duplicate all of our endpoints wrapped in a subdomain constraint and a path scope:
Rails::Application.routes.draw do constraints subdomain: "api" do controller :api do resources :widget post :register get :help end end scope "/api" do controller :api do resources :widget post :register get :help end end end
This is not a great solution since any new controller actions would require changes in two places.
A Better Way
A neat trick is to define a method inside the routes block that emits the routes. This can then be wrapped by the scope and constraints conditional.
Rails::Application.routes.draw do def api_endpoints controller :api do resources :widget post :register get :help end end constraints subdomain: "api" do api_endpoints end scope "/api" do api_endpoints end end
This is a great way to group your endpoints into logical chunks that can be reused in different contexts.