Ruby has a facility for executing code stored in the form of strings at runtime. One of the methods in the cluster of eval methods is the class_eval method.
class_eval evaluates/executes a block of code in the context of the specified Class or module.
For example,
class String
def lowercase
self.downcase
end
end
String.class_eval do
def lowercase
self.downcase
end
end
In each of the above cases, the String class is reopened to add a new method.
Let's look at some things which we can do with class_eval that we cannot do with the regular class keyword:
- Evaluate a string in the class-definition context
- Use existing local variables inside a class-definition body
Example of evaluating a string of code
x = 1
String.class_eval "x + 1" # => 2
Example of usage of a local variable in regular class-definition body and block given to class_eval
# Out of scope
name = 'John'
class Human
puts name
end
# NameError (undefined local variable or method)
# inside the scope
name = 'John'
Human.class_eval { puts name } # => 'John'
But the same variable which we just defined is no longer visible when we define a method inside the class_eval block:
Human.class_eval { def speak; puts name; end } # => nil
Human.new.speak # => NameError (undefined local variable or method)
The def inside the block starts a new scope, hence the variable name is not accessible. But there is a way to access the name variable using the method define_method.
Human.class_eval { define_method(:speak) { puts name} } # => :speak
Human.new.speak # => 'John'
The way we do this is by passing the name of the method we want to create either as a string or a symbol and providing a code block, the code block serves as the body of the method. ( See example 👆)
define_methodis an instance method of the classModule, so you can call it on any instance of Module or Class.
Read more on the class_eval and define_method: