比方說,你有一個動物園,一個非常漂亮的動物園,一羣野生動物。當然,作爲動物園飼養員,你經常需要根據他們的需求和特點找到特定的動物。但隨着動物園的成長和壯大,事先不可能知道這些特徵是什麼!讓我們試着解決這個問題...
首先,我們來定義什麼是動物;
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
完成!一個功能齊全的動物園,我們可以在這裏搜索我們的動物!