2011-11-22 110 views
7

缺乏背景下的叫我的路由時,我一直有缺失情況和nilClass錯誤的問題。在源代碼中進行深入研究後,似乎generate_method調用基本上使用初始方法的塊創建了一個新方法。工作圍繞Sinatra的途徑方法

get "/" do 
    @some_local_instance.do_something() 
end 

所以在上面的方法有很可能是該類稱爲some_local_instance內的局部變量,但是當死記硬背實際上是評估它沒有上下文來定義的方法,其中,所以它會失敗。

我之所以這樣問是因爲我的腳本的一部分,我有西納特拉時加載哪個寄存器路線,當這些路由是我需要訪問這些類的一些局部變量被加載外部類。一個例子是:

class SomeRouteClass 
    def initialize(sinatra, calculator) 
     @calculator = calculator 
     @sinatra = sinatra 
    end 

    def setup_routes 
     @sinatra.get "/add" do 
      return @calculator.add(1,1) 
     end 
    end 
end 

class Calculator 
    def add(a,b) 
     return a+b; 
    end 
end 

sinatra = Sinatra.new 
calculator = Calculator.new 

routing_class = SomeRouteClass.new(sinatra, calculator) 
routing_class.setup_routes 

sinatra.run! 

原諒任何拼寫/語法錯誤,這只是一個簡單的例子,但你可以看到一個類註冊路線,當這條路被擊中返回該計算器的情況下產生一定的價值它在實例化時花費了。

問題我在這個例子中,當我嘗試運行/添加路由時,它告訴我@calculator是一個nilClass,我相信這是Sinatra只需要代碼塊的方式上下文。對於任何簡單的模板渲染來說,這似乎都很好,但是如果你需要做更多的事情,或者希望通過不使用靜態和單例模塊來保持代碼模塊化,你似乎沒有辦法解決這個問題......

我的假設在這裏正確嗎?如果是的話有沒有什麼辦法讓上下文感覺它逼着我寫的不好,難以維護的代碼,如果我有寫的一切,靜態和單身從路由交互。

== ==編輯

已經重構的問題和內容,以更準確地反映實際的問題,現在我有庫的一個更穩固的理解。

+1

通過源多一些期待之後,它似乎不只是複製和粘貼與使用define_method的新路徑一起使用的方法。所以這個方法之外沒有任何背景......這意味着唯一的解決辦法就是將所有東西都變成靜態的,這似乎是錯誤的......因爲它很難以這種方式進行改變和測試......我可以完全雖然Ruby對我來說仍然是一種新語言,但它錯誤地做了什麼。 – Grofit

+0

一直試圖使用常量對象模式來解決這個問題,但這仍然使事情真的很討厭,因爲一切都必須是靜態的,這樣才能工作...是否有一個原因,他們將方法體複製到一個新的方法所以它失去了所有的情況?因爲我看不到任何好處,只是缺點...雖然我對此還是很陌生,因此可能無法完全理解某些需要這樣做的複雜因素。我只能想到的一點是,方法主體對象可能被清除,或者方法可能在被調用之前被更新或從實例中取走,但看起來不太可能 – Grofit

回答

0

我不能接受這個答案,但這樣做更多的研究後,它可能是在像Ruby靜態類的動態語言都沒有,如從一個維修點的噩夢。

看來,最重要的Ruby庫對靜態實例(或consts),它得到的設置,然後使用工作......這確實還顯得有些奇怪了吧,如在查看數據庫提供商點。只需調用數據庫靜態類並連接到數據庫然後開始查詢是非常簡單的,但是如果您需要同時連接到2個獨立的數據庫,該怎麼辦?你需要繼續使用相同的靜態類來交換服務器,這很麻煩。

無論如何它似乎此刻的答案只是使你需要暴露給路線的所有東西都保持不變,然後當你正在測試時,只需將該常量設置爲模擬。它似乎仍然有點瘋狂調用這些東西consts的時候,確實他們不是在這個詞的真正意義上的consts,因爲他們可以在任何時候改變......像許多事新Ruby開發者似乎只是爲了貪圖混亂它(即elsif,@@ blah,變量大小寫是否定義)。

正如我所說的,我不會接受這個答案,如果別人能告訴我這樣做的更好的模式,但目前將會給它幾天。

+0

它看起來像使用助手,你可以把一些邏輯內,但仍然不覺得很好。我在看Padrino,因爲它至少提供了一個控制器和每個控制器助手的外觀,更好地封裝了你的數據和邏輯,但是這些都是建立在sinatra之上的,所以必須有能力在默認的Sinatra版本。 – Grofit

-2
class SomeRouteClass 
    def initialize(sinatra, calculator) 
     @calculator = calculator 
     @sinatra = sinatra 
    end 

    def calculator 
     @calculator 
    end 

    def setup_routes 
     @sinatra.get "/add" do 
      return calculator.add(1,1) 
     end 
    end 
end 
+1

導致異常:未定義的局部變量或方法'計算器'爲#<#:0x29c9a60>,我看到你在那裏試圖做什麼,但它仍然看起來很奇怪。正如當你註冊PATTERN-X的時候你所說的一條路線叫做METHOD-Y,但是Sinatra是否會採取這種方法,並且圍繞它進行分類?所以它不再具有該方法之外的範圍的任何上下文? – Grofit

0

傳遞到get的塊在與Calculator對象不同的上下文中進行評估。 Sinatra可能會撥打instance_eval或其堂兄弟。然而,應該可以從周圍的範圍捕捉局部變量,使用類似以下的(未經測試,唉)做法:

def setup_routes 
    calculator = @calculator 
    @sinatra.get "/add" do 
     return calculator.add(1,1) 
    end 
end