Implementing a Rules DSL
[ 280 ]
By adding an enclosing property to the block and nestedBlock closures, we
ensure that nestedBlock is only allowed within block. Placing nestedBlock
outside of block will trigger the assertion. Running the original script with these
closures in the binding will give the following output:
block encountered
nested block encountered
Using a specification parameter
If we like, we can also use closures that take one or more parameters in addition to
the closure parameter; a common style, when using a structured block.
DSL, as mentioned earlier, is used to add a specification parameter to identify
individual blocks.
The implementation can choose to ignore this parameter, or it can be used as a means
of identifying the individual blocks.
binding.block = { spec, closure ->
def cloned = closure.clone()
cloned.delegate = delegate
this.enclosing = "block"
println "${spec} encountered"
cloned()
}
binding.nestedBlock = { spec, closure ->
assert closure.delegate.enclosing == "block"
def cloned = closure.clone()
cloned.delegate = delegate
this.enclosing = "nestedBlock"
println "${spec} encountered"
cloned()
}
block ("first block") {
nestedBlock ("first nested"){
}
}
block "second block", {
nestedBlock ("second nested"){
}
}
http://www.ebook3000.com