2012-05-23 102 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

相关问题