Metaprogramming Techniques
Ruby code that writes and inspects code at run time: dynamic calls, generated methods, ghost methods, eval contexts, singleton classes and hooks. Interviewers probe when reaching for it is a mistake.
on this pageshowhide
explore
- Send & Dynamic Calls4 questions
- Defining Methods Dynamically5 questions
- Ghost Methods & Fallbacks4 questions
- Evaluation Contexts5 questions
- Introspection APIs6 questions
- Singleton Classes4 questions
- Monkey Patching5 questions
- DSL Construction4 questions
- Subclass & Definition Hooks4 questions
questions
page 2 of 2In Ruby, how can a `logged` class-level call use method_added to wrap the next method defined, and why can a naive version raise SystemStackError?
basics
~20 slogged sets a flag, and method_added(name) wraps the method just defined. If the wrapper is defined with define_method in the same class before the flag is cleared, that definition fires method_added again, endlessly. Clear the flag first, or prepend the wrapper.
In Ruby, a method on a live object behaves unlike the code you read — how do you find the file and line that actually define it?
basics
~10 sCall obj.method(:name).source_location. It returns the file and line of the definition that call would actually run, exposing a patch or prepended module; nil means the method is implemented in C.
In Ruby, why is a prepended module calling super safer than an alias_method chain for patching a method, and what happens when both patch one method?
basics
~20 sA prepended module sits in front of the class, so its super reaches the original without renaming anything, and stacked patches compose. An alias chain snapshots the original; loaded twice, or added after a prepend on one method, it recurses into SystemStackError.
In a Ruby admin panel that dispatches each button's action name to a service object's method, should it use send or public_send, and what else guards the dispatch?
basics
~20 spublic_send, so private and protected helpers stay unreachable. Visibility alone is not an allowlist: inherited public methods such as instance_variable_set and send remain callable, so check the name against a frozen list of allowed actions before dispatching.
In Ruby, a spec gives one object a singleton method — why can Marshal.dump of it then fail, and which objects refuse singleton methods entirely?
basics
~20 sMarshal cannot serialize methods, so dumping an object whose singleton class holds methods raises TypeError. Integers, Floats and Symbols refuse singleton methods with TypeError, frozen objects with FrozenError, and nil, true and false patch their shared classes.
In a Ruby codebase, what team policy would you set for monkey-patching core classes like Integer and String, and why?
basics
~20 sDefault to not patching: helpers, wrapper objects or refinements. A justified global patch lives in one core_ext file per class as a named, prepended module that raises if the name exists, pinned by tests and checked in CI with -w and -W:performance.
In Ruby, what can eval(code, some_binding) read, and why can't later code in your method use a local the string assigned?
basics
~20 sKernel#eval with a Binding runs the string in that binding's context: its self, its local variables and its constant scope. Locals the string creates stay in that binding, because the surrounding method's locals were fixed when it was parsed.
In Ruby, why does BasicObject define __send__ when Kernel already provides send, and when should library code call it?
basics
~20 ssend behaves like send but lives on BasicObject under a name nobody overrides by accident. Library code that dispatches on objects it does not control uses it, because a class may define its own send and BasicObject subclasses have no Kernel#send.
When building a Ruby DSL, what does an RSpec-style shape, where each group block becomes the body of a new class, give you over Rake-style methods added to main?
basics
~20 sRake extends the top-level main object with private DSL methods: flat files work, but helper defs land on Object. RSpec runs each group block as a Class.new subclass body via module_exec, so helpers are methods, nesting is inheritance and examples get fresh instances.
In Ruby, what does ObjectSpace.each_object(Session) yield and return, and why is its count not an exact number of live sessions?
basics
~20 sIt yields every heap object that is a Session or subclass instance and returns how many it yielded. The count can include unreachable objects the GC has not yet collected, so it is an upper bound, not a live count.
In Ruby 4.0, what does redefining Integer#+ in a patch cost at run time, and how do you make Ruby warn about it?
basics
~20 sInteger#+ is a core method the interpreter and JIT run without a method call; redefining it, by def or prepend, flags it so every Integer + becomes a full call. Ruby warns only under -W:performance or Warning[:performance] = true.
showing 31–41 of 41