使用动作邮件发送电子邮件时,我们遇到了生产问题。
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
通常没有定义,但是我创建了一个以处理NameError
中可能的Mail::Message#method_missing
并返回正确的值。
问题在于,调用了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
。
有解决方案的想法吗?
答案 0 :(得分:0)
解决者
module Mail
class Part < Message
def to_ary
[]
end
end
end
我最初的解决方案尝试不过分。