Class: Blockenspiel::Builder
- Inherits:
-
Object
- Object
- Blockenspiel::Builder
- Includes:
- DSL
- Defined in:
- lib/blockenspiel/builder.rb
Overview
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.
Defined Under Namespace
Classes: Target
Instance Method Summary collapse
-
#_create_target ⇒ Object
Creates a new instance of the dynamic target class.
-
#add_method(name_, opts_ = {}, &block_) ⇒ Object
Declare a DSL method.
-
#initialize ⇒ Builder
constructor
Sets up the dynamic target class.
Methods included from DSL
Constructor Details
#initialize ⇒ Builder
Sets up the dynamic target class.
85 86 87 88 |
# File 'lib/blockenspiel/builder.rb', line 85 def initialize # :nodoc: @target_class = ::Class.new(::Blockenspiel::Builder::Target) @target_class.dsl_methods(false) end |
Instance Method Details
#_create_target ⇒ Object
Creates a new instance of the dynamic target class
93 94 95 |
# File 'lib/blockenspiel/builder.rb', line 93 def _create_target # :nodoc: @target_class.new end |
#add_method(name_, opts_ = {}, &block_) ⇒ Object
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.
187 188 189 190 191 192 193 194 195 196 |
# 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 |