Refactoring: Refactorings/Replace Dynamic Receptor with Dynamic Method Definition
Jump to navigation
Jump to search
Classes that use method_missing errors are difficult to debug, so use a dynamic method definition to define the necessary methods.
Mechanics
- Dynamically define the necessary methods
- Test
- Remove method_missing
- Test
Example: Dynamic Delegation
Before
If a method is not defined in subject, then error messages can become cryptic.
class Decorator
def initialize(subject)
@subject = subject
end
def method_missing(sym, *args, &block)
@subject.send sym, *args, &block
end
end
After
class Decorator
def initialize(subject)
subject.public_methods(false).each do |method|
(class << self; self; end).class_eval do
define method method do |*args|
subject.send method, *args
end
end
end
end
end
Example: User-Defined Data
Before
class Person
attr_reader :name, age
def method_missing(sym, *args, &block)
empty?(sym.to_s.sub(/^empty_/,"").chomp("?"))
end
def empty?(sym)
self.send(sym).nil?
end
end
After
class Person
def self.attrs_with_empty_predicate(*args)
attr_accessor *args
args.each do |attribute|
define_method "empty_#{attribute}?" do
self.send(attribute).nil?
end
end
end
attrs_with_empty_predicate :name, :age
end