2013-07-09 60 views
2

我正在創建一個功能,其工作方式與ActiveRecord::Basefind_by_'column_name'工作方式類似。例如,如果我這樣做ActiveRecord :: Base「find_by_」方法如何工作?

User.find_by_address("1234 Apple Road")

它會查找通過address列。但我很困惑它是如何工作的。

當我查看代碼中「動態匹配器」的代碼時,我看到self.prefixself.suffix,例如, here,但在我的研究中,我找不到任何關於用於Ruby的self.prefixself.suffix

我該如何創建這種功能?

回答

5

它使用method_missing,這是一個回調,當一個名字不可識別的方法被調用時,Ruby提供了回調。這是在Ruby中使用動態名稱創建方法的標準方法。

傳遞給它的第一個參數是一個表示方法名稱的Symbol,然後它接收傳遞給無法識別的方法的每個參數。

1

比方說,你有一個動物園,一個非常漂亮的動物園,一羣野生動物。當然,作爲動物園飼養員,你經常需要根據他們的需求和特點找到特定的動物。但隨着動物園的成長和壯大,事先不可能知道這些特徵是什麼!讓我們試着解決這個問題...

首先,我們來定義什麼是動物;

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 

完成!一個功能齊全的動物園,我們可以在這裏搜索我們的動物!

相關問題