複数のリソースに一度にアクセスしたいときのURL設計

RESTとRailsスタイル]」のときに、@shu_0115さんから「複数同時に書き込みたいときはどうするか」という質問がありました。これは実用上はなかなか重要な点だと思うので、少しまとめます。

親子関係のリソースを更新

例えば /users/123 と /users/123/profile を両方変更したいなど。
この場合は、親に対するリクエス

PUT /users/123

だけですませるのが一般的です。POSTでユーザを新規作成するときも、自動的に子のリソースが作られたとみなしますよね。

複数のMemberリソースを更新

例えば /posts/1 /posts/2 /posts/3 の3つの投稿に同時に「rest」タグをつける、というUIがあるかもしれません。
この場合、とくにアトミックな必要はないので、Ajaxでリクエストを3回送ってもかまわないのですが、3個ならまだしも10個などになるとひどいので、パフォーマンスの観点から、そういう用途が必要ならCollectionリソースを使って

POST /posts

で、リクエストボディでIDとタグデータを送る、というのがいいと思います。このようなインターフェイスをバルク更新もしくはバッチ更新といいます。

複数のMemberリソースを取得

実は、複数のMemberリソースは、更新(作成)よりも取得のほうが需要があります。例えばCollection内に非常に多くのMemberリソースがある状況で、特定の複数のリソースをIDからピックアップしたい、などです。10個ピックアップしたいときに10回リクエストするのはとても非効率です。
この場合は、IDを列挙するURLを使って

GET /posts/1,2,3

とすることができます(コンマの代わりにセミコロンでも可)。これをバルク取得といいます。
前節の更新は、このURLを使ってPUTメソッドで設計することもできます。

ステータスコード

バルク取得、バルク更新は、複数の処理が行われるということなので、一部だけエラーという可能性があります。アトミックな処理なら全部がエラーとすればいいのですが。
この場合は、しょうがないので 200 OK または 207 Multi-Status を返して、レスポンスボディ内にどれが成功してどれが失敗したのかを記述します。

複数のリソースをアトミックに作成・更新

トランザクションリソースを使います。
(詳細省略)

所感

Twitterは、バルク取得APIをつくってよ。1個1個取ってたらすぐAPI制限に引っかかるんだよ…。
と前から思っていたこともあって書いてみました。