[Grails]namespaceの使い方

#参考
[http://d.hatena.ne.jp/mottsnite/20140521/1400684993](http://d.hatena.ne.jp/mottsnite/20140521/1400684993)
[http://grails.org/doc/latest/guide/single.html#namespacedControllers](http://grails.org/doc/latest/guide/single.html#namespacedControllers)

#概要
[以前にも一度namespaceに関して投稿しました。](http://qiita.com/saba1024/items/7694ff2b6597ba2c4526)
今回Grails2.4で再度チャレンジしてリンクの生成が上手く行ったので再投稿です。

#メリット
namespaceを用いることで、同名のコントローラ名（ファイル名）が利用できるようになります。

# テストプロジェクトの作成
プロジェクト名は **namespace_sample** とする。
`grails create-app namespace_sample`を実行した後、その場で`grails`コマンドを実行してインタラクティブモードに入っておく。

#コントローラの作成
インタラクティブモードで以下のコマンドを実行する。

```
#まずフロントエンド用
grails> create-controller frontend.hello
| Created file grails-app/controllers/frontend/HelloController.groovy
| Created file grails-app/views/hello
| Created file test/unit/frontend/HelloControllerSpec.groovy
grails> 

#続いてバックエンド用
grails> create-controller backend.hello
| Created file grails-app/controllers/backend/HelloController.groovy
| Created file grails-app/views/hello
| Created file test/unit/backend/HelloControllerSpec.groovy

# 最後にデフォルトパッケージのコントローラも作っておいてみる。
grails> create-controller hello
| Created file grails-app/controllers/namespace_sample/HelloController.groovy
| Created file grails-app/views/hello
| Created file test/unit/namespace_sample/HelloControllerSpec.groovy

```

#コントローラの編集
上記で作成したコントローラを以下のように編集する。

```groovy:namespace_sample/grails-app/controllers/backend/HelloController.groovy
package backend

class HelloController {

    // namespaceの指定
    static namespace = 'backend'

    def index() {
        [msg:"BACKEND!"]
    }
}
```

```groovy:namespace_sample/grails-app/controllers/frontend/HelloController.groovy
package frontend

class HelloController {

    // namespaceの指定
    static namespace = 'frontend'

    def index() {
        [msg:"FRONTEND!"]
    }
}
```

```groovy:namespace_sample/grails-app/controllers/namespace_sample/HelloController.groovy
package namespace_sample

class HelloController {

    /*
     * namespaceの指定はなし
     */

    def index() {
        [msg:"DEFAULT!"]
    }
}
```

#データ表示用のViewの生成
namespaceが指定されているコントローラは、デフォルトで　`grails-app/views/<NAMESPACE名>/<CONTROLLER名>/`ディレクトリを優先的に利用するようになります。
該当するgspファイルやディレクトリがなかった場合、旧来通り`grails-app/views/<NAMESPACE名>/<CONTROLLER名>/`ディレクトリが利用されます。

とりあえず共通で利用されるgspファイルを作成してみます。

```html:namespace_sample/grails-app/views/hello/index.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
  <title></title>
</head>
<body>
This page is<h1>"${msg}"</h1>
</body>
</html>
```

#URLの設定
UrlMappings.groovyを以下のように編集します。

```groovy:namespace_sample/grails-app/conf/UrlMappings.groovy
class UrlMappings {

	static mappings = {
        /********** ここから追加 **********/
        "/frontend/$controller/$action?/$id?(.${format})?"(namespace: 'frontend')
        "/backend/$controller/$action?/$id?(.${format})?"(namespace: 'backend')
/*
ここのコメントアウトされた書き方だとNG（g:linkタグなどが正しく動作しない）
        '/frontend' {
            namespace = 'frontend'
        }

        '/backend' {
            namespace = 'backend'
        }

        "/$namespace/$controller/$action?"()
*/
        /********** ここまで追加　**********/

        "/$controller/$action?/$id?(.$format)?"{
            constraints {
                // apply constraints here
            }
        }

        "/"(view:"/index")
        "500"(view:'/error')
	}
}
```

#確認してみる
インタラクティブモードで`run-app`を実行してGrailsを起動します。
その後、以下のURLにそれぞれアクセスすれば、ちゃんとnamespaceが有効になっていて異なるページが表示されます。

http://localhost:8080/namespace_sample/backend/hello/index
http://localhost:8080/namespace_sample/frontend/hello/index
http://localhost:8080/namespace_sample/hello/index

# Viewも分けてみる
とても簡単。
単純に以下のディレクトリとファイルを作るだけ。

* namespace_sample/grails-app/views/backend/hello/index.gsp
* namespace_sample/grails-app/views/frontend/hello/index.gsp

こうすることで、namespaceが指定されたコントローラは自動的に自分のnamespaceのディレクトリは以下を優先的に利用するようになります。

#GSPタグでのリンクの生成
単純にnamespace属性を追加するだけです。
サンプルとして、`namespace_sample/grails-app/views/hello/index.gsp`を以下のようにしてみます。

```html:namespace_sample/grails-app/views/hello/index.gsp
<g:link namespace="backend" controller="hello" action="index">To Backend</g:link><br />
<g:link namespace="frontend" controller="hello" action="index" >To Frontend</g:link><br />
<g:link controller="hello" action="index">To Default</g:link><br />
```

これでちゃんと動くはず。

#それでもやっぱりg:formは上手く動かない
[前回の投稿](http://qiita.com/saba1024/items/7694ff2b6597ba2c4526)同様に、`g:form`では **namespaceの指定が有効になりません。**
回避方法としてはやはり引き続きmappingを利用するしかなさそうです。