Metaprogramming

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: Pattern matching

Article author: Arthur Isaev