参考
http://d.hatena.ne.jp/mottsnite/20140521/1400684993
http://grails.org/doc/latest/guide/single.html#namespacedControllers
概要
以前にも一度namespaceに関して投稿しました。
今回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
コントローラの編集
上記で作成したコントローラを以下のように編集する。
package backend
class HelloController {
// namespaceの指定
static namespace = 'backend'
def index() {
[msg:"BACKEND!"]
}
}
package frontend
class HelloController {
// namespaceの指定
static namespace = 'frontend'
def index() {
[msg:"FRONTEND!"]
}
}
package namespace_sample
class HelloController {
/*
* namespaceの指定はなし
*/
def index() {
[msg:"DEFAULT!"]
}
}
データ表示用のViewの生成
namespaceが指定されているコントローラは、デフォルトで grails-app/views/<NAMESPACE名>/<CONTROLLER名>/
ディレクトリを優先的に利用するようになります。
該当するgspファイルやディレクトリがなかった場合、旧来通りgrails-app/views/<NAMESPACE名>/<CONTROLLER名>/
ディレクトリが利用されます。
とりあえず共通で利用される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を以下のように編集します。
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
を以下のようにしてみます。
<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は上手く動かない
前回の投稿同様に、g:form
では namespaceの指定が有効になりません。
回避方法としてはやはり引き続きmappingを利用するしかなさそうです。