概要
例えばHoge
というドメインがある場合、普通であればHogeController
というコントローラを用意して、それをHogeドメインのscaffolding用コントローラにします。
ところが、ドメイン名とscaffold用のコントローラ名を別のものにしたい!という要望がよく出てきます(自分の場合)
そういう場合、別名のコントローラのプロパティに、このコントローラはHogeドメイン
のscaffoldようだよという宣言をしてあげることで対応できます。
例えばTestController
というコントローラでHoge
ドメインを扱いたい場合は以下のようにします。
class TestController {
static scaffold = Hoge
}
コレだけでOK!!
/test/にアクセスすれば、ちゃんとHogeドメインの一覧が表示されます。
問題点
じつはこの状態だと、データの閲覧はできますが新規登録、更新、削除ができません。
というのも、フォームの送信先のコントローラ名が、ドメイン名になってしまうためです。
解決方法
コレを回避するために、テンプレートを修正します。
テンプレートのインストール
まずは以下のコマンドを実行してテンプレートを編集できるようにします。
grails install-templates
create.gspの修正
formタグの修正
src/templates/scaffolding/create.gsp
のformタグを以下のように編集します。
修正前
<g:form url="[resource:${propertyName}, action:'save']" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
修正後
<g:form url="[action:'save']" method="POST" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
edit.gspの修正
フォームタグの修正
src/templates/scaffolding/edit.gsp
のformタグを以下のように修正します。
修正前
<g:form url="[resource:${propertyName}, action:'update']" method="PUT" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
修正後
<g:form url="[action:'update']" method="PUT" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
hiddenフィールドの追加
さらにhiddenFieldをg:actionSubmitタグの上に追記します。
<!--g:hiddenFieldを追記-->
<g:hiddenField name="id" value="\${${propertyName}?.id}" />
<g:actionSubmit class="save" action="update" value="\${message(code: 'default.button.update.label', default: 'Update')}" />
show.gspの修正
次に、src/templates/scaffolding/show.gsp
のフォームタグの部分を以下のように修正します。
修正前
<g:form url="[resource:${propertyName}, action:'delete']" method="DELETE">
<fieldset class="buttons">
<g:link class="edit" action="edit" resource="\${${propertyName}}">
<g:message code="default.button.edit.label" default="Edit" />
</g:link>
<g:actionSubmit class="delete" action="delete" value="\${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('\${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
</fieldset>
</g:form>
修正後
<g:form url="[action:'delete']" method="DELETE">
<fieldset class="buttons">
<g:link class="edit" action="edit" params="[id:${propertyName}.id]">
<g:message code="default.button.edit.label" default="Edit" />
</g:link>
<g:hiddenField name="id" value="\${${propertyName}?.id}" />
<g:actionSubmit class="delete" action="delete" value="\${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('\${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
</fieldset>
</g:form>
resource="\${${propertyName}}を削除します。
さらに、linkタグのパラメータの修正と、edit.gsp同様にhiddenFieldを追記しています。
コレでひとまず動作します。
Controller.groovyの修正
処理自体はテンプレート通りで特に問題ありませんが、データベースを更新したあとのリダイレクトの宛先のコントローラ名が、ドメイン名になってしまっているので、その部分を修正します。
該当ファイルは、テンプレートである/src/templates/scaffolding/Controller.groovy
です。
saveメソッドとupdateメソッド両方で同じように修正する必要があります。
修正前
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: '${className}.label', default: '${className}'), ${propertyName}.id])
redirect ${propertyName}
}
'*'{ respond ${propertyName}, [status: OK] }
}
修正後
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id])
redirect action: 'show', id:${propertyName}.id
}
'*' { respond ${propertyName}, [status: CREATED] }
}
redirectの部分を修正しています。
コレで、モデルの更新後のリダイレクトが正常に動作するようになります。
まとめ
やることといえば、基本的にはテンプレートをちょこっと修正するだけです。
テンプレートを元に戻したい場合はVCSから戻すのもいいし、サイトinstall-templateを実行してもOKです。
また、やっぱりドメイン名と同名のコントローラでscaffoldしたい!となった場合、今回の修正をしていても問題なくscaffoldは動作します。