RESTful Hypermedia API サーバサイド編 – roar

モバイルアプリサービス部の五十嵐です。

サーバサイド編3回目はroarを紹介します。サーバサイド編としていますが、roarにはクライアント側の機能もあるので併せて紹介します。

roarとは

APIサーバ

roarはこれまで紹介してきたgarageやactive_model_serializerと同様に、JSONなどのAPIをレンダリングします。APIのレンダリングにはRepresentableというgemを使用しています。Representableはhypermedia APIをレンダリングするためのDSLで、active_model_serializerのSerializerと同じような位置づけです。フォーマットは、JSON、JSON-HAL、JSON-API、XMLに対応しています。

APIクライアント

roarはAPIのHTTPクライアントとしても機能します。Representableを使うことでActiveRecordのオブジェクトをリクエストのJSONにパースしたり、レスポンスのJSONをActiveRecordのオブジェクトにパースすることができます。また、HTTPSや証明書による認証などセキュアな機能にも対応しています。

双方向

このように、リクエストのパースやレスポンスのレンダリングをRepresentableが担うことで、サポートされているフォーマットを使うだけでActiveRecordのオブジェクトをデータとしてやりとりすることができます。イメージを簡単に描いてみました。

roar

サンプル

Rails Webookさんが非常に丁寧なサンプルと解説を書かれているので詳細はそちらを参照していただくとして、この記事では重要なパーツだけを簡単に紹介したいと思います。

Representer

SongというオブジェクトのAPIをレンダリングする部分です。active_model_serializerのserializerとよく似ていますので、active_model_serializerの記事を見ていただければどういうものか理解いただけるかと思います。フォーマットを指定する場合は、include Roar::JSON::JSONAPIのようにフォーマットをインクルードします。

# app/representers/song_representer.rb
require 'roar/json/json_api'

module SongsRepresenter
include Roar::JSON::JSONAPI
type :songs

property :id
property :title

has_one :composer
has_many :listeners

link "songs.album" do
{
type: "album",
href: "http://example.com/albums/{songs.album}"
}
end

link "songs.album" do
{
type: "album",
href: "http://example.com/albums/{songs.album}"
}
end

meta do
property :page
property :total
end
end

サーバ側

ActiveRecordのSongクラスに対してSongRepresenterをextendすることで、to_jsonfrom_jsonが使えるようになります。

to_jsonは指定されたRepresenterの通りにレンダリングしたJSONを返します。GETメソッドなどのAPIのレスポンスで使います。

song = Song.new(title: "Fate")
song.extend(SongRepresenter)

song.to_json #=> {"title":"Fate"}

from_jsonはJSONからActiveRecordのオブジェクトに変換します。POSTメソッドなので要求を受け取った時に使います。

song = Song.new
song.extend(SongRepresenter)

song.from_json('{"title":"Linoleum"}')

クライアント側

データの取得の場合はSongオブジェクトを生成してgetメソッドを実行するだけで、結果がsongの中に入り、ActiveRecordのインスタンスとして利用できます。

song = Client::Song.new
song.get(uri: "http://localhost:4567/songs/1", as: "application/vnd.api+json")

データの登録などについても同様です。

song = Song.new(title: "Roxanne")
song.post(uri: "http://localhost:4567/songs", as: "application/vnd.api+json")

所感

いかがだったでしょうか。これまで見てきたものはサーバサイド側だけでしたが、roarはクライアント側もサポートしているので、Railsアプリケーション同士の連携や、RailsのAPIとRubyのクライアント用のライブラリをセットで提供することが容易になります。また、対応しているJSONフォーマットであれば受信したリクエストのパースもしてくれるので、APIの開発が省力化できそうです。

参考