Metaprogramming là code tạo hoặc thay đổi behavior của code. Ruby làm việc này tự nhiên vì class/module là object và method table có thể sửa runtime.
Dynamic dispatch
1 | attribute = :name |
Ưu tiên public_send khi input không được phép gọi private method. Allowlist method name từ user; dynamic dispatch không biến authorization thành tùy chọn.
Định nghĩa method
1 | class Serializer |
define_method giữ lexical closure, khác def mở scope mới.
class_eval và instance_eval
1 | User.class_eval do |
class_evalđịnh nghĩa instance behavior trên class/module.instance_evalđổiselfsang object; method định nghĩa ở đây thành singleton method của object đó.
Dùng khi xây DSL/framework boundary, không dùng để làm code business “ngầu”.
method_missing
1 | def method_missing(name, *args) |
Nếu override method_missing, phải đồng bộ respond_to_missing?. Nếu tập method biết trước, define_method dễ debug hơn.
Scope gates
class, module, def mở lexical scope mới. Block giữ outer locals:
1 | prefix = "audit" |
Rủi ro
- stack trace khó đọc;
- IDE/static analysis kém;
- public API sinh runtime khó discover;
- monkey patch xung đột version;
evalvới input tạo code execution.
Rule thực dụng: nếu loop/collection/ordinary object giải quyết được, dùng chúng trước. Metaprogramming tốt làm API đơn giản hơn cho nhiều caller; metaprogramming tệ chuyển complexity vào bóng tối rồi gọi đó là magic.