Currently when I need to share a method like processParams(params)
between different controllers, I use either inheritance or services.
Both solution has some
You can write all the common method in commonService and use that service to envoke commmon method
You can use the Delegation design pattern:
class Swimmer {
def swim() { "swimming" }
}
class Runner {
def run() { "running" }
}
class Biker {
def bike() { "biking" }
}
class Triathlete {
@Delegate Swimmer swimmer
@Delegate Runner runner
@Delegate Biker biker
}
def triathlete = new Triathlete(
swimmer: new Swimmer(),
runner: new Runner(),
biker: new Biker()
)
triathlete.swim()
triathlete.run()
triathlete.bike()
In case of a controller, assign the helper class directly at the instance field (or in the nullary constructor):
class HelperClass {
def renderFoo() { render 'foo' }
}
class FooController {
private @Delegate HelperClass helperClass = new HelperClass()
def index = { this.renderFoo() }
}
The delegate's type information gets compiled into the containing class.
Common functionality is a call for a new class, not necessarily common ancestor. The question formulation is missing responsibility statement for it. Needless to say, it's a single responsibility that we create a new class for. I take further decisions basing on class responsibility.
I prefer a hybrid of robbbert's and Jared's answers: I construct extra classes, passing them necessary controller internals as parameters. Sometimes the classes develop from method objects. Like:
def action = {
def doer = SomeResponsibilityDoer(this.request, this.response)
render doer.action()
}
Not so brief, but lets you get code under tests and keep coupling low.
As SomeResponsibilityDoer
is only going to have couple of fields - request an response - it's not a big deal constructing it with every request.
It's also not a big deal having SomeResponsibilityDoer
not reloaded on controller change in dev, because:
src/groovy
.This doesn't help the restarting in development mode issue you have, but it's the way I've solved this problem. It's ugly and probably not good practice, but I factor common code into classes as closures. Then I can do something like:
new ControllerClosures().action(this)
and from with in the controllerClosures class
def action={
it.response.something
return [allYourData]
}
One option I like is to write the common methods as a category, then mix it into the controllers as necessary. It gives a lot more flexibility than inheritance, has access to stuff like params, and the code is simple and understandable.
Here's a tiny example:
@Category(Object)
class MyControllerCategory {
def printParams() {
println params
}
}
@Mixin(MyControllerCategory)
class SomethingController {
def create = {
printParams()
...
}
def save = {
printParams()
}
}