Skip to content

Instantly share code, notes, and snippets.

@pnc
Created October 23, 2010 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pnc/642374 to your computer and use it in GitHub Desktop.
Save pnc/642374 to your computer and use it in GitHub Desktop.
Groovy's delegate method, implemented for Ruby Procs
# The idea here is to emulate Groovy's delegate= pattern for closures.
# We define a builder module. This will receive method calls
# from our builder. It could be an instance of an object if we wanted.
module FamilyBuilder
def self.parent(name)
puts "Parent: #{name}"
end
def self.child(name)
puts "Child: #{name}"
end
end
class Proc
# Sets the delegate for this Proc to be the given
# object, or clears the delegate if nil is given.
def delegate=(object)
@delegate = object
@delegated = !!(object)
end
alias_method :original_call, :call
def call
if @delegated
# Evaluate ourselves, but against the delegate
# rather than the original binding.
@delegate.instance_eval(&self)
else
original_call
end
end
# A helper to temporarily set the delegate, execute,
# and then reset the delegate
def evaluate_against(object)
original_delegate = @delegate
self.delegate = object
self.call
self.delegate = original_delegate
end
end
build = Proc.new do
parent "Bill"
parent "Jane"
child "Jack"
end
# Use the delegate setter explicitly, as in Groovy.
build.delegate = FamilyBuilder
build.call
# =================
# An example with an object instance:
greeting = "Hello James!"
Proc.new do
gsub! "James", "Phil"
end.evaluate_against(greeting)
puts greeting
@pnc
Copy link
Author

pnc commented Oct 23, 2010

Output:

Parent: Bill
Parent: Jane
Child: Jack
Hello Phil!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment