How to split routes.rb into smaller parts?
… and check why 5600+ Rails engineers read also this
How to split routes.rb into smaller parts?
Each application created using Ruby on Rails framework has a routing engine and config/routes.rb file where we define routes paths. That file very often becomes very large in the proces of development. Each additional line makes the routing file harder to maintain. Also, searching for specific paths during the development phase becomes increasingly difficult. Currently, I work on an application in which the routing file contains about 500LOC. Quite a lot, isn’t it? The solution is very simple. All you need to do is split the file into a couple of smaller ones.
Order of loading files
When a request comes, routes.rb file is processed in “top to bottom” order. When the first suitable entry is found, the request is forwarded to the appropriate controller. In case of not finding a matching path in the file, Rails will serve 404. Because of the possibility of sorting the order of loading files, we can define the priorities for our namespaces.
Solution
The following example is a short part of routes.rb:
ActionController::Routing::Routes.draw do
root to: "home#index"
get "/about
get "/login" => "application#login"
namespace :api do
#nested resources
end
namespace :admin do
#nested resources
end
namespace :messages do
#nested resources
end
namespace :orders do
#nested resources
end
end
There are some some default namespace (with /home, /about, /login routes) and four other namespaces. These namespaces define nicely existing contexts in our application. So, they are great canditates for division to other files. So we have created api.rb, admin.rb, messages.rb and orders.rb. Usually, I put the separated files in config/routes/ directory which is created for this purpose. Next step is to load above files. We can do this in several ways. In applications based on Rails 3, loading route files from application config is a very popular method . Finally, we have to add to our application.rb following line:
config.paths["config/routes"] += Dir[Rails.root.join('config/routes/*.rb’)]
If you want to have control over the order of loading files you can do this this way:
config.paths["config/routes"] = %w(
config/routes/messages.rb
config/routes/orders.rb
config/routes/admin.rb
config/routes/api.rb
config/routes.rb
).map { |relative_path| Rails.root.join(relative_path) }
However, since version 4 of Ruby on Rails if you attempt to add the above line application will throw an exception. The Rails 4 does not provide [‘config/routes’] key in Rails::Engine. There is another option that works in both versions of the framework. Here we have another solution:
YourApplication::Application.routes.draw do
def draw(routes_name)
instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
end
draw :messages
draw :orders
draw :api
draw :admin
root to: "home#index"
get "/about
get "/login" => "application#login"
end
It allows us to add a new method to ActionDispatch::Routing module which helps as to load paths. Rails 4 initially had a similar solution but it has been removed. You can check out the git commit here: https://github.com/rails/rails/commit/5e7d6bba79393de0279917f93b82f3b7b176f4b5
Conclusion
Splitting files is a very simple solution for improving the condition of our routes files and developers lives. In this regard, this solution makes life easier in this.