Home > binder

binder

Binder is a project mainly written in Ruby, it's free.

Allows you to rebind your ruby procs

= Motivation

If you're tired of creating APIs like this:

MyApp.configure do |c| c.description "My app's Description" end

and you long to create APIs like this:

MyApp.configure do description "My app's Description" end

Then look no further than this gem.

= Installation

gem install binder

= Use

In truth, there's no magic to this. If you want to change the context in which a block gets evaluated, you can use a combination of instance_eval and the fact that you can pass a proc to a method as if it were a block by prefixing it with an "&":

class Dog def do_tricks(&block) instance_eval(&block) end

def speak
  puts "ruff!"
end

def fetch
  puts "fetching...."
end

end

Dog.new.do_tricks do speak fetch end

If you're creating a large API like the Rails 3 router, you may find yourself writing a whole lot of mehods that run the block passed to it in some other context.

To dry up the process of creating these methods, you can use the binder gem:

require 'binder'

class Dog extend Binder bind :do_tricks, :self

def speak
  puts "ruff!"
end

def fetch
  puts "fetching...."
end

end

Dog.new.do_tricks do speak fetch end

First, we passed to bind the name of the method that we wanted to pass our block to; the second argument represents the context in which we want our block evaluated. :self, in this case, represents the instance of the Dog that we're calling "do_tricks" on. We could have alternatively passed a symbol representing an instance method or an instance variable.

If you wanted to bind class method instead of instance methods, you simply have to extend the singleton class:

require 'binder'

class Dog class << self extend Binder bind :do_tricks, :self

  def speak
    puts "ruff!"
  end

  def fetch
    puts "fetching...."
  end
end

end

Dog.do_tricks do speak fetch end

If you'd rather not have to extend all of your classes with "Binder" everytime you intend to use the "bind" class method, you can require 'binder/pervasive' instead. Note, however, that this will pollute your namespace, so if you've happened to define a "bind" method in any of your existing classes, you may run into issues.

require 'binder/pervasive'

class Dog bind :do_tricks, :self

def speak
  puts "ruff!"
end

def fetch
  puts "fetching...."
end

end

Dog.new.do_tricks do speak fetch end

== Proc#bind_to

In addition to the "bind" method, binder also adds a "bind_to" instance method to the Proc class. It allows you to change the context in which the proc is run:

require 'binder'

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!"

== "Tell"

The "Tell" 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:

require 'binder/tell'

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!"

Previous:copycouch