skip to content

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 pageshow

explore

questions

page 2 of 2

In 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?

level: seniorimportance: should knowfreq 20%

basics

~20 s

logged 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.

open as a page

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?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Call 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.

open as a page

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?

level: seniorimportance: should knowfreq 45%

basics

~20 s

A 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.

open as a page

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?

level: seniorimportance: should knowfreq 36%

basics

~20 s

public_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.

open as a page

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?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Marshal 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.

open as a page

In a Ruby codebase, what team policy would you set for monkey-patching core classes like Integer and String, and why?

level: principalimportance: should knowfreq 25%

basics

~20 s

Default 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.

open as a page

In Ruby, what can eval(code, some_binding) read, and why can't later code in your method use a local the string assigned?

level: middleimportance: nice to knowfreq 22%

basics

~20 s

Kernel#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.

open as a page

In Ruby, why does BasicObject define __send__ when Kernel already provides send, and when should library code call it?

level: middleimportance: nice to knowfreq 24%

basics

~20 s

send 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.

open as a page

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?

level: seniorimportance: nice to knowfreq 20%

basics

~20 s

Rake 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.

open as a page

In Ruby, what does ObjectSpace.each_object(Session) yield and return, and why is its count not an exact number of live sessions?

level: seniorimportance: nice to knowfreq 15%

basics

~20 s

It 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.

open as a page

In Ruby 4.0, what does redefining Integer#+ in a patch cost at run time, and how do you make Ruby warn about it?

level: seniorimportance: nice to knowfreq 20%

basics

~20 s

Integer#+ 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.

open as a page

showing 31–41 of 41