SinatraアプリをRailsアプリに組み込む

今やってるプロジェクトでSinatraでつくったアプリケーションをRailsアプリに組み込む必要があったので,アプリを作るところから作業を簡略化してメモする.

ぼやき

自分のケースだとSinatrajQuery Mobileを扱っててRailsAPIサーバに使うという「普通逆だろ!」とツッコミを受けても文句言えない状態(言い訳だけど最初はAPIサーバつくる予定じゃなかったし,Sinatraのほうは破棄するつもりだった).Githubなんかは逆にSinatraで実装したAPIRailsにマウントしている.フレームワークの立ち位置から考えるとそれが正しいと思う. 詳しくはこのスライドを参照すること.

まずRailsアプリをつくる

rails new hoge

index.htmlを削除しておく

cd hoge
rm ./public/index.html

Gemfileにsinatraを追記する

gem "sinatra"

bundle installは忘れずに

bundle install

Sinatraアプリを配置する

Sinatraアプリの名前はfooとする.(Railsアプリのルート)/lib/fooというディレクトリをつくる

mkdir ./lib/foo # カレントディレクトリはRailsアプリのルート

foo配下に以下の内容のapp.rbを作成する.

class Foo < Sinatra::Base
  get '/' do
    'this is /'
  end 

  get '/a' do
    'this is /a'
  end

  get '/a/b' do
    'this is /a/b'
  end
end

SinatraアプリはModularスタイルで書く.静的ファイルやビューファイルの設定が必要な場合はする.

libに置いただけでは読み込まれないので, (Railsアプリのルート)/config/initializers/foo.rbというファイルを置いて,起動時にapp.rbをrequireするようにする.

require Rails.root.join('lib/foo/app')

マウントする

config/routes.rbにSinatraアプリをマウントする旨を記述する.

Hoge::Application.routes.draw do
  mount Foo, :at => '/'
end

おしまい

Railsアプリを起動して, 「http://localhost:3000/a/b」にアクセスすると「this is /a/b」と表示されるはず.

まとめてみると簡単なのだが,自分の場合,Sinatraアプリの方でrootの設定をしていたせいでハマった.Sinatraアプリでrootの設定をすると「/」や「/a」にはアクセスできるのに「/a/b」のような一段以上深い階層は「ルーティングがみつかりません」と怒られる.rootの設定を外すとうまく動いた(そもそも組み込んでるのにrootの設定をするのがナンセンス?).ここらへんの動きがよく分からないのでRails, Sinatra, Rackの中のことを学んでいく必要性を感じてる.とりあえずは手始めに入門SinatraとかCrafting Rails Applicationを辞書をひきつつ読んでる.