restfulとは何ぞやを紐解いてみました
今まで動いてくれれば良いベースでむりくりモノを動かしてきた自分には、根本からの設計をきちんと行えないエンジニアとしてのレッテルが付いている気がしてならないので、根幹的な理解を深めていこうと考えました。railsでモブプロをやっていて、URLとHTTPメソッドの紐付けを『こうすりゃこうなんのよ』での理解だったので、ここを説明する出来るところまで落とし込んでみようと考えました。
本篇
restfulについて調べる&教えてもらったものを纏めます。
まず、前提としてrestfulには、3つの文脈があります。
- RESRfulとその影響を強く受けて決められたRailのフレームワークの規約
- 通信やAPIの規格としてのREST
- REST API
これらです。今回は、一番上のRESTfulとその影響を強く受けて決められたRailsのフレームワークの規約をテーマに纏めています。
RESTful
webアプリケーションをユーザ都合の機能からではなく、リソースを定義して、リソースに対する一覧、詳細、更新、削除という状態の変化とHTTPメソッドを結びつける考え方をRESTfulという。
アプリケーションの機能とHTTP通信の仕様をHTMLフォームを仲介して結びつけたのが rails流の RESTfulの規約となっており、何も縛りがないと、ユーザーの行動に基づいてcontrollerのアクションを作りがちになる。
RESTfulでない場合、以下のようなよく分からないcontrollerが生まれてしまう。
アクション名も自由なので、def commentがコメントを見るのか、更新するのかわからない様な状況を防ぐ為のものとしてrestfulが機能していると言う事です。
つまり、『RESTfulで書かれている』 = 『挙動が明示的であることの保証』と言う図式を成り立たせているわけです。
リソースに対して、どんなアクション(操作)を使いたいかで、HTTPメソッドとURLが決定されることが利点として存在する。わかりやすいURL設計を可能にするというのは、自分が簡単に作れるという意味ではなく、何もしなくても、操作が自明なURLが作られるということである。
このように、自明にリソースの場所を指し示すことができることをアドレス可能性と呼ぶ。
def create_blog
end
def comment
getだったら詳細、postだったら更新とか。。。
end
RESTfulで考えるとリソース(URIで表現可能なもの。つまり、HTTP経由で自由にURIとHTTPメソッドで操作が可能なデータ群の事を総じてリソースと言う)をblog、comenntと別々に定義して、blogs_controllerの責務はblogリソースの一覧、詳細、作成、更新と考えられるので、どんな要件が定義されていても基本骨格は一般的なCRUDの体裁になります。つまり、統一されたURI設計によって、どのようにリソースが操作されているかがよくわかると言うことです。
アクションがどうやって紐づけられているのか
htmlのformがgetとpostにしか対応していないので、rails側で、hiddenやdata属性としてgetやpost以外のメソッドを指定するように工夫しています。検証モードで見に行くと、それがよくわかります。
HTTPの通信としてのブラウザの対応状況、HTML5とかの規格しての対応状況などを考えると、確実なのはGETとPOSTしかないという感じなので、railsがviewに力技でhiddenを埋め込んで、rails流のRESTfulを実現しているようです。
HTTP Method | id | no_id |
---|---|---|
Get | Show Edit | index new |
Post | create | |
Put(Patch) | update | |
Delete | destory |
railsでは上記の様な形で、restfulを再現しています。
パラメータとしてidがあるかないかが大きな意味を持ちます。idがある(リソースを一意に特定できる)場合の確認画面はshowやeditと全く同じです。idがない場合はnewと同じです。
(EditとNewは、rails特有で、操作をさせる訳ではなく、編集画面(edit)や新規作成画面(new)を表示させたいからshowやindexと便宜上分けているだけ。リソースに対する操作ではない。htmlを操作する場合に、コードとして操作を自明にさせたいから、本来、idの有無のURLとHTTPメソッドですおさが決まるはずのに,URLに/editや/newがあるのはそのため)
例えば「インプレイスエディタ」を例にとりますと、詳細「show」も編集「edit」も同じactionであるviewで処理されます。getという表示させるだけのHTTPメソッドが使われていることからもそれが自明です。
つまり、画面やユーザーの得る機能の差異とRESTfulとしての機能差異は実は関係ないものもあるのです。画面やユーザーの得る機能でURL設計を行わずに リソースの操作としての差異に注目してURLを設計しましょうというが、RailsのRESTfulの発想です。
異なるリクエストでもリソースへのCRUD操作が同じであれば、ユーザーへの機能要件の異なる機能の実装をパラメータできりわけてもよいし、アクションを別にした状態でまとめても良いです。しかし、リソースへの操作が異なればまとめてはいけないとなります。
restfulの例外について
POSTでリソースをIDで特定しない時、このリクエストはRESTfulでいうと、リソースの新規作成の意味になります(create)。ところが検索は条件付きの一覧表示(index)です。RESTfulに強いこだわりをもつなら、検索もGETにするべきでしょう。またSEOの観点からパラメータをつけてURLを別にした方が、検索結果ページの順位に有利働く場合などもあり、検索ならフォームをGETにしておいた方が無難なことが多いです。
でも、「ブログの編集を確認画面を挟んで完了する」という要件はどうか?フォームに記入して「確認」を押してもリソースは更新されず、次の確認画面に進むのでPUTだとNGです。PUTは確認画面の「更新」ボタンを押したときのアクションです。しかし、GETは文字数の制限もありますし、パラメータに入力項目が表示される問題もありますので、POSTが妥当です。
POSTでID指定という機能はRESTfulには定義されてませんが、この場合はアリでしょうか?結論から言うと複数の画面をはさむクイズ形式のアプリやなど、RESTfulで収まらない場合は多々あります。可能な限りRESTfulにしましょうという感じです。よくあるユーザーのホームなどもリソースを限定できない機能が多数あります。
つまり、できる限り1リソースに対して機能としてリソースに機能を1つ1つ切り分けて行くことを行い、機能として切り分けができないようなものは、例外機能として書いておくと良い。