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"