mirror of
https://github.com/ms-ati/docile
synced 2023-03-27 23:21:52 -04:00
Add documentation of #dsl_eval_immutable
This commit is contained in:
parent
abd75d6290
commit
62de806d24
3 changed files with 59 additions and 7 deletions
|
@ -3,7 +3,6 @@ require "docile/fallback_context_proxy"
|
|||
require "docile/chaining_fallback_context_proxy"
|
||||
|
||||
# Docile keeps your Ruby DSLs tame and well-behaved
|
||||
# @see http://ms-ati.github.com/docile/
|
||||
module Docile
|
||||
# Execute a block in the context of an object whose methods represent the
|
||||
# commands in a DSL.
|
||||
|
@ -12,8 +11,9 @@ module Docile
|
|||
#
|
||||
# Use this method to execute an *imperative* DSL, which means that:
|
||||
#
|
||||
# 1. each command mutates the state of the DSL context object
|
||||
# 2. the return values of the commands are ignored
|
||||
# 1. Each command mutates the state of the DSL context object
|
||||
# 2. The return value of each command is ignored
|
||||
# 3. The final return value is the original context object
|
||||
#
|
||||
# @example Use a String as a DSL
|
||||
# Docile.dsl_eval("Hello, world!") do
|
||||
|
@ -42,6 +42,38 @@ module Docile
|
|||
end
|
||||
module_function :dsl_eval
|
||||
|
||||
# Execute a block in the context of an immutable object whose methods,
|
||||
# and the methods of their return values, represent the commands in a DSL.
|
||||
#
|
||||
# @note Use with a *functional* DSL (commands return successor
|
||||
# context objects)
|
||||
#
|
||||
# Use this method to execute a *functional* DSL, which means that:
|
||||
#
|
||||
# 1. The original DSL context object is never mutated
|
||||
# 2. Each command returns the next DSL context object
|
||||
# 3. The final return value is the value returned by the last command
|
||||
#
|
||||
# @example Use a String as a DSL
|
||||
# Docile.dsl_eval_immutable("Hello, world!") do
|
||||
# reverse
|
||||
# upcase
|
||||
# end
|
||||
# #=> "!DLROW ,OLLEH"
|
||||
#
|
||||
# @example Use a Float as a DSL
|
||||
# Docile.dsl_eval_immutable(84.5) do
|
||||
# fdiv(2)
|
||||
# floor
|
||||
# end
|
||||
# #=> 42
|
||||
#
|
||||
# @param dsl [Object] immutable context object whose methods make up the
|
||||
# initial DSL
|
||||
# @param args [Array] arguments to be passed to the block
|
||||
# @yield the block of DSL commands to be executed against the
|
||||
# `dsl` context object and successor return values
|
||||
# @return [Object] the return value of the final command in the block
|
||||
def dsl_eval_immutable(dsl, *args, &block)
|
||||
exec_in_proxy_context(dsl, ChainingFallbackContextProxy, *args, &block)
|
||||
end
|
||||
|
@ -49,6 +81,17 @@ module Docile
|
|||
|
||||
private
|
||||
|
||||
# @api private
|
||||
#
|
||||
# Execute a block in the context of an object whose methods represent the
|
||||
# commands in a DSL, using a specific proxy class.
|
||||
#
|
||||
# @param dsl [Object] context object whose methods make up the
|
||||
# (initial) DSL
|
||||
# @param proxy_type [Class] class to instantiate as the proxy context
|
||||
# @param args [Array] arguments to be passed to the block
|
||||
# @yield the block of DSL commands to be executed
|
||||
# @return [Object] the return value of the block
|
||||
def exec_in_proxy_context(dsl, proxy_type, *args, &block)
|
||||
block_context = eval("self", block.binding)
|
||||
proxy_context = proxy_type.new(dsl, proxy_type.new(dsl, block_context))
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
require "docile/fallback_context_proxy"
|
||||
|
||||
module Docile
|
||||
|
||||
# Operates in the same manner as {FallbackContextProxy}, but replacing
|
||||
# the primary `receiver` object with the result of each proxied method.
|
||||
#
|
||||
# This is useful for implementing DSL evaluation for immutable context
|
||||
# objects.
|
||||
#
|
||||
# @see Docile#dsl_eval_immutable
|
||||
class ChainingFallbackContextProxy < FallbackContextProxy
|
||||
|
||||
# Proxy methods as in {FallbackContextProxy#method_missing}, replacing
|
||||
# `receiver` with the returned value.
|
||||
def method_missing(method, *args, &block)
|
||||
@__receiver__ = super(method, *args, &block)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -7,6 +7,10 @@ module Docile
|
|||
# Will attempt to forward all method calls first to the primary receiver,
|
||||
# and then to the fallback receiver if the primary does not handle that
|
||||
# method.
|
||||
#
|
||||
# This is useful for implementing DSL evaluation in the context of an object.
|
||||
#
|
||||
# @see Docile#dsl_eval
|
||||
class FallbackContextProxy
|
||||
# The set of methods which will **not** be proxied, but instead answered
|
||||
# by this object directly.
|
||||
|
|
Loading…
Reference in a new issue