Reputation: 12406
I'd like to store a user configurable GString that would be bound to a domain class but I'm having a problem finding a nice solution to this.
Example (concept/pseudo/non-working)
class Person{
...
String displayFooAs; //<-- contains a java.lang.String like '${name} - ${address}'
}
class Foo{
String name;
String address;
String city;
public String getDisplayAs(def person){
return doStuff(this, person.displayFooAs); //<-- Looking for something simple.
}
}
UPDATE:
After review I've decided that this kind of flexibility would pose a security risk. It would allow users to essentially script out sql injection into 'dispalyFooAs'. Back to the drawing board.
Upvotes: 1
Views: 1113
Reputation: 113
I needed something similar where I would evaluate the GString inside a closure loop so the template references it property values. I took the example above and formalized it into a standardized class for late GString evaluations.
import groovy.text.SimpleTemplateEngine
class EvalGString {
def it
def engine
public EvalGString() {
engine = new SimpleTemplateEngine()
}
String toString(template, props) {
this.it = props
engine.createTemplate(template).make(this.properties).toString()
}
}
def template = 'Name: ${it.name} Id: ${it.id}'
def eval = new EvalGString()
println eval.toString(template, [id:100, name:'John')
println eval.toString(template, [id:200, name:'Nate')
Output:
Name: John Id: 100
Name: Nate Id: 200
Upvotes: 0
Reputation: 171084
Do you mean like:
public String getDisplayAs(def person){
doStuff( this, person?.displayFooAs ?: "$name - $address" )
}
This works in Groovy, but I've never embedded SimpleTemplateEngine into something like this in Grails, so would require extensive testing to make sure it works as expected and doesn't gobble memory.
import groovy.text.SimpleTemplateEngine
class Person {
String displayAs = 'Person $name'
}
class Foo {
String name = 'tim'
String address = 'yates'
String getDisplayAs( Person person ) {
new SimpleTemplateEngine()
.createTemplate( person?.displayAs ?: '$name - $address' )
.make( this.properties )
.toString()
}
}
def foo = new Foo()
assert foo.getDisplayAs( null ) == 'tim - yates'
assert foo.getDisplayAs( new Person() ) == 'Person tim'
Upvotes: 1
Reputation: 3552
You've defined
private static final String DEFAULT_DISPLAY_AS = '${name} - ${address}'
static and final - of course it doesn't work?
Define it's as closure
private def DEFAULT_DISPLAY_AS = {->'${name} - ${address}'}
and call in code
DEFAULT_DISPLAY_AS()
Upvotes: 0