$resourceでmetadataをいいカンジに扱う
TL;DR
'transformResponse': function (data, headersGetter) {
var result = angular.fromJson(data);
result.data.$metadata = result._metadata;
return result.data;
},
'interceptor': {
'response': function (response) {
response.resource.$metadata = response.data.$metadata;
return response.resource;
}
}
WHAT
以下の様なレスポンスを返すAPIがあるとする.
{
"data": [
{ "id": 1, "content": "kokoro pyonpyon" },
{ "id": 2, "content": "Ah^~ my heart will be hopping^~" }
],
"_metadata": {
"total": 53,
"nextPage": 2
}
}
普通にtransformResposne
通すだけだと,_metadata
が落ちてしまう.
あとのコールバックで_metadata
を利用したいのでそれは困る.
HOW
transformResponse
の返り値に$metadata
をつっこみ,interceptor
内でresource
に押し付ける.
var app = angular.module('app', ['ngResource']);
app.factory('Post', [
'$resource',
function ($resource) {
var endpoint = 'api/v1/posts/:id';
var params = {};
var actions = {
'query': {
'method': 'GET',
'isArray:' true,
'transformResponse': function (data, headersGetter) {
var result = angular.fromJson(data);
result.data.$metadata = result._metadata;
return result.data;
},
'interceptor': {
'response': function (response) {
response.resource.$metadata = response.data.$metadata;
return response.resource;
}
}
}
};
$resource(endpoint, params, actions);
}
]);
動作の流れ
上記のコードでは,デフォルトの代わりに利用するinterceptor
を定義している.
src/ngResource/resource.js#L558-L559 from angular/angular.js
// src/ngResource/resource.js#L558-L559
var responseInterceptor = action.interceptor && action.interceptor.response ||
defaultResponseInterceptor;
デフォルトのinterceptor
(defaultResponseInterceptor
)ではresponse.resource
を返すようになっている.
src/ngResource/resource.js#L497-L499 from angular/angular.js
// src/ngResource/resource.js#L497-L499
function defaultResponseInterceptor(response) {
return response.resource;
}
response.resource
にはAPIのレスポンスをResource
でラップしたものが入っていて,それが最終的に呼び出し元に返される.
ということで,response.resource
に$metadata
を押し付けておけば後から取り出してほげほげできるというわけ.
Railsでいうindex
ライクな,リストを返すAPIが上記の形式({ "data": [...], "_metadata": {...} }
)で統一されているならば,transformResponse
やinjector
をうまくサービス化してDRYにできるかもしれない.
transformResponse
とinterceptor
を使いこなしたイケてるコードを書こう.