【发布时间】: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_ary。 Mail::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