Ruby Define Method at Depth
The intermediate course built methods with define_method from names in a loop. This lesson looks closer at symbol names and at the values the generated blocks capture.
Methods generated from a list of symbols
A list holds two symbols, and the loop builds one method for each symbol. Each generated method answers with its own symbol as a string.
class Parrot
[:squawk, :chirp].each do |sound|
define_method(sound) do
sound.to_s
end
end
end
parrot = Parrot.new
puts parrot.squawk
puts parrot.chirpA symbol name and an argument
The name here is written as the symbol :twice. The block parameter becomes the argument of the generated method.
class Doubler
define_method(:twice) do |number|
number * 2
end
end
puts Doubler.new.twice 21Each loop pass keeps its own value
The loop runs once for red and once for green. Each block captures the value from its own pass, so the two methods answer differently.
class Team
[:red, :green].each do |color|
define_method(color) do
color.to_s
end
end
end
team = Team.new
puts team.red
puts team.greenA shared local answers its last value
This block captures a plain local instead of a loop value. The local is reassigned after the method is built, and the method reads the shared local when it is called.
class Team
color = :red
define_method(:shade) do
color.to_s
end
color = :blue
end
puts Team.new.shadeExample
class Greeter
[:hi, :hey].each do |word|
define_method(word) do |name|
"#{word} #{name}"
end
end
end
greeter = Greeter.new
puts greeter.hi "Ana"
puts greeter.hey "Ben"Key points
- define_method takes a symbol as the name of the new method.
- The block parameter becomes an argument of the generated method.
- Each pass of a loop gives its block a fresh captured value.
- A generated method keeps the value its own block captured.
- A plain local shared by a block keeps only its last value.
In this example, a loop builds the hi and hey methods on the Greeter class. Each block parameter becomes the name argument of its method. Each call prints its greeting word with the name passed in.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A class sets color = :red, builds a method answering color.to_s, then sets color = :blue. What does the method answer?