class Blockenspiel::Builder
Dynamically construct a target¶ ↑
These methods are available in a block passed to Blockenspiel#invoke and can be used to dynamically define what methods are available from a block. See Blockenspiel#invoke for more information.
Public Instance Methods
Declare a DSL method.¶ ↑
This call creates a method that can be called from the DSL block. Provide a name for the method, a block defining the method's implementation, and an optional hash of options.
By default, a method of the same name is also made available to
parameterless blocks. To change the name of the parameterless method,
provide its name as the value of the :dsl_method
option. To
disable this method for parameterless blocks, set the
:dsl_method
option to false
.
The :mixin
option is a deprecated alias for
:dsl_method
.
Warning about the return
keyword¶ ↑
Because you are implementing your method using a block, remember the
distinction between Proc.new
and lambda
. Invoking
return
from the former does not return from the block, but
returns from the surrounding method scope. Since normal blocks passed to
methods are of the former type, be very careful about using the
return
keyword:
add_method(:foo) do |param| puts "foo called with parameter "+param.inspect return "a return value" # DOESN'T WORK LIKE YOU EXPECT! end
To return a value from the method you are creating, set the evaluation value at the end of the block:
add_method(:foo) do |param| puts "foo called with parameter "+param.inspect "a return value" # Returns from method foo end
If you must use the return
keyword, create your block as a
lambda as in this example:
code = lambda do |param| puts "foo called with parameter "+param.inspect return "a return value" # Returns from method foo end add_method(:foo, &code)
Accepting a block argument¶ ↑
If you want your method to take a block, you have several options depending
on your Ruby version. If you are running the standard Matz Ruby interpreter
(MRI) version 1.8.7 or later (including 1.9.x), or a compatible interpreter
such as JRuby 1.5 or later, you can use the standard “&” block argument
notation to receive the block. Note that you must call the passed block
using the call
method since Ruby doesn't support invoking
such a block with yield
. For example, to create a method named
“foo” that takes one parameter and a block, do this:
add_method(:foo) do |param, &block| puts "foo called with parameter "+param.inspect puts "the block returned "+block.call.inspect end
In your DSL, you can then call:
foo("hello"){ "a value" }
If you are using MRI 1.8.6, or another Ruby interpreter that doesn't
fully support this syntax (such as JRuby versions older than 1.5), Blockenspiel provides an alternative in the
form of the :block
option. This option causes blocks provided
by the caller to be included in the normal parameter list to your method,
instead of as a block parameter. It can be set to :first
or
:last
to prepend or append, respectively, the block (as a
Proc
object) to the parameter list. If the caller does not
include a block when calling your DSL method, nil is
prepended/appended. For example:
add_method(:foo, :block => :last) do |param, block| puts "foo called with parameter "+param.inspect if block puts "the block returned "+block.call.inspect else puts "no block passed" end end
The :receive_block
option is a deprecated alternative. Setting
:receive_block => true
is currently equivalent to setting
:block => :last
.
# File lib/blockenspiel/builder.rb, line 187 def add_method(name_, opts_={}, &block_) receive_block_ = opts_[:receive_block] ? :last : opts_[:block] receive_block_ = :first if receive_block_ && receive_block_ != :last @target_class._add_methodinfo(name_, block_, receive_block_) dsl_method_name_ = opts_[:dsl_method] || opts_[:mixin] if dsl_method_name_ != false dsl_method_name_ = name_ if dsl_method_name_.nil? || dsl_method_name_ == true @target_class.dsl_method(dsl_method_name_, name_) end end