Edited at
RubyDay 4

Railsアプリケーションでより良いリソース設計を実装するためのテクニック

More than 1 year has passed since last update.


shallowを使って無意味なネストをなくす

ルーティングを書くときは、意味のないネストが生まれないように気をつける。

例えば、各モデルのprimary keyidで、ユーザーid: 100の記事id: 200を次のようなルーティングで示しているとする。

resources :users do

resources :articles
end

METHOD
PATH

ユーザーが投稿した記事の一覧
GET
/users/100/articles

記事の詳細
GET
/users/100/articles/200

記事の編集
GET
/users/100/articles/200/edit

というルーティングになる。この時、1件の記事を対象とするリソースに、ユーザー情報は対象のリソースとは関係ないのでリソースに含まれるべきではない。(また、権限の情報はリソースそのものの情報とは関係ない。)

ルーティングはあくまでどのリソースを対象にしているかを考えるべきである。

shallowオプションを使えば、このユーザーによる無駄なルーティングのネストをさけて、あるべきルーティングを作ることができる。

resources :users, shallow: true do

resources :articles
end

METHOD
PATH

ユーザーが投稿した記事の一覧
GET
/users/100/articles

記事の詳細
GET
/articles/200

記事の編集
GET
/articles/200/edit


動詞を含まない

パスの中に、動詞を含めるべきではない。

リソースの操作は、取得・作成・削除・更新で表現でき、これらは全てHTTP Request methodで表現ですべきです。

リソースの操作の安全性や冪等性によって、どのRequest methodを使うか選択します。

METHOD

GET / HEAD
 リソースの取得

POST
 リソースの破壊的変更、冪等でない

PUT / PATCH
リソースの更新、冪等である

DELETE
リソースの削除、冪等である


リソースの操作を index show create update destroyで表現できないか考える

多くのリソースの操作は index show create update destroy で表現できる。

できるだけこれらのアクションで表現することによって人間にとって理解しやすいルーティングを実現することができる。

(サーバーサイドレンダリングを利用するアプリケーションでは new editも使うとよい。)

「DHH(Railsの作者)はどのようにRailsのコントローラを書くのか」という記事が参考になる。


singular resourceを使う

親リソースに紐づく子リソースが必ず1つしか存在しないhas-one関連のリソースは、singular resourceをりようして表現する。

例えばユーザーが一つのプロフィールを持つという構造を表現する。

resources :users do

resource :profile
end


  • app/


    • controllers/


      • users_controller.rb

      • profiles_controller.rb





PATH

プロフィールの詳細
/users/100/profile

プロフィールの登録
/users/100/profile/new

プロフィールの編集
/users/100/profile/edit


render / redirect_toの使い分け

リクエストの処理の終了後にredirectすべきか、renderingをすべきかを考える。

判断基準の一つとして、その処理が成功・失敗した後の対象のリソースが変化しているかどうかをみる。

リソースの作成処理を行った後に作成したリソースの詳細画面を表示するのであれば、現在のパスでは存在しないリソースの取得をすることになるのでリダイレクトが必要であるし、削除した後に一覧画面に遷移する場合も同様にリダイレクトが必要です。

一方で、詳細画面(show)から同じリソースの更新をして同じリソースの詳細画面をもう一度表示する場合は取得するとなる対象リソースと更新する対象リソースが全く同じなのでリダイレクトする必要はない。


検索 / filter 系はGET QUERYを使う

検索や、簡易的なリソースのフィルタリングはGETクエリを使う。

例: /articles?tag=書評

例: /search?q=日記

また、あるリソースに紐づくリソースの一覧を表示する場合等、has-many関連のリソースを表現する場合はネストしたほうが明確である。

例: /categories/1/articles


params[:id]はなにか

:idはデータベースに登録しているrecordのidを表しているのではない。

リソースを一意に識別する符号であるということを意識する。

そのリソースが、年月日に紐付いて1日に1つのリソースを持つものであれば、テーブル構造に関係なく、idは年月日を示すものになるべきである。

例: /schedules/2016-12-04


書籍