【问题标题】:Why can't I handle a limit exception in ActiveRecord?为什么我不能在 ActiveRecord 中处理限制异常?
【发布时间】:2016-04-16 05:27:55
【问题描述】:

今天我发现了一个我无法处理的奇妙异常。

当我写这段代码时:

def example
  Integer('example show')
rescue 
  p 'All is good, I handle it'
end

> example
#=> 'All is good, I handle it'

但是当ActiveRecord 抛出异常时,我得到:

def example
  SomeModel.all.limit('example show')
rescue
  p 'All is bad, I cannot handle it'
end

> example
#=> ArgumentError: invalid value for Integer(): "example show"

我认为这是一些神奇的深度异常或嵌套异常,但这也很好用:

class A
  def a
    b
  end
  def b 
    Integer('show example')
  end
end

begin
  A.new.a
rescue
  p 'All is good, I can handle it'
end
=> 'All is good, I can handle it'

【问题讨论】:

  • @DaveNewton,我更新了我的问题,请看一下。

标签: ruby-on-rails ruby exception activerecord


【解决方案1】:

发生这种情况是因为SomeModel.all.limit 的评估被延迟到您的rescue 块之外。 all.limit 返回一个 ActiveRecord::Relation 直到它必须运行时才真正运行,所以 example 返回就好了,然后你尝试使用该值,Rails 无法将 example show 转换为 Integer。这是来自我的控制台的演示:

> def example
*   User.all.limit('something')
* rescue
*   puts 'Rescued'
* end
=> :example
> foo = example
=> #<#<Class:#<ActiveRecord::Relation::ActiveRecord_Relation_User:0x007ffb5b52e168>>:0x3ffdada970b4>
> foo.to_a
ArgumentError: invalid value for Integer(): "something"

我建议您自己处理 somethingInteger 的转换,这样您就可以在您的 example 方法中正确捕获它。否则,每次访问example 的返回值时都需要rescue,这不会顺利进行。您还可以通过调用SomeModel.all.limit('something').load 来强制实例化example 中的关系。这将引发您的rescue 可以按照您期望的方式捕获它的异常。

【讨论】:

  • 啊,你说得对,我忘记了 ActiveRecord::Relation 在救援之前不会执行,所以 load 会解决这个问题,非常感谢。
  • 这里相关的不是它被延迟,而是它可能在不同的线程中运行。
  • @sawa:我在示例代码中没有看到任何线程指示,并且可以在没有并发的情况下复制它。你在哪里看到那些进来的人?
  • @Kristján 我不知道这一点,但如果它没有在不同的线程中运行,那么它不会在运行时完成块。
猜你喜欢
  • 2011-03-14
  • 2021-11-12
  • 2012-12-06
  • 1970-01-01
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2020-01-19
相关资源
最近更新 更多