RailsのURL設計を考えてみる(6) 設計の選択肢
今回は直接Railsとは関係ないのですが、先日こういうページを見つけました。
これは2009年に書かれたもののようですが、URL設計に関する重要な考え方がいろいろ書かれています。
その中に、このブログのシリーズの(4) スラッシュと「持っている」関係や(5) Railsのリソースパターンの前段階になるような“Choosing a URI schemes for resource hierarchies”という話があったので、かいつまんで紹介したいと思います。
リソースの階層に対して、どういうURLを設計するか?
前提として、設計するWebサイトには、conversation(会話)というリソースが複数あり、それぞれのリソースはユニークなIDで区別されるとします。(IDは数字とは限らない識別子)
/conversations
と /conversation/{id}
/conversations
ですべての会話/conversation/{id}
でID=id
の会話
全体の会話は複数形、特定の1つの会話は単数形という考え方。
英語としては自然なのかもしれませんが、わざわざ使い分けるほどの意義は薄いし、後者でパスを削った /conversation
は何を指すのかという問題が残ります。
/conversations/conversation/{id}
/conversations
ですべての会話/conversations/conversation/{id}
でID=id
の会話
先ほどと比べると1種類のパスに統合されましたが、やはり /conversations/conversation
が何を指すのかが謎です。
/conversations/{id}
/conversations
ですべての会話/conversations/{id}
でID=id
の会話
Rails方式です。これでパスを削っても問題なくなりました。ただし、新しい会話を作成するための画面に用いる /conversations/new
という補助的リソースが、ID=new
のリソースと区別できなくなるという問題があります。これは比較的小さな問題ではありますが、前の2つの方式ではこの問題は起こりません。
/conversations/conversation-{id}
/conversations
ですべての会話/conversations/conversation-{id}
でID=id
の会話
それを解決した方法。ただしちょっと冗長ではあります。
深い階層
次に、それぞれのconversationがtodo list(やることリスト)というリソースを複数持っているとします。
/conversations/{cid}/todo-lists/{tid}
/conversations/{cid}/todo-lists
でID=cid
の会話が持つすべてのやることリスト/conversations/{cid}/todo-lists/{tid}
でID=cid
の会話が持つID=tid
のやることリスト
Rails方式。前節と同じ問題は引き継ぎます。
また、 /conversations/{cid}/todo-lists
(やることリストの全体)は実際には必要なく、 /conversations/{cid}
があればそれで十分なことがあります((日付をURLに入れるとき、わざわざ /years/2012/months/01/days/03
とする必要がないのにも似ています))。
/conversations/{cid}/{tid}
/conversations/{cid}/{tid}
でID=cid
の会話が持つID=tid
のやることリスト
tid
が何を指しているのかがよくわかりません。日付など明らかにわかるような場合なら短くていい方式でしょう。
/conversations/conversation-{cid}/todo-list-{tid}
/conversations/conversation-{cid}/todo-lists-{tid}
でID=cid
の会話が持つID=tid
のやることリスト
前節の最後の方法を採用しつつ、todo listの全体はいらないのだから、そのパス階層だけなくした方式。この方式だと、全体のリソースと個別のリソースのどれを提供しているかが明確になります。
私見
Rails方式でいいじゃん(笑)
と言ってしまうと元も子もないのですが、こういうような議論を経て、今のRailsのリソースパターン(Memberリソース、Collectionリソースなど)が定まってきたのではないか、と想像できます。
Rails方式における /conversations/new
の問題点については、実は過去には /conversations;new
となっていた時期がありました。これなら問題は起きないのですが、セミコロンが不自然であまり受け入れられなかったのか、すぐにスラッシュに変わりました。
個人的な考えでは、こういう補助的なリソースは“_
”で始めることとして、 /conversations/_new
とすればいいのではと思っています*1。ただしRailsの規約で“_
”はpartial viewを指すので、ちょっと相性が悪いかもしれません。
もちろん、Railsを使うときもこれらの方式のどれを実際に採用するかは自由です。routes.rbの書き方次第で、どのような方式にすることもできます。ただ、Railsのパターンに従ってresources
で書くのが楽ですよ。