:::: MENU ::::

VersionistとRablを使ってRailsのAPIをバージョン管理


こんにちは、sovaのはき猫です。今年もサクラがキレイでしたね。

先日、sovaで初のアプリケーションである「クローズドな掲示板アプリ – CircleBoard –」をリリースしました!是非使ってみて下さい。

さて、sovaでは次のプロジェクトが開始しようとしています。次のプロジェクトではフロントエンドにBackbone.Marionetteを使い、バックエンドはRailsでAPIのみを提供するアーキテクチャを考えています。

バックエンドはAPIを提供するのみなので、APIのバージョン管理が重要になってきます。そこで、RailsでAPIのバージョン管理をする方法について調べてみました。

Grapeを使う

一番最初に見つけたのがGrapeを使ってAPIのバージョン管理をする方法です。下記サイトを参考にさせて頂きました。

調べたところ、Grapeを使うと既存のRailsコードとは別にSinatra風のDSLを使ってバージョン管理されたAPIを提供出来るようにするgemのようです。
使い方は公式githubのサンプルに載っていました。

gemのインストール

使い方

公式のgithubにTwitter APIのサンプルが載っていました。一部を抜粋して転記します。
興味のある方は公式のgithubなどを参照してみて下さい。
Grapeを使えばAPIのバージョンと提供するAPIのメソッド群を定義すれば簡単にバージョン管理されたAPIを提供することが出来るgemみたいです。

ぱっとみた印象だと、Sinatraにバージョン管理を付加したような作りだと思いました。
(公式githubにはSinatraとGrapeを一緒に使う方法も載っていました)

今回作るアプリケーションは提供するAPIの数が少なくないので、Grapeのように1ソースに全て書けてしまえるような仕組みより、Railsのように規約によって縛られて、コード分割が明確な仕組みの方が合っているので、Grapeの採用は見送ろうと思いました。

VersionistとRablを使う

前述のようにGrapeは合わないと思ったので、違うgemを探していたところ、Versionistというgemに出会いました。下記サイトを参考にさせて頂きました。

Versionistを使うと既存のRailsコードのようにgeneratorを使って効率よく開発することが出来ます。
このgemが良さそうだったので、サンプルでAPIを作ってみました。VersionistとRablを使ってjsonを返すAPIの作り方を紹介します。

gemのインストール

VersionistのJSONパーサにはOJとYajlが使えるみたいですが、OJの方がYajlより高速とのことなので、今回はOJを使うことにしました。

使い方

今回はサンプルとして以下のようなRest APIを作ってみます。

 URL   メソッド  内容
 /v1/books   GET  全ての本を配列で返す
 /v1/books/:id   GET  :idで指定された本の値を返す
 /v1/books   POST  新しい本を追加する
 /v1/books/:id   PUT  :idで指定された本の内容を更新する
 /v1/books/:id   DELETE  :idで指定された本を削除する

Versionistではgeneratorも用意されているので、generatorを使いつつ開発を進めることが出来ます。まずはV1のbooksコントローラとBookモデルを作成します。

すると、controller以下にv1というディレクトリが出来て、そこにbooks_controller.rbが作成されます。その他色々なディレクトリにv1ディレクトリが作成されます。

続いてbooks_controller.rbを編集してRest APIを作っていきます。バリデーションやエラー制御を全くしていないですが、単純なCRUDが出来るようになります。普通のRailsですね。

次にRablを使ってAPIで返すJSONを定義していきます。

まず、GET /v1/books/:idのAPIが呼ばれた時に返すshow.json.rablの定義をしています。まず、先頭のobjectでcontrollerで格納された変数@bookを使うことを宣言しています。2行目のattributesでJSONに含めるkey要素を指定しています。3行目のnodeは単純にモデルの値を返すのではなく、何かしら加工した後に返すような場合に使います。この例ではModel側ではrelease_dateと定義しているキーをJSONで返す時にはreleaseDateに変換しています。

次のGET /v1/booksが呼ばれた時に返すindex.json.rablではobjectではなくcollectionで指定しています。collectionを指定することで、JSONを配列として返すことが出来ます。2行目のextendsでその他のattributeはshow.json.rablと同じ値を使うことを宣言しています。

最後のcreate,update,deleteでは全てshow.json.rablと同じ値を使うように定義しています。

これでRest APIが完成しました。

動作確認

curlコマンドを使って動作確認してみます。動作確認する前に適当にDBにデータを入れておいて下さい。

少し見づらいですが、/v1/books にアクセスした時は配列で全ての本要素が返されています。/v1/books/1 にアクセスした時は指定されたID要素の本要素が返されています。Rest APIで本要素が取得出来てますね。

バージョンアップするとき

バージョンアップする時はVersionistのコマンドを使って簡単に行うことが出来ます。ただし、RablでJSONのレスポンスを定義している場合はVersionist管理外なので、Rablファイルは自分でコピーする必要があります。
詳しくは公式ページを見た方が早いですが、公式サイトのサンプルを一部を抜粋して掲載しておきます。v2 -> v3にマイグレーションする時の例です。

まとめ

如何でしょうか。VersionistとRablを使えば通常のRailsアプリ開発と同じノリでバージョン管理されたAPIの開発を行うことが出来ます。Sovaではこの仕組みを使ってアプリ開発を行っていこうと思っています。

もし他にいいやり方等があればコメントかDMでアドバイス頂ければと思います。

Twitter: @sovaLab


So, what do you think ?