Installation
# gem install binder
Use
binder allows you to change the closure in which a proc is executed. This is helpful for anyone developing their own domain specific language in ruby. For more information about proc binding, check out this post I wrote which in turn inspired me to write this gem: moonmaster9000.tumblr.com/post/398991873/creating-cleaner-apis
Proc#bind_to
The #bind_to method on a proc instance allows you to change the closure in which the proc is run:
require 'binder'
# ==> true
def speak
"why should i?"
end
class Dog
def speak
"ruff!"
end
end
command = proc { speak }
command.call
# ==> "why should i?"
command.bind_to(Dog.new).call
# ==> "ruff!"
Object#tell (or #ask, #beg, or #teach)
The “tell”/“ask”/“beg”/“teach” method is essentially short hand for an instance_eval on an object - it simply presents you with a more human readable way of using this language feature:
class Dog
def speak
puts "ruff!"
end
end
fido = Dog.new
fido.instance_eval do
speak
end
# ==> would print "ruff!"
tell fido do
speak
end
# or
tell(fido) { speak }
# or
tell(fido, :to) { speak }
# ==> would all print "ruff!" - and these are all equivalent to the instance eval above
commands = proc { speak }
fido.instance_eval(&commands)
# ==> would print "ruff"
tell fido, commands
# ==> would also print "ruff!"
Object##bind
binder also provides the “#bind” object class method to DRY up your DSL instance methods:
class Dog
# binds a "do_trick" instance method to the instance of Dog
bind :do_trick, :self
def speak
"ruff!"
end
end
Dog.new.do_trick { speak }
# ==> "ruff!"
class Cat
# binds a block passed to a "do_trick" instance method to the Cat class
bind :do_trick, :class
class << self
def speak
"screw you"
end
end
def speak
"bugger off"
end
end
Cat.new.do_trick { speak }
# ==> "screw you"
class Kitten
bind :do_trick, :mother # binds to @mother instance variable
def initialize(mom)
@mother = mom
end
end
Kitten.new(Cat).do_trick { speak }
# ==> "screw you"
Kitten.new(Cat.new).do_trick { speak }
# ==> "bugger off"
Kitten.new(Dog.new).do_trick { speak }
# ==> "ruff!"
Object##bind_class_method
Whereas the Object##bind method created instance methods, Object##bind_class_method creates class methods:
class Cat
# binds to Cat class, not an instance of Cat
bind :do_trick, :class
class << self
def speak
"screw you"
end
end
def speak
"bugger off"
end
end
class Lion
# binds to Lion, since "self" will be evaluated in the context
# of a class method
bind_class_method :tame, :self
# binds to value returned by method "child"
bind_class_method :do_trick, :child
class << self
def down_kitty
"meow"
end
def child
@child ||= Cat
end
end
end
Lion.tame { down_kitty }
# ==> "meow"
Lion.do_trick { speak }
# ==> "screw you"