# RestResponder のビュー選択ロジック
- Controller クラスで respond メソッドを打った時の挙動についてわかったことをダラダラ書いておく

## 前提
- Grails で rest profile でアプリを作成しているとき
- Grails は 3.2.4 のときの挙動

## RestResponder って…?
- rest profile で起動すると、Controller クラスに勝手に implements されるクラス(trait)
    - http://docs.graorg/latest/guide/traits.html
    - trait は Groovy 独自の機能なのでググってください
    - respond メソッドも Grails さんが勝手に Controller クラスに加えてくれるため使える

## respond メソッドが打たれた時の大まかな流れ
### ソース
- https://github.com/grails/grails-core/blob/master/grails-plugin-rest/src/main/groovy/grails/artefact/controller/RestResponder.groovy
- https://github.com/grails/grails-core/blob/master/grails-plugin-rest/src/main/groovy/org/grails/plugins/web/rest/render/DefaultRendererRegistry.groovy
- https://github.com/grails/grails-views/blob/master/core/src/main/groovy/grails/views/mvc/renderer/DefaultViewRenderer.groovy
- よく見るとモジュールを跨いでいる…

### 流れ
1. `RestResponder#render()`
    - 単なる delegate メソッド
1. `RestResponder#internalRespond()`
    1. リクエストの MIME タイプから適切なレスポンス MIME タイプを入れる
    1. `RendererRegistry` から MIME タイプ、respond メソッドに指定されたオブジェクトクラス、オブジェクトから適切な `Renderer` を引っ張ってくる
        - `RendererRegistry` は特に指定してなければ、 `org.grails.plugins.web.rest.render.DefaultRendererRegistry` クラスのインスタンスが作られる
        - `Renderer` も特に設定しなければ `grails.plugin.json.renderer.JsonViewJsonRenderer` クラスのインスタンスが返ってくる
            - 実装はほとんど `grails.views.mvc.renderer.DefaultViewRenderer`
        - 実は `org.springframework.validation.Errors` クラスのインスタンスが引数に指定されたときは処理ロジックが違ったり…
1. `DefaultViewRenderer#render()`
    - こいつが本命
    - Controller クラスで指定されたオプションの解釈、テンプレートの解決、描画まですべて受け持っている

### テンプレートの解決方法
1. `ビュー名` の解決
    1. `respond` メソッド呼び出し時に渡した `view` オプション
    1. なければ、アクション名
1. `ビュー URI` の解決
    1. ビュー名が `/` から始まっている場合はそのまま使う
    1. それ以外の場合は `/${コントローラ名}/${ビュー名}` を設定する
1. namespace が指定されている場合はさらに頭に `/${namespace}` を追加する
1. ここまでで一度テンプレートファイルがあるかどうか探してみる
1. 見つからなければ、 `respond` メソッド呼び出し時に渡したオブジェクトのクラスから適切なテンプレートを探す
    - ここでも見つからなければ `object/_object.gson` に落ちる

# RestResponder にまつわるTips
## `respond` に渡したインスタンスに対応するテンプレートで描画されない！
- `respond` に渡しているインスタンスは、あるモデルクラスの関連クラスのインスタンスを渡していませんか？
    - 渡している場合は、そのインスタンスのクラス名を要チェキ
    - 以下のようになっている場合は、そのまま渡してもテンプレート解決できない
```
class jp.co.hoge.domain.user.Worker_$$_jvst806_3
                               なんかくっついてる   ^^^^^^^^^^^^^
```
- 以下のようにビュー名を直接指定して、テンプレートを見つけさせる
```
respond([mission: mission], view: '/mission/_mission')
```
    - 渡すモデル、ビュー名は全部しっかり指定する
    - インスタンスのクラス名に余分なものがついているので、Grails によるモデルの補完、ビュー名の解決はうまく動かない


---

## Page Navigation

- Canonical URL: https://tips.weseek.co.jp/Tips/Grails/RestResponder%20について
- Permalink: https://tips.weseek.co.jp/5fb74d07a1ba4200489a4b93
- Parent: [Grails](/65069da24603e7ff39a6b3f0.md)
- Children: 0 total
- Total descendants: 0
- Siblings: 2 total
  - [GORM for Mongo](/5fb74c91a1ba4200489a4b84.md)
  - [Spock](/5fb74c7aa1ba4200489a4b79.md)
- Last updated: 2020-11-20T04:58:47.855Z by takuya
- Full page listing (all children regardless of count): https://tips.weseek.co.jp/_api/v3/page-listing/children?id=5fb74d07a1ba4200489a4b93
