After I published the post on rendering dynamic views with ERB, I got a bunch of emails from readers asking about the binding, as many had not seen or used it before. To be honest, I haven't used it in my typical Rails apps, too. However, it's a very interesting concept to learn about and very useful if you're working with view templates. So in this article, we'll learn about binding in Ruby.
What is Binding?
A Ruby binding is an instance of the Binding class. It's an object that packages or encapsulates the current scope, allowing you to pass it around in your code.
Objects of classBindingencapsulate the execution context at some particular place in the code and retain this context for future use. The variables, methods, and value ofselfthat can be accessed in this context are all retained.Bindingobjects can be created usingKernel#binding. - Ruby Docs
The Kernel#binding method returns the current binding object. Think of this binding object as a wrapper that encapsulates the current programming environment, i.e. variables, methods, and even the self object.
The basic idea behind binding is to store the current context in an object for later use. Later, you can execute some code in the context of that binding, using eval.
The most common and realistic use case for a binding object is to use it later to fill some pre-defined slots in a template, like ERB views. So you save the current context including variables in a binding, and use it somewhere else to generate the final views, just like Rails.
Evaluating Ruby Code in Different Context
The Kernel#eval method takes a string that contains Ruby code, executes it, and returns the result.
eval %q(
def run(task)
puts "running task: #{task}"
end
)
run "compile" # running task: compileHowever, you can pass a binding object as the second argument of the Kernel#eval method. This establishes the environment for the evaluation.
def get_binding(word)
return binding # calls Kernel#binding method
end
word = "Ruby"
eval "puts 'hello ' + word" # hello Ruby
eval "puts 'hello ' + word", get_binding("Rails") # hello RailsThe following example illustrates how eval returns a different value for the language variable for different bindings.
language = "JavaScript"
eval("puts language", binding) # JavaScript
def get_binding
language = "C-Sharp"
binding
end
new_binding = get_binding
eval("puts language", new_binding) # C-Sharp
class Ruby
def get_binding
language = "Ruby"
binding
end
end
ruby_binding = Ruby.new.get_binding
eval("puts language", ruby_binding) # Ruby
If you check out the source code of the IRB gem, you'll notice that it makes abundant use of the bindings.
Top-Level Binding
Ruby provides a constant called TOPLEVEL_BINDING that returns the binding of the top-level scope. Use it to access the top-level scope from anywhere in the program.
def run_ruby
puts "running inside main"
end
class Ruby
def run_ruby
puts "running inside Ruby"
end
def exec
eval "run_ruby", binding # running inside Ruby
eval "run_ruby", TOPLEVEL_BINDING # running inside main
end
end
Ruby.new.execHow ERB Uses Binding
The following code substitutes variables into a template string with erb. It uses Kernel#binding method to get the current context.
require 'erb'
name = 'Akshay'
age = 30
erb = ERB.new 'My name is <%= name %> and I am <%= age %> years old'
puts erb.result(binding)
# Output:
#
# "My name is Akshay and I am 30 years old"Note the<%= title %>statement. Within an erb template, Ruby code can be included using both<% %>and<%= %>tags.
The<% %>tags are used to execute Ruby code that does not return anything, such as conditions, loops, or blocks, and the<%= %>tags are used when you want to output the result.
What's going on in the above example?
- After requiring the
ERBgem and creating a few variables, we create an instance of theERBclass with a template string. - We create a
Bindingobject by calling theKernel#bindingmethod. Again, think of the binding object as a wrapper that includes the current programming environment with variables likenameandage, methods, and even theselfobject. - The
resultmethod on theerbobject uses this binding object and the variables defined in that binding to replace the slots in the template string, generating the final string printed above.
Now go ahead and re-read the previous post on rendering dynamic views. It will make more sense this time.

That's a wrap. I hope you liked this article and you learned something new.
As always, if you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I look forward to hearing from you.
If you'd like to receive future articles directly in your email, please subscribe to my blog. If you're already a subscriber, thank you.
