module Blockenspiel::DSLSetupMethods
DSL setup methods¶ ↑
These class methods are available after you have included the Blockenspiel::DSL module.
By default, a class that has DSL capability will
automatically make all public methods available to parameterless blocks,
except for the initialize
method, any methods whose names
begin with an underscore, and any methods whose names end with an equals
sign.
If you want to change this behavior, use the directives defined here to control exactly which methods are available to parameterless blocks.
Public Instance Methods
A DSL-friendly attr_accessor.
This creates the usual “name” and “name=” methods in the current class that can be used in the usual way. However, its implementation of the “name” method (the getter) also takes an optional parameter that causes it to behave as a setter. This is done because the usual setter syntax cannot be used in a parameterless block, since it is syntactically indistinguishable from a local variable assignment. The “name” method is exposed as a dsl_method.
For example:
dsl_attr_accessor :foo
enables the following:
my_block do |param| param.foo = 1 # Usual setter syntax works param.foo 2 # Alternate setter syntax also works puts param.foo # Usual getter syntax still works end my_block do # foo = 1 # Usual setter syntax does NOT work since it # looks like a local variable assignment foo 2 # Alternate setter syntax does work puts foo # Usual getter syntax still works end
# File lib/blockenspiel/dsl_setup.rb, line 263 def dsl_attr_accessor(*names_) names_.each do |name_| unless name_.kind_of?(::String) || name_.kind_of?(::Symbol) raise ::TypeError, "#{name_.inspect} is not a symbol" end unless name_.to_s =~ /^[_a-zA-Z]\w+$/ raise ::NameError, "invalid attribute name #{name_.inspect}" end module_eval("def #{name_}(value_=::Blockenspiel::NO_VALUE); ::Blockenspiel::NO_VALUE.equal?(value_) ? @#{name_} : @#{name_} = value_; end\n") alias_method("#{name_}=", name_) dsl_method(name_) end end
A DSL-friendly attr_writer.
This creates the usual “name=” method in the current class that can be used in the usual way. However, it also creates the method “name”, which also functions as a setter (but not a getter). This is done because the usual setter syntax cannot be used in a parameterless block, since it is syntactically indistinguishable from a local variable assignment. The “name” method is exposed as a dsl_method.
For example:
dsl_attr_writer :foo
is functionally equivalent to:
attr_writer :foo alias_method :foo, :foo= dsl_method :foo
which enables the following:
my_block do |param| param.foo = 1 # Usual setter syntax works param.foo 2 # Alternate setter syntax also works end my_block do # foo = 1 # Usual setter syntax does NOT work since it # looks like a local variable assignment foo(2) # Alternate setter syntax does work end
# File lib/blockenspiel/dsl_setup.rb, line 309 def dsl_attr_writer(*names_) names_.each do |name_| attr_writer(name_) alias_method(name_, "#{name_}=") dsl_method(name_) end end
Make a particular method available to parameterless DSL blocks.
To explicitly make a method available to parameterless blocks:
dsl_method :my_method
To explicitly exclude a method from parameterless blocks:
dsl_method :my_method, false
To explicitly make a method available to parameterless blocks, but point it to a method of a different name on the target class:
dsl_method :my_method, :target_class_method
# File lib/blockenspiel/dsl_setup.rb, line 175 def dsl_method(name_, delegate_=nil) name_ = name_.to_sym if delegate_ delegate_ = delegate_.to_sym elsif delegate_.nil? delegate_ = name_ end @_blockenspiel_methods[name_] = delegate_ unless @_blockenspiel_module.public_method_defined?(name_) @_blockenspiel_module.module_eval("def #{name_}(*params_, &block_); val_ = ::Blockenspiel._target_dispatch(self, :#{name_}, params_, block_); ::Blockenspiel::NO_VALUE.equal?(val_) ? super(*params_, &block_) : val_; end\n") end end
Control the behavior of methods with respect to parameterless blocks, or make a list of methods available to parameterless blocks in bulk.
To enable automatic exporting of methods to parameterless blocks. After
executing this command, all public methods defined in the class will be
available on parameterless blocks, until dsl_methods false
is
called:
dsl_methods true
To disable automatic exporting of methods to parameterless blocks. After
executing this command, methods defined in this class will be excluded from
parameterless blocks, until dsl_methods true
is called:
dsl_methods false
To make a list of methods available to parameterless blocks in bulk:
dsl_methods :my_method1, :my_method2, ...
You can also point dsl methods to a method of a different name on the target class, by using a hash syntax, as follows:
dsl_methods :my_method1 => :target_class_method1, :my_method2 => :target_class_method2
You can mix non-renamed and renamed method declarations as long as the renamed (hash) methods are at the end. e.g.:
dsl_methods :my_method1, :my_method2 => :target_class_method2
# File lib/blockenspiel/dsl_setup.rb, line 216 def dsl_methods(*names_) if names_.size == 0 || names_ == [true] @_blockenspiel_active = true elsif names_ == [false] @_blockenspiel_active = false else if names_.last.kind_of?(::Hash) names_.pop.each do |name_, delegate_| dsl_method(name_, delegate_) end end names_.each do |name_| dsl_method(name_, name_) end end end