Railsの”shallow（浅い）”ルーティングを理解する

## 何をしたか
Railsの課題を実施しています。DB構造はこんな感じで、`user`に紐づく`post`と、それぞれに紐づく`comments`があります。

[![Image from Gyazo](https://i.gyazo.com/fb34b2e981265c776b35ae7e4a83236d.png)](https://gyazo.com/fb34b2e981265c776b35ae7e4a83236d)

その中で、`post`-`comment`間のルーティングについて`shallow`を使いましょうとの指示があったのですが、実は、`shallow`は悪手だと聞いていたこともあって、自分では使っていませんでした。

とはいえ**「悪手なのでやめましょう」**ではなんの発展もないので、`shallow`がどんなルーティングを生んでいるのか、および

- `shallow`を肯定する人の意見
- そうではない人の意見

も比べて、今後自分の担当するプロジェクトにおいて使う・使わないを検討する材料にしたいと思います。

なお、実行環境は下記の通りです。

- `Rails 5.2.3`
- `Ruby 2.6.0`

## shallowはどんなルーティングを生んでいるか

`shallow`は、ネストしたルーティングにおいて、下層にあるテーブルのIDが一意なら、その上にあるテーブルのIDは不要という発想に基づいています。

具体的には、以下のようにネストしたルーティングを記載すると...

```Ruby:config/routes.rb
resources :posts, shallow: true do
  resources :comments
end
```

以下のような`comments`のルーティングが生成されます。


|ヘルパー|リクエスト|URI|アクション|
|----|----|----|----|
|post_comments|GET|/posts/:post_id/comments|index|
|post_comments|POST|/posts/:post_id/comments|create|
|new_post_comments|GET|/posts/:post_id/comments/new|new|
|edit_comment|GET|/comments/:id/edit|edit|
|comment|GET|/comments/:id|show|
|comment|PATCH|/comments/:id|update|
|comment|DELETE|/comments/:id|destroy|

ちなみに、`shallow`がない時はこんな感じです。

|ヘルパー|リクエスト|URI|アクション|
|----|----|----|----|
|post_comments|GET|/posts/:post_id/comments|index|
|post_comments|POST|/posts/:post_id/comments|create|
|new_post_comments|GET|/posts/:post_id/comments/new|new|
|edit_post_comment|GET|/posts/:post_id/comments/:id/edit|edit|
|post_comment|GET|/posts/:post_id/comments/:id|show|
|post_comment|PATCH|/posts/:post_id/comments/:id|update|
|post_comment|DELETE|/posts/:post_id/comments/:id|destroy|

`edit`、`show`、`update`、`destroy`の４アクションで、URIパターンがスッキリし、ヘルパーメソッドも短くなっていることがわかります。

画像だともう少しスッキリしている感がわかりやすいかなと思ったので、`rails routes`で出力した結果も載せておきます。

▼Shallowあり
[![Image from Gyazo](https://i.gyazo.com/0f3257ba90c8c4e174745ee190062cfa.png)](https://gyazo.com/0f3257ba90c8c4e174745ee190062cfa)

▼Shallowなし
[![Image from Gyazo](https://i.gyazo.com/35b54096e4042d8aee6a8ecbe8dfd25d.png)](https://gyazo.com/35b54096e4042d8aee6a8ecbe8dfd25d)

だいぶスッキリしていますね:relaxed:

## shallow肯定派の主張

`shallow（浅い）`ルーティングを肯定する人の主張はまさにここで、

- ルーティングがスッキリする
- URLがカッコ悪くない
- ヘルパーもスッキリしてコードの見通しが良くなる

ということだと思います。

Qiitaでよく閲覧されている記事には、この辺がありそうです。

[resources を nest するときは shallow を使うと幸せになれる](https://qiita.com/kuboon/items/96bbd227f9497ed81f38)

では、悪手だという人の主張はどこにあるのでしょうか。

## shallow否定派の主張

### 1) RESTfulでない
私がよく聞く理由の一つがまずこれで、例えば、

- newとdestroyのリダイレクト先の設定に困った（どのPOSTにリダイレクトすれば良いのだ問題）
- newとeditのフォームでURLの指定が異なる（newには親のIDが含まれるけど、editには含まれない）

などがあります。

### 2) 他の実装者の混乱を招く
これは、弊社だけかなあと思いつつ...。URIパターンが普段よく見るルーティング異なるため、

- ネストしているのかURLからわかりづらくなる
- ヘルパーメソッドの確認がいちいち大変

などで地味にコストがかかっております...:sweat_smile:

### 3) その他の主張

そのほか、私は実際に見たことはないですが

- SQLインジェクションを招きやすい
- 渡すParamsが増える（今回も実はcreateとupdateで渡すparamsを変えなければいけなかった）

などのデメリットもある様です。
主な主張はこちらにまとまっているかなあと思いました。

[Railsのroutesのshallowは安易に使わないで欲しい](https://matsu.teraren.com/blog/2019/01/31/rails-routes-shallow-not-recommend/)

## 考察：今回の実装画面

最後に、今回実装することになっている画面をよく見ると、コメントは非同期通信で画面のすぐ上に投稿する（リダイレクトが発生しない）作りだったり、

[![Image from Gyazo](https://i.gyazo.com/7d0184fbb0b10cac9f1ccc5504e5b81e.jpg)](https://gyazo.com/7d0184fbb0b10cac9f1ccc5504e5b81e)

EditとNewフォームは分かれていたりするので（画面は実装中なので、実装出来次第画像は差し替えます）、上記の`shallow`の欠点は影響しない範囲ではないかと思いました＾＾

## 結論：自分はshallow使うか
いろいろ考えたのですが、自分は積極的にはshallowは使わないかなと思いました。最大の理由は**「チームに混乱を招くから」**で、スムーズに開発を進めるという意味では、shallowは使わない方が幸せになれそうです。

一方で、お客さんに納品するアプリなどで、お客さんから注文があった場合には、使用場面を考慮した上でshallowを使うのもありかなとは思います。

普段のコミュニケーションでリンクをシェアするときなどに、やはりスッキリしたURLの方がかっこいいですものね:innocent:

以上、`shallow`に関する考察と感想でした。