Metaprogramming
| Send messages | |
| define_method | |
| method_missing | |
| Freeze shared state |
Send messages
Every method call is a message, and send delivers a message chosen at runtime.
Pass the method name as a symbol or a string, and prefer public_send when private methods must stay off limits.
name = "ada"
puts name.send(:upcase)
puts name.public_send("upcase")
ruby send_demo.rb
ADA
ADA
define_method
The define_method call creates methods inside a loop, so similar methods need no repetition.
Each generated method closes over its own word, so hello and bye remember different values.
class Greeter
["hello", "bye"].each do |word|
define_method(word) do
puts word.upcase
end
end
end
Greeter.new.hello
ruby greeter_demo.rb
HELLO
method_missing
When no method matches, Ruby calls method_missing instead of failing right away.
Read the value from the hash when the key exists, call super otherwise, and mirror the logic in respond_to_missing?
class Config
def initialize(values)
@values = values
end
def method_missing(name, *args)
return @values[name] if @values.key?(name)
super
end
def respond_to_missing?(name, include_private = false)
@values.key?(name) || super
end
end
config = Config.new({ theme: "dark" })
puts config.theme
ruby config_demo.rb
dark
Freeze shared state
Shared constants invite accidental changes, and freeze locks an object against mutation.
A frozen hash raises FrozenError on write, while frozen? reports the locked state.
SETTINGS = { theme: "dark", retries: 3 }.freeze
puts SETTINGS.frozen?
ruby freeze_demo.rb
true
Next: Enumerators
Article author: Arthur Isaev