2011-11-29 20 views
4

這是一個關於Sinatra處理路線方法的前一個問題的更加集中的版本。爲什麼Sinatra複製路徑的方法塊?

從我的源代碼西納特拉採取的路線中的方法塊的理解,使含有相同的身體出即一種新的方法:

get "some/url" do 
    return "Hello World" # this gets taken out 
end 

所以在這個例子中,方法體似乎被複制轉變成適用於Sinatra物體的新方法。我只是想知道爲什麼會發生這種情況,我嘗試了他們的IRC頻道,但沒有人在那裏,郵件列表並不那麼繁忙。

主要大宗,我在他們的框架談論的源代碼是base.rb內圍繞線1180:

def generate_method(method_name, &block) 
    define_method(method_name, &block) 
    method = instance_method method_name 
    remove_method method_name 
    method 
    end 

那麼,有沒有他們爲什麼這樣做,不只是引用任何具體原因該方法本身?

我問這個問題的原因是因爲Sinatra目前處理這個問題的方式使得它不可能擁有一種超越自身知識的方法,並且通過僅僅採用一種沒有上下文的方法來打破類封裝。

回答

4

正如上面的評論,這產生了一種方法。一個合適的方法。如果Sinatra不會在generate_method中再次刪除該方法,則可以通過執行諸如send("GET some/url")之類的操作來調用該方法。問題是,爲什麼Sinatra再次刪除這個方法?簡單來說,每條路線可能有多個處理程序:

get 'some/route' do 
    pass if request.referrer == '/foo' 
    "didn't come from /foo" 
end 

get 'some/route' do 
    "did come from /foo" 
end 

兩種方法都具有相同的名稱。

至於你關於子類和方法的註釋,這應該工作:

class MyApp < Sinatra::Base 
    def content 
    return "did come from /foo" if request.referrer == '/foo' 
    "didn't come from /foo" 
    end 

    get('some/route') { content } 
end 

或者,做一個經典的應用程序時:

helper do 
    def content 
    return "did come from /foo" if request.referrer == '/foo' 
    "didn't come from /foo" 
    end 
end 

get('some/route') { content } 
+0

我認爲這個問題的答案已經很清楚了,這是我的誤解,認爲這是一種不是匿名方法的一流方法。它仍然沒有幫助我的*實際*問題,但這是另一個問題。 – Grofit

+0

有一件事剛剛浮現在你的最後一個例子中,你展示了一種訪問匿名方法範圍之外的東西的方法,這非常棒... **是**我的問題,但是由看起來,唯一的方法是將其添加到幫助程序或使用set。這對於那些方法塊實際上可以完成你所需要的任何事情的小事物來說似乎非常棒,但是當你對其他類和實例有依賴關係時,你似乎將幾乎所有東西都添加到了幫助器中,以便將它放在範圍內。展示我所面臨的主要問題的一個問題是關於KL-7的其中一條評論。 – Grofit

+0

您應該查看模塊化應用程序。 –

3

我的猜測是他們希望每個路由都有完整的方法(可以訪問其他實例和類方法),但不想污染名稱空間。方法名稱生成爲"#{verb} #{path}",所以如果例如對於相同路徑有不同條件的多條路徑,除非在定義並將其存儲在別的地方之後立即刪除方法,否則衝突是不可避免的。而這正是他們所做的。方法是未綁定的,但它不是問題,因爲它們以後可以將其綁定到類的任何實例。

注意,這只是一個猜測。我不熟悉Sinatra,所以這個實現可能有完全不同的想法。

+0

也許我只是不正確的理解,但是不可能只是有一個指向方法鍵的路由列表?那麼該方法鍵引用ACTUAL方法,而不是新生成的方法。這將滿足具有到同一方法的多條路線的標準。我只是把這看作是一個看起來很棒的框架/庫,對我來說幾乎是一個癱瘓的問題。因爲在這些方法中做任何業務邏輯幾乎是不可能的,因爲你只能真正使用靜態/全局對象,並且幾乎停止了任何OO實踐。 – Grofit

+0

你是指「實際」的方法?當你在sinatra中定義路由時,你正在傳遞路徑字符串,一些選項以及最後一個塊到'get'方法。當時沒有任何特定路線的方法。這個動作發生在'generate_method'裏面,其中會生成一些名爲'GET /'的新方法,並將其他一些選項存儲到某個數組中。你在問題中提到的'方法體'和'複製方法'實際上分別是'塊體'和'塊轉換方法'。 –

+0

順便說一句,這是如何防止你使用面向對象? –

0

我想這只是模擬instance_exec支持紅寶石比老1.8.7

相關問題