February 22, 2019
Given the class Person
as shown below.
class Person
NAME = "Mark"
def talk(msg)
puts msg
end
end
The goal of this article is to let you know an alternate approach about
constants and classes. If you are not familiar about how lambdas
work,
read the Procs and Lambdas article first.
Using metaprogramming, we can define a constant by using the const_set
method. Looking at our example, let’s use const_set
to define our constant.
# Will work regardless if NAME is a string or a symbol.
Object.const_set(:NAME, "Mark")
Object.const_set("NAME", "Mark")
To read and access a constant’s value, we use const_get
.
# Will both return "Mark"
Object.const_get(:NAME)
Object.const_get("NAME")
We can define a method by using define_method
with a method name and a
block.
define_method "talk" do |msg|
puts msg
end
# or separate the block by:
blk = -> (msg) { puts msg }
define_method "talk", &blk
Looking from our original example at the beginning of this article, we know
that the Person
class has a constant called NAME
and a single instance
method talk
so let’s define the behavior that will define those requirements.
blk = -> (msg) { puts msg }
klass = -> (klass) do
klass.const_set(:NAME, "Mark")
define_method("talk", &blk)
end
# class_eval executes the passed block in the context
# of the class that's why the variable `klass` accepts a
# class object which in this example is `Person`.
Person = Class.new
Person.class_eval(&klass)
Person.new.talk("Hello world!") # Returns "Hello world!"
With a whole new understanding of constants and classes, it’ll be easy for you to read and understand Ruby code without relying on the Internet.
To learn more about metaprogramming, I suggest taking @saturnflyer’s Ruby Metaprogramming Class.
Happy reading!