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.
Pick Axe page on Binding