以下のPRで導入されたRails 6.1から使える機能を使うといい感じでroutesを複数ファイルに分割できたのでやり方をメモしておきます📝
やり方
以下のようなroutesをnamespace毎に分割したいときには、
Rails.application.routes.draw do root to: 'boards#new' resources :feeds, only: [:index, :show, :new, :create] resources :boards, only: [:show, :new, :index], constraints: { format: :html } get '/boards/:id', to: 'rss/boards#show', constraints: lambda { |req| req.format == :rss } get '/mypage', to: 'mypage#show' namespace :api do resources :feeds, only: [:index, :show] resources :feed_entries, only: [:index], controller: 'feed/entries' resources :entries, only: [:index] resources :boards, only: [:create, :show, :index] resources :tags, only: [:index] end namespace :admin do root to: 'boards#index' resources :boards resources :board_feeds resources :feeds require 'sidekiq/web' mount Sidekiq::Web, at: '/sidekiq' end end
以下のようにcoufig/routes
配下にファイルを分けて、
# config/routes/admin.rb Rails.application.routes.draw do namespace :admin do root to: 'boards#index' resources :boards resources :board_feeds resources :feeds require 'sidekiq/web' mount Sidekiq::Web, at: '/sidekiq' end end
# config/routes/api.rb Rails.application.routes.draw do namespace :api do resources :feeds, only: [:index, :show] resources :feed_entries, only: [:index], controller: 'feed/entries' resources :entries, only: [:index] resources :boards, only: [:create, :show, :index] resources :tags, only: [:index] end end
config/routes.rb
で以下のようにdraw :filename
としてあげればOKです🙆♂️
Rails.application.routes.draw do root to: 'boards#new' resources :feeds, only: [:index, :show, :new, :create] resources :boards, only: [:show, :new, :index], constraints: { format: :html } get '/boards/:id', to: 'rss/boards#show', constraints: lambda { |req| req.format == :rss } get '/mypage', to: 'mypage#show' draw :api draw :admin end
drawメソッドの中身は以下のような形になっていて、引数で渡されたfile名で探索して、instance_evalで分割したファイル内の処理を実行することで、分割したファイル内の処理をroutes.rb
で実行することで、routesを定義しているようですね👀
# actionpack/lib/action_dispatch/routing/mapper.rb def draw(name) path = @draw_paths.find do |_path| File.exist? "#{_path}/#{name}.rb" end unless path msg = "Your router tried to #draw the external file #{name}.rb,\n" \ "but the file was not found in:\n\n" msg += @draw_paths.map { |_path| " * #{_path}" }.join("\n") raise ArgumentError, msg end route_path = "#{path}/#{name}.rb" instance_eval(File.read(route_path), route_path.to_s) end
おわりに
サービスが大きくなるとroutesが肥大化してきて辛くなってくると思うのですが、標準機能でこの辺に楽に対応できるのは良いですね✨