【发布时间】:2020-11-04 14:56:47
【问题描述】:
我有一个模块,它通过点语法为哈希提供一些惰性查找:
module DotHash
def method_missing(method_name, *args, &block)
# look for keys...
end
def respond_to_missing?(method_name, _include_all = nil)
# some logic
end
end
遇到了不小心扩展nil的问题:
# @hash == nil
@hash.extend(DotHash)
这引起了巨大的问题,因为现在nil 有这个method_missing 逻辑,这把事情搞砸了。
我虽然添加一个钩子可以解决问题:
module DotHash
def self.extended(base)
return if base.is_a?(Hash)
raise "must be a hash"
end
def method_missing(method_name, *args, &block)
# look for keys...
end
def respond_to_missing?(method_name, _include_all = nil)
# some logic
end
end
确实,它会引发错误:
[1] pry(main)> nil.extend(DotHash)
RuntimeError: must be a hash
但还是添加了逻辑:
[2] pry(main)> nil.foobar
Traceback (most recent call last):
9707: from bin/rails:6:in `<main>'
9706: from /usr/local/bundle/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require'
9705: from /usr/local/bundle/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency'
9704: from /usr/local/bundle/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require'
9703: from /usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
9702: from /usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
9701: from /usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
9700: from /usr/local/bundle/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
... 9695 levels...
4: from /usr/src/app/app/lib/dot_hash.rb:26:in `respond_to_missing?'
3: from /usr/src/app/app/lib/dot_hash.rb:14:in `method_missing'
2: from /usr/src/app/app/lib/dot_hash.rb:26:in `respond_to_missing?'
1: from /usr/src/app/app/lib/dot_hash.rb:14:in `method_missing'
/usr/src/app/app/lib/mapper/dot_hash.rb:26:in `respond_to_missing?': stack level too deep (SystemStackError)
是否有一个钩子会在对象被扩展之前触发,而不是之后?
【问题讨论】: