一番大きなところでは、以下のように設計の考え方が異なる。
- v1 : 1 screen, 1 API call. 画面に必要なものを全て返すエンドポイントを作っていく設計。
- v2 : リソースごとにエンドポイントを作っていく設計(RESTful API)。
RESTful に API を作っていくことの大きなメリットは、アプリの画面と API の結合性が低くなり、生産性が上がること。 具体的には、Web エンジニアがアプリの画面の詳細まで知らなくても設計ができる、iOS と Android で実装状況が異なる場合にも API の中で条件分岐が必要ない、といったことが挙げられる。
これは別の見方をすると、あるエンドポイントが様々な画面で使われるということになる。 画面によって必要な情報の多寡は異なるので、スケールするように、v2 ではデフォルトではリソースの id のみを返し、それ以外の情報は全てホワイトリストで取得する。
v1 と異なり、{ "data": { ... }}
と言った data
によるラッピングは行わない。
これは、HTTP ではヘッダーが用意されており、メタデータはここに入れることができるため。
オブジェクトが返る。
# GET /api/v2/users/1
{ "id": 1 }
オブジェクトの配列が返る。
# GET /api/v2/users
[{ "id": 1 }, { "id": 2 }, ...]
HTTPステータスは通常の使い方に従う。
より詳細なエラー情報として、message
と error_code
をボディに含める。
{ message: "...", error_code: 100 }
例えば、ユーザー情報を取得する場合、fields=name
のように指定すると id に加えて名前が返る。
複数指定する場合、カンマ区切りで fileds=name,facebook_uid
とするか、角括弧を使って fields[]=name&fields[]=facebook_uid
とすることで可能。
例えば、ユーザーの画像のURLを一緒に取得する場合、include=avatar&fields=avatar.url
のように指定するとアバターのURLも同時に取得できる。この場合、avatar アソシエーションのフィールド url を avatar.url
といった形で取得している。
例えば会社の社員インタビュー一覧のエンドポイント GET /companies/:id/employee_interviews
があって、そこでインタビュータイトルと同時にユーザーの名前とアバターURLを取得したい場合、パラメータは、次のようになる。
include=user,user.avatar&fields=title,user.name,user.avatar.url
事前にどんなパラメータがあるのかこのままでは仕様書が無い限り分からないので、debug
パラメータを用意してある。これを true
/ t
に設定すると、全フィールドと一段階までのアソシエーションが全て返る。production 環境では利用できないので注意。
ソートはデフォルトで一覧エンドポイントのテーブルのカラムに対して行えるようになっている。
例えば、col1
, col2
というカラムを持つテーブルであれば、+col1
, -col1
, +col2
, -col2
をデフォルトで受け付ける。
具体例として、ユーザーを名前を昇順で取得したい場合、sort=+name_ja
といった形で指定できる。ユーザーを facebook_uid の降順で取得したい場合、sort=-facebook_uid
といった形で指定できる。カンマで区切ることで複数のカラムでのソートも可能。
controller 側で sort_param
を使うことで、対象テーブルのカラム以外でのソートを定義することも可能。
例えば、 companies#employees
では sort=-score
によって Wantedly スコアの降順でのソートを提供している。大きく、昇順なのか降順なのかは常にあるので、+
か -
を先頭につけておくのがベター。
一覧エンドポイントで per_page
, page
パラメータを指定することでページングができる。
デフォルトで以下の情報がレスポンスヘッダーに入る。
X-List-CurrentPage: 4
また、page_count
パラメータを true に設定することで、次の情報も返る。
バックエンドでは COUNT クエリが余分に一個走るため、デフォルトの挙動にはなっていない。
X-List-TotalCount: 123
X-List-NumPages: 1
X-List-IsFisrtPage: true
X-List-IsLastPage: false
一覧系のエンドポイントでは様々なパラメータでフィルタリングすることが考えられるので、既に挙げたパラメータ以外の任意のパラメータが実装される。 どういう利用可能なパラメータについては、後述するように controller の引数に明示される。
おおよそ以下の資料に書いてあるような方針で設計している。