RailsアプリケーションにGrapeを使って定義したエンドポイントはrake routes
には表示されません。表示されるのはroutes.rb
でマウントしたAPIのルートのみ。
そこで自前のrake routes
を定義してGrapeのAPIもroutesに表示してあげることにしました。
参考
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です。とりあえずこれでいこうと思います。