2012-05-23 57 views
1

在我的Rails應用程序3.0.11,我們有一個控制器非常簡單的代碼:控制器中的Rails異常執行查詢實例變量?

def index 
    @record = Record.valid # scope around 80,000 records 
    asdfasdfsa # consider this is a typo to raise NameError Exception 
end 

有趣的是,當它來到了錯字,應用程序似乎查詢/執行@record實例變量首先提出例外。查詢花費將近1分鐘以獲取記錄。所以在瀏覽器中,頁面在進入異常模板之前會長時間掛起。

如果我用局部變量「record」替換@record,查詢根本不會發生。任何人都知道它發生了什麼?

+0

這是什麼意思'正常變量'記錄''? –

+0

我應該叫它局部變量,而不是有@record = Record.valid,我們分配記錄= Record.valid – aquajach

+0

你使用某種異常通知寶石?如果沒有錯字,也沒有異常提出,它應該仍然掛起很長一段時間,或者當異常提出時掛起更長時間? (假設你的視圖用'@ record'做了一些事情,並且在正常情況下檢索數據)。 – nathanvda

回答

3

有關此問題的詳細信息,請參閱我的博文Ruby's Inspect Considered Harmful。總之,雖然:

  1. NameError格式的錯誤消息時
  2. 的所有實例變量inspect電話inspect默認實現遞歸
  3. NameError 扔掉inspect結果調用inspect如果是超過65個字符
  4. 對我們來說,這意味着在視圖原因中的拼寫錯誤ED的Rails掛20分鐘而紅寶石建立了一個巨大的,20MB的字符串,然後着手扔掉
  5. 我們花了7個月獲得trivial fix for this into Rails core

總之,我認爲NameError的行爲是Ruby解釋器中的一個令人髮指的錯誤。我可以想到這個實現沒有理智的原因。

+0

直接鏈接到monkypatch修復:https://github.com/rails/rails/issues/1525#issuecomment-2693127 – DGM

+0

'inspect','Kernel#global_variables'列出的'$ 1'的奇怪行爲, SystemStackError',緩慢的bug修復。看起來像核磁共振只是吸... – iblue

1

這是異常處理代碼的副作用。

想想你在兩種情況下看到的行爲。

  1. 實例變量 - 您已將查詢分配給控制器的實例變量。然後拋出一個異常,並且作爲該異常的一部分,rails會在控制器上調用to_s,然後強制執行查詢,默認情況下它將顯示所有實例變量。

  2. 本地變量 - 您已將查詢分配給控制器的局部變量。在這種情況下引發異常時,局部變量就會被丟棄。

我覺得很好的做法,始終覆蓋的對象,其中結構的創建字符串表示可能在Ruby控制檯昂貴的和/或垃圾to_s。

+0

你可以發佈一些對代碼的引用嗎?這發生在哪裏? – iblue

+0

我不知道它會發生在哪裏,但添加一個to_s方法到你的控制器並觀察它更快...... – DGM

+0

正如@DGM指出的那樣,當所有'魔術'發生時,實際源代碼變得複雜起來。 [鏈接](http://ruby-doc.org/core-1.9.3/Object.html#method-i-inspect)可能是最好的開始。我通常認爲重寫to_s是因爲它在一般情況下更有用,並且如果在對象上未覆蓋檢查,則檢查使用它的默認值。 – Khronos

4

正如@Khronos指出的,這是由於錯誤信息和評估變量,但它不是to_s,它是#inspect

in actiondispatch/middleware/templates/rescues/diagnostic.erb它調用<%=h @exception.message %>來顯示錯誤。一個快速的短途到IRB提供這麼一個小節目:

class Object ; def inspect; "foo" ; end ; end 
=> nil 
a=Exception.new(Object) 
=> #<Exception: #<Exception:0x10d8a4108>> 
a.message 
=> foo 

所以我認爲@ exception.message將調用檢查異常,這反過來可能導致呼叫控制器檢查上。雖然它在檢查過程中枚舉整個對象,但它運行查詢時,但它運行到_s時,我認爲它只會刪除所有對象ID。

我仍然有點模糊,但它至少與異常和檢查有關。

+0

我也很樂於辯論這是一件好事還是一個錯誤... – DGM

+0

你是對的#inspect被責備。我在回答中提供了詳細信息;我們已經對這個問題進行了很多爭論。 – kranzky

相關問題