比方说,你有一个动物园,一个非常漂亮的动物园,一群野生动物。当然,作为动物园饲养员,你经常需要根据他们的需求和特点找到特定的动物。但随着动物园的成长和壮大,事先不可能知道这些特征是什么!让我们试着解决这个问题...
首先,我们来定义什么是动物;
class Animal
def initialize(attributes)
@attributes = attributes
end
def [](value)
@attributes[value]
end
end
够简单。现在,我们来建造动物园!
class Zoo
def animals
@animals ||= []
end
end
什么是没有动物的动物园?
完美。我们现在有一个充满动物的动物园。现在,我们知道它们都有其特定的特征,但我们仍然无法找到它们......能够像这样搜索我们的动物不是很好吗?
zoo.find_animals_by_region('Africa')
但请记住,我们并不知道所有这些特征!让我们尝试通过向我们的动物园添加特殊方法来解决这个问题。
class Zoo
def animals
@@animals ||= []
end
def method_missing(method_name, *args, &block)
# stuff here
end
end
大,我们现在可以捕获所有的呼叫,我们的动物园未定义的方法,这意味着find_animals_by_something会抓马上,因为它是不确定的!而且,我们甚至可以获得使用的method_name。大!让我们使用这个来获得我们的优势。
class Zoo
def animals
@@animals ||= []
end
def method_missing(method_name, *args, &block)
if method_name.to_s.start_with?('find_animals_by_')
# here we go!
end
end
end
这里我们开始吧!我们现在只捕获以特殊关键字“find_animals_by_”开头的缺少方法。让我们在其中添加一些逻辑,并且不要忘记针对不需要的方法调用super!
class Zoo
def animals
@@animals ||= []
end
def method_missing(method_name, *args, &block)
if method_name.to_s.start_with?('find_animals_by_')
find_animals_by_attribute(method_name[16..-1], args[0])
else
super(method_name, *args, &block)
end
end
def find_animals_by_attribute(attribute, value)
animals.select{ |animal| animal[attribute.to_sym] == value }
end
end
完成!一个功能齐全的动物园,我们可以在这里搜索我们的动物!