Introduction to Bindings

Tuesday, March 20, 2007 by Nate Murray.

The Pixaxe book defines Binding objects to:

encapsulate the execution context at some particular place in the code and retain this context for future use.

You can get a Binding for the current context by calling Kernel#binding.

The Binding stores information about the variables, methods, and self and you can access them by passing the Binding to eval.


  class Product
    def set_title(title)
      @title = title
    end

    def get_binding
      binding
    end
  end

  p = Product.new
  p.set_title("nice and shiny")

  q = Product.new
  q.set_title("old and ugly")

  eval "@title", p.get_binding    # => "nice and shiny"
  eval "@title", q.get_binding    # => "old and ugly"

You can see here that @title gets evaluated differently depending on the binding. The first eval returns "nice and shiny" because that is the value of @title for the first Product p.

Blocks and Procs

Blocks carry information about their Binding.



  a = "inside a"
  a_block = lambda { a }

  def try_to_set_a(block)
    a = "resetting a"
    block.call
  end

  try_to_set_a(a_block)          # => "inside a"


Notice here that a is "inside a" and not "resetting a". This is beacuse a block stores the variables as they were originally defined. The a in try_to_set_a does not interfere with the a in a_block.

An interesting note is that you can redefine variable within a Binding.

  a = "inside a"
  a_block = lambda { a }

  def try_to_set_a(block)
    a = "resetting a"
    block.call
  end

  eval "a = 'something else'"
  try_to_set_a(a_block)          # => "something else"

This is because the Binding in this case is the top-level binding which happens to be the same binding in which a was defined in originally.

Practical Use

Bindings are often used when evaluating ERB. (For those of you who don’t know, ERB is a template system that is included in the Ruby Standard Library.)

ERB#result takes a Binding object as its argument and the variables in the ERB template are evaluated in this context.

Going back to our Product example from earlier, lets see how we can use the Product’s bindings in this fashon:

  require 'erb'

  class Product
    def set_title(title)
      @title = title
    end

    def set_cost(cost)
      @cost = cost
    end

    def get_binding
      binding
    end
  end

  p = Product.new
  p.set_title("nice and shiny")
  p.set_cost("19.95")

  q = Product.new
  q.set_title("old and ugly")
  q.set_cost("230.00")

  template = ERB.new <<-EO_ERB
    == Invoice
    Title: <%= @title %>
    Cost:  <%= @cost  %>
  EO_ERB

  template.result(p.get_binding)   # => "  == Invoice\n  Title: nice and shiny\n  Cost:  19.95\n"
  template.result(q.get_binding)   # => "  == Invoice\n  Title: old and ugly\n  Cost:  230.00\n"

Conclusion

As you can see Binding is a very handy object but this article serves as only an introduction to the subject. Here are a couple articles that deal with binding a little more in-depth.

Jim Weirich’s Variable Bindings in Ruby
Pick Axe page on Binding

Labels: , ,

» Post a Comment

Who we are:
The Pasadena Ruby Brigade is a group of programmers who are interested in Ruby. We enjoy sharing our ideas and code with anyone who is interested in this wonderful programming language.

Who can join:
Anyone! Just head over to our mailing list and drop us an email.

What we do:
We recently started a project over at RubyForge. This project is a group of programs written and maintained by our members that we thought could be beneficial to the whole community.

Projects

Downloads

Recent Posts

Archives