Module: Musa::Extension::With
- Included in:
- Darwin::Darwin::MainContext, Darwin::Darwin::MeasuresEvalContext, MusicXML::Builder::Internal::Attributes, MusicXML::Builder::Internal::Direction, MusicXML::Builder::Internal::Measure, MusicXML::Builder::Internal::Part, MusicXML::Builder::ScorePartwise, Rules::Rules, Sequencer::Sequencer::DSLContext
- Defined in:
- lib/musa-dsl/core-ext/with.rb
Overview
Module providing the with method for flexible DSL block execution.
The with method is a cornerstone of Musa DSL's builder pattern, allowing
objects to execute blocks in either the object's context (for DSL-style
configuration) or the caller's context (for traditional Ruby blocks).
Context Switching Logic
The method intelligently determines which context to use based on:
- The
keep_block_contextparameter (explicit control) - Block parameters (implicit control via
_parameter) - Whether parameters are passed to the block
Modes of Operation
DSL mode (
instance_eval): Block executes in object's context- Used when: no parameters, no
keep_block_context, no_parameter - Enables: direct access to object's instance variables and methods
- Used when: no parameters, no
Caller context mode (
callwith self as_): Block keeps its context- Used when: block has
_parameter, orkeep_block_context: true - Enables: access to both contexts (object via
_, caller's scope naturally)
- Used when: block has
Hybrid mode (
instance_exec): Block in object context with parameters- Used when: parameters provided but
keep_block_contextnot set - Enables: DSL-style access plus explicit parameters
- Used when: parameters provided but
Use Cases
- Builder pattern DSL methods
- Configuration blocks that need object context
- Flexible API supporting both DSL and traditional Ruby styles
- Initializers that configure objects via blocks
Instance Method Summary collapse
-
#with(*value_parameters, keep_block_context: nil, **key_parameters, &block) ⇒ Object
Executes a block with flexible context and parameter handling.
Instance Method Details
#with(*value_parameters, keep_block_context: nil, **key_parameters, &block) ⇒ Object
The _ parameter is special: when present, it signals "keep caller's context"
and receives self (the object) as its value.
Uses SmartProcBinder internally to handle parameter matching.
Executes a block with flexible context and parameter handling.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/musa-dsl/core-ext/with.rb', line 107 def with(*value_parameters, keep_block_context: nil, **key_parameters, &block) # Wrap block in SmartProcBinder for parameter introspection and management smart_block = Musa::Extension::SmartProcBinder::SmartProcBinder.new(block) # Check if first parameter is _ (underscore), which signals "keep caller's context" send_self_as_underscore_parameter = smart_block.parameters[0][1] == :_ unless smart_block.parameters.empty? # Determine effective context mode: # 1. Use explicit keep_block_context if provided # 2. Otherwise, use _ parameter presence as signal # 3. Default to false (use object's context) effective_keep_block_context = keep_block_context effective_keep_block_context = send_self_as_underscore_parameter if effective_keep_block_context.nil? effective_keep_block_context = false if effective_keep_block_context.nil? # Match provided parameters to block's expected parameters effective_value_parameters, effective_key_parameters = smart_block._apply(value_parameters, key_parameters) # Execute block in appropriate context if effective_keep_block_context # Keep caller's context: call block normally if send_self_as_underscore_parameter # Pass self as first parameter (the _ parameter) smart_block.call(self, *effective_value_parameters, **effective_key_parameters) else # Just pass the effective parameters smart_block.call(*effective_value_parameters, **effective_key_parameters) end elsif effective_value_parameters.empty? && effective_key_parameters.empty? # DSL mode: no parameters, execute in object's context instance_eval &block else # Hybrid mode: execute in object's context with parameters instance_exec *effective_value_parameters, **effective_key_parameters, &block end end |