Метапрограммирование — это техника написания кода, который генерирует или модифицирует другой код во время выполнения. В Ruby это достигается благодаря динамической природе языка и мощному API для интроспекции и модификации объектов.
В Ruby можно переоткрыть любой класс и добавить или изменить его методы:
class String
def shout
"#{self.upcase}!!!"
end
end
"hello".shout # => "HELLO!!!"
Этот метод вызывается, когда объект получает сообщение (вызов метода), которое он не понимает:
class Ghost
def method_missing(name, *args)
"Призрачного метода #{name} не существует"
end
end
Ghost.new.boo # => "Призрачного метода boo не существует"
Позволяет динамически создавать методы во время выполнения:
class Dog
['bark', 'wag'].each do |action|
define_method(action) do
"Dog is #{action}ing!"
end
end
end
dog = Dog.new
dog.bark # => "Dog is barking!"
Эти методы выполняют строки кода или блоки в разных контекстах:
class Calculator
end
Calculator.class_eval do
def add(x, y)
x + y
end
end
calc = Calculator.new
calc.add(2, 3) # => 5
Модули позволяют добавлять методы в классы (include — методы экземпляра, extend — методы класса):
module Greeter
def hello
"Hello!"
end
end
class Person
include Greeter
end
Person.new.hello # => "Hello!"
Ruby позволяет исследовать объекты во время выполнения:
String.methods # => список всех методов класса String
"hello".class # => String
String.ancestors # => [String, Comparable, Object, Kernel, BasicObject]
Создадим DSL для настройки атрибутов модели:
class Model
def self.attribute(name, options = {})
define_method(name) do
instance_variable_get("@#{name}") || options[:default]
end
define_method("#{name}=") do |value|
instance_variable_set("@#{name}", value)
end
end
end
class User < Model
attribute :name, default: "Anonymous"
attribute :age
end
user = User.new
user.name # => "Anonymous"
user.name = "Alice"
user.name # => "Alice"
Резюмируем: метапрограммирование в Ruby — это мощный инструмент, который позволяет программам модифицировать себя во время выполнения. Оно основано на динамической природе Ruby и предоставляет множество методов для создания, модификации и исследования кода в рантайме. При грамотном использовании оно позволяет создавать гибкие и выразительные решения, но требует осторожности и хорошего понимания последствий.