【问题标题】:Raised error is not caught by rescue block救援块未捕获引发的错误
【发布时间】:2019-08-23 10:53:05
【问题描述】:

我们在使用 action mailer 发送电子邮件时遇到了生产问题。

NameError
undefined local variable or method `to_ary' for #<Mail::Part:0x0000000008e0c998>
Did you mean?  to_addrs

错误出现完全随机,行为方式与https://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/完全相同

我想做的是对missing_method 进行修补以使其工作。 所以我创建了一些测试,包括

let(:part) { Mail::Part.new }

it 'returns self' do
   allow_any_instance_of(Mail::Message).to receive(:method_missing).and_raise(NameError, 'error part')
   expect([part].flatten).to eq [part]
end

并创建了猴子补丁

require 'mail'

module Mail
  class Part < Message
    # monkey patched due to same behaviour like
    # https://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/v
    def method_missing(name, *args, &block)
      begin
        super
        pp :hello
      rescue NameError => e
        return [self] if name.try(:to_sym) == :to_ary
        raise e
      end
    end
  end
end

这个测试的目的是Array#flatten 在它的内容上调用to_aryMail::Part#method_missing 通常没有定义,但我创建了一个来处理来自 Mail::Message#method_missing 的可能的 NameError 并返回正确的值。

问题是,Mail::Part#method_missing 被调用,super 被调用并引发NameError,但救援不处理任何事情。 pp :hello 被跳过,因为引发了错误。

所以测试结束了

NameError: error part

  0) Mail::Part call flatten with NameError returns self
     Failure/Error: expect([part].flatten).to eq [part]

     NameError:
       error part
     # ./spec/lib/core_ext/mail/part_spec.rb:13:in `flatten'
     # ./spec/lib/core_ext/mail/part_spec.rb:13:in `block (4 levels) in <top (required)>'
     # ./spec/active_record_spec_helper.rb:19:in `block (2 levels) in <top (required)>'

另一个问题是,当我尝试时,测试以无限递归结束

def method_missing(name, *args, &block)
  return [self]
end

同理

def method_missing(name, *args, &block)
   begin
      raises_name_error
   rescue NameError => e
      return [self] if name.try(:to_sym) == :to_ary
      raise e
   end
end

def raises_name_error
   raise NameError, 'error part'
end

但在这种情况下,救援块处理NameError

有什么解决办法吗?

【问题讨论】:

  • 您的 Gemfile 和 Gemfile.lock 看起来如何?您是否尝试“隔离”您的错误以查看是否是 gem 依赖项导致的?
  • 我们使用捆绑器,它应该为我们检查依赖关系。我没有尝试过,我什至不知道这可能是由它引起的
  • 请问猴子补丁to_ary而不是method_missing会有什么问题?
  • 猴子补丁 missing_method 听起来更像是治疗症状,而不是解决问题。

标签: ruby-on-rails ruby error-handling actionmailer


【解决方案1】:

解决者

module Mail
  class Part < Message
    def to_ary
      []
    end
  end
end

我最初的解决方案尝试有点矫枉过正。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    相关资源
    最近更新 更多