【Rails】ルーティング情報をフィルタリングするコマンド作成
最初に
rails routes
コマンドといって、ルーティングの一覧をだすコマンドがある。
(※rake routes
ではない)
しかし、ActiveStorage周りのルーティングで、めちゃくちゃ幅をとったりして、とても読みにくい。
特定のキーワードでフィルタリングした上で、幅を絞ると見やすくなるのでは、と思い実装した。
探せば同じ目的の機能がありそうだけど、実装も簡単だし、ちゃっちゃと実装した。 lsコマンドのlオプション付きのを実装したことがあるから簡単だった。
コード
以下のコードをrake
ファイルに追記する。
使い方は、コードの先頭に書いたとおり。
# rake routes F=devise # rake routes V=GET F=devise # rake routes V1=PATCH V2=PUT # rake routes F1=devise F2=users # rake routes F1=devise OP=AND F2=users desc 'Print out all defined routes with filtering' task :routes do routes = `rails routes` routes = routes.split("\n") routes.shift routes = routes.select{ _1.index(ENV["V"]&.upcase || '') && _1.index(ENV["V1"]&.upcase || '') && _1.index(ENV["V2"]&.upcase || '') } if ENV["OP"]&.start_with?("A") || ENV["AND"] || ENV["A"] routes = routes.select{ _1.index(ENV["F"]) } if ENV["F"] routes = routes.select{ _1.index(ENV["F1"]) } if ENV["F1"] routes = routes.select{ _1.index(ENV["F2"]) } if ENV["F2"] else r1 = routes.select{ ENV["F"] and _1.index(ENV["F"]) } r2 = routes.select{ ENV["F1"] and _1.index(ENV["F1"]) } r3 = routes.select{ ENV["F2"] and _1.index(ENV["F2"]) } routes = r1 | r2 | r3 end routes.map! do |route| route.gsub!("(.:format)", "") row = route.split row.unshift("") if row.size == 3 row end prefixes, verbs, uris, actions = routes.transpose max_prefix_size = prefixes.map(&:size).max max_verb_size = verbs.map(&:size).max max_uri_size = uris.map(&:size).max max_action_size = actions.map(&:size).max puts routes.map!{ |prefix, verb, uri, action| "#{prefix.rjust max_prefix_size} #{verb.ljust max_verb_size} #{uri.ljust max_uri_size} #{action.ljust max_action_size}" } end
サッと書いたり修正したりしたので、いつもよりバグってるかもしれない。
コード解説
routesコマンド
task :routes do
この部分で、routes
サブコマンドで呼び出すものを定義している。
実際にはRakefileにあり、rake routes
で呼び出す。
ルーティング一覧を取得する
routes = `rails routes` routes = routes.split("\n") routes.shift
Railsから直接取れるのだろうが、Railsの機能を調べるのが面倒そうだったので、
`rails routes`
で直接コマンドを叩いて1回取得して加工することにした。
これをやると、コマンドを2回叩いてることになるので、その分遅くなっているかもしれない。
そのあと、改行"\n"
で分割して行単位の配列にして、routes.shift
でヘッダー部分を取り除いている。
Verbで絞る
routes = routes.select{ _1.index(ENV["V"]&.upcase || '') && _1.index(ENV["V1"]&.upcase || '') && _1.index(ENV["V2"]&.upcase || '') }
Rakeファイルでの引数の取り方がわからなかったので、コマンドの呼び出し時に環境変数を指定してもらって、 環境変数をコマンドライン引数代わりにしている。
V=GET
とすると、GETのルーティングのみに絞れる。
V1=PATCH V2=PUT
とすると、PATCHかPUTのルーティングのみに絞れる。
upcase
をつけて、V=get
のように小文字でも絞れるようにした。
AND検索
if ENV["OP"]&.start_with?("A") || ENV["AND"] || ENV["A"]
OP=AND
やAND=true
と書くと、AND検索になる。
rake routes F1=users F2=posts OP=AND
3列のものを4列に揃える
rails routes
で取れる情報は、path/urlヘルパーメソッドがあったりなかったりする。
いったん行データをsplitで配列して、サイズが3(つまり、3列)なら、空文字列を入れる形で4列にする。
routes.map! do |route| route.gsub!("(.:format)", "") row = route.split row.unshift("") if row.size == 3 row end
あと、"(.:format)"
の文字列は、あっても価値が低く思うので、取っ払うことにした。
transposeして、列幅を求めて出力
全部のデータを4列にしたのもあり、transpose
でデータを転置して、列ごとに取り出せる。
列ごとに取り出して、列ごとの文字列の最大値を求めることで、必要な列幅がわかる。
で、最後にrjust
やljust
を使って、右や左に寄せたりして、出力して終わり。