Override a template method in scaffolded controllers
-
06-07-2021 - |
سؤال
I have a Grails project where I use heavily customized scaffolding templates to add a beforeUpdate
template method to update
so that I can easily customize scaffolded Controller
's without having to generate and then edit each controller separately.
Unfortunately this doesn't work and only beforeUpdate
from scaffolding gets called.
I suspect it has to do with the code generation used by Groovy to inject the scaffolding code into the actual Controller
, but I can't find any confirmation.
What I'm asking is either a solution to the problem or an explanation for why it doesn't work.
Here is the scaffolding code:
def beforeUpdate = {
println "beforeUpdate from scaffold"
}
def update() {
// call before update hook
beforeUpdate()
def ${propertyName} = ${className}.get(params.id)
if (!${propertyName}) {
flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])
redirect(action: "list")
return
}
[...]
and the scaffolded controller code (which is not called, while I believe it should):
class CalendarController {
static scaffold = Calendar
def beforeUpdate = {
println "beforeUpdate from controller"
}
}
I have already tried grails clean ;-)
UPDATE
I have eventually realized that this is simply impossibile due to how the Grails scaffolding is designed. Closing.
المحلول 2
I have eventually realized that this is simply impossibile due to how the Grails scaffolding is designed: by dynamically copying/creating methods into the scaffolded controllers and not using inheritance.
نصائح أخرى
You have a similar problem to this question - essentially the way scaffolding works the scaffolding template generates a separate class which the "real" controller delegates to. So if you want the generated controller to call methods on the real controller you can't use this
, you need to get a reference to the real controller object.
To cut a long story short, use
GrailsWebUtil.getControllerFromRequest(request).beforeUpdate()
instead of just
beforeUpdate()
def update() {
// call before update hook
def realController = GrailsWebUtil.getControllerFromRequest(request)
if(realController.hasProperty('beforeUpdate') &&
realController.beforeUpdate instanceof Closure) {
realController.beforeUpdate()
} else {
this.beforeUpdate()
}
def ${propertyName} = ${className}.get(params.id)
if (!${propertyName}) {
flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])
redirect(action: "list")
return
}
[...]