The Ruby Binding class is a pretty interesting idea. It allows you to execute code within the execution context of an instance of an object.

“Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use. The variables, methods, value of self, and possibly an iterator block that can be accessed in this context are all retained. Binding objects can be created using Kernel#binding, and are made available to the callback of Kernel#set_trace_func.” - Class: Binding (Ruby 1.9.3) Documentation

Using Kernel#eval you can run code within the context of a binding. Each class that has Kernel mixed in has a binding.

Let’s try an example:

class Person
    def initialize(first_name, last_name)
      @first_name = first_name
      @last_name = last_name
    end
    def get_binding
      binding
    end
    def to_s
      "#{@first_name} #{@last_name}"
    end
  end

  mo = Person.new("mo", "khan")
  p mo # "mo khan"
  eval("@first_name='magic'", mo.get_binding)
  p mo # "magic khan"

When you give eval a binding it executes the block of ruby code within the context of the binding. In this case a private instance variable named @first_name was re-assigned a value of ‘magic’.

This can be quite useful when rendering an ERB template and passing it a binding. An example of this is in the RAILS code base. When you assign an instance variable in a controller this is how the variable is made available to the erb view template.

comments powered by Disqus