Rails + Grape 構成で Grape API ファイルを自動再読み込みさせるには
RESTful な API が楽ちんに書ける grape。 rails との組み合わせで使う場合も README に従うだけで簡単に出来ますが、なぜか自動再読み込み (auto reloading) されないって問題にぶち当たります。
development 環境だと model や controller への修正はブラウザをリロードするだけで即反映されますよね。でも grape の api ファイルはなぜか再読み込みされない。いちいち rails サーバを再起動しないといけなくて、非常に困っちゃんです。
(よく理解してませんが rails 上で別の rack フレームワーク(この場合 grape)を動かそうとするとrails の自動再読み込みの仕組みがうまく動かないみたいです)
で、解決方法ですが、grape api ファイルの更新を検知して、無理やり再読み込みさせてやります。
環境
古くてごめんなさい
MacOSX Mavericks ruby 1.9.3p547 (2014-05-14 revision 45962) [x86_64-darwin13.3.0] rails-3.2.11 grape-0.9.0
セットアップ
今回は既存の rails アプリに grape を追加しました。手順をざくっと書いておきます。
Gemfile に追記して、
gem 'grape'
インストール
bundle install
grape api ファイルを置くディレクトリを作って
mkdir app/api
Hello World なやつを書いた。(app/api/skimatalk_api.rb)
require 'grape' # この行は grape 単体で動かす場合に必要。rails との組み合わせでは不要 class SkimatalkApi < Grape::API format :json resource :ehehe do desc 'this is a test' get :hoe do {a: 1, b: 2} end end end
rails と組み合わせて実験する前に grape 単体で動かしてみたかったので、同じディレクトリにテスト用の config.ru を作成 (app/api/config.ru)
# coding: utf-8 require './skimatalk_api.rb' run SkimatalkApi
起動
$ cd app/api $ rackup Thin web server (v1.6.2 codename Doc Brown) Maximum connections set to 1024 Listening on 0.0.0.0:9292, CTRL+C to stop 127.0.0.1 - - [22/Nov/2014 19:54:05] "GET /ehehe/hoe HTTP/1.1" 200 13 0.0971
http://localhost:9292/ehehe/hoe にアクセスすると JSON が表示された。わーい。
(さっき作った config.ru はもう不要なので削除してよいです)
今度はこれを rails 上で動かします。 config/routes.rb に以下を追加して /api/* へのリクエストを grape へ渡すようにします
mount SkimatalkApi => '/api'
サーバ再起動してから、
rails s
http://localhost:3000/api/ehehe/hoe にアクセス。JSON が表示された。やったね。
でも(さっきも言ったとおり)app/api/skimatalk_api.rb
を修正してリロードしても変更が反映されません。困ったね。
解決方法
ここからが本題。
config/initializers/reload_api.rb
を作って以下のように書きます
if Rails.env.development? api_reloader = ActiveSupport::FileUpdateChecker.new(Dir['app/api/*']) do # app/api/* は環境にあわせて変更すること Rails.application.reload_routes! # or do something better here end ActionDispatch::Callbacks.to_prepare do api_reloader.execute_if_updated end end
これだけで、 app/api/* への修正を検知して自動再読み込みしてくれるようになりました。
仕組みは読めばなんとなく分かるよね。分かんなくてもいいよね。
参考
正直このエントリは stackoverflow のこれ↓を解説しただけです。ググって見つけるのに苦労したので書きました…
Ruby on Rails 3 - Reload lib directory for each request - Stack Overflow