GrapeのAPIのエンドポイントをrake routes的に出力する
移転しました →
RailsアプリケーションにGrapeを使って定義したエンドポイントはrake routes
には表示されません。表示されるのはroutes.rb
でマウントしたAPIのルートのみ。
そこで自前のrake routes
を定義してGrapeのAPIもroutesに表示してあげることにしました。
参考
@kamipo こんなんどうでしょ https://t.co/kkSyqiGott 同僚が見つけてきた Grape の routes 出す task + Rails の routes タスク実行したら一緒に Grape のほうも出力するように調整
— Kensuke Nagae (@kyanny) 2013, 10月 22
lib/tasks/routes.rake
上のリンクから持ってきたものを少し変更し、task名をroutes
としています。
desc "API Routes" task routes: :environment do API::Base.routes.each do |api| method = api.route_method.ljust(10) path = api.route_path puts " #{method} #{path}" end end
この状態で$ rake routes
とすると先にGrapeのエンドポイントが出力され、続いてRailsのroutesが出力されます。
こんな感じ。揃っていなくて気持ち悪いですね。
GET /blogs(.:format) GET /blogs/:id(.:format) GET /blogs/:blog_id/posts(.:format) GET /blogs/:blog_id/posts/:id(.:format) Prefix Verb URI Pattern Controller#Action blog_posts GET /blogs/:blog_id/posts(.:format) posts#index POST /blogs/:blog_id/posts(.:format) posts#create new_blog_post GET /blogs/:blog_id/posts/new(.:format) posts#new edit_blog_post GET /blogs/:blog_id/posts/:id/edit(.:format) posts#edit blog_post GET /blogs/:blog_id/posts/:id(.:format) posts#show PATCH /blogs/:blog_id/posts/:id(.:format) posts#update PUT /blogs/:blog_id/posts/:id(.:format) posts#update DELETE /blogs/:blog_id/posts/:id(.:format) posts#destroy blogs GET /blogs(.:format) blogs#index POST /blogs(.:format) blogs#create new_blog GET /blogs/new(.:format) blogs#new edit_blog GET /blogs/:id/edit(.:format) blogs#edit blog GET /blogs/:id(.:format) blogs#show PATCH /blogs/:id(.:format) blogs#update PUT /blogs/:id(.:format) blogs#update DELETE /blogs/:id(.:format) blogs#destroy api /api API
デフォルトのroutesタスクを再定義しよう
Railsのデフォルトタスクはlib/tasks
以下のファイルの読み込み後に行われるため、lib/tasks/routes.rake
ファイルではデフォルトタスクの再定義はできません。
Rubyだからメタに書けばできないことはないんだろうけど、いろいろ試してまだ答えに行き着いていません。今後の課題。
別タスクで無理矢理解決
実際のroutesタスクはruby/2.1.0/gems/railties-4.1.0/lib/rails/tasks/routes.rake
にあります(バージョンは読み替えてもらうとして)。
内容はこうなっています。
desc 'Print out all defined routes in match order, with names. Target specific controller with CONTROLLER=x.' task routes: :environment do all_routes = Rails.application.routes.routes require 'action_dispatch/routing/inspector' inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes) puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, ENV['CONTROLLER']) end
このソースを流用して、Grape APIの結果も含めて出力すりゃいいじゃんということで、ソースはこうなりました。DRY?なにそれ状態。
desc "Routes with API routes" task all_routes: :environment do Rails.application.require_environment! require 'action_dispatch/routing/inspector' all_routes = Rails.application.routes.routes inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes) output = inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, ENV['CONTROLLER']) puts output first_line = output.lines.first verb_index = first_line.index("Verb") pattern_index = first_line.index("URI Pattern") API.routes.each do |api| method = api.route_method .ljust(pattern_index-verb_index-1) # "GET" => "GET " .rjust(pattern_index-1) # "GET " => " GET " path = api.route_path puts "#{method} #{path}" end end
ほんで、$ rake all_routes
ってやるとこういう出力が得られるようになります。
Prefix Verb URI Pattern Controller#Action blog_posts GET /blogs/:blog_id/posts(.:format) posts#index POST /blogs/:blog_id/posts(.:format) posts#create new_blog_post GET /blogs/:blog_id/posts/new(.:format) posts#new edit_blog_post GET /blogs/:blog_id/posts/:id/edit(.:format) posts#edit blog_post GET /blogs/:blog_id/posts/:id(.:format) posts#show PATCH /blogs/:blog_id/posts/:id(.:format) posts#update PUT /blogs/:blog_id/posts/:id(.:format) posts#update DELETE /blogs/:blog_id/posts/:id(.:format) posts#destroy blogs GET /blogs(.:format) blogs#index POST /blogs(.:format) blogs#create new_blog GET /blogs/new(.:format) blogs#new edit_blog GET /blogs/:id/edit(.:format) blogs#edit blog GET /blogs/:id(.:format) blogs#show PATCH /blogs/:id(.:format) blogs#update PUT /blogs/:id(.:format) blogs#update DELETE /blogs/:id(.:format) blogs#destroy api /api API GET /blogs(.:format) GET /blogs/:id(.:format) GET /blogs/:blog_id/posts(.:format) GET /blogs/:blog_id/posts/:id(.:format)
さっきより全然いい。コードは気持ち悪いけど結果はOKです。とりあえずこれでいこうと思います。