#[]
関心のあるインスタンスにカスタムメソッドを注入するアプローチを提案します。
def weaken_checks_for_brackets_accessor inst
inst.instance_variable_set(:@original_get_element_method, inst.method(:[])) \
unless inst.instance_variable_get(:@original_get_element_method)
singleton_class = class << inst; self; end
singleton_class.send(:define_method, :[]) do |*keys|
begin
res = (inst.instance_variable_get(:@original_get_element_method).call *keys)
rescue
end
weaken_checks_for_brackets_accessor(res.nil? ? inst.class.new : res)
end
inst
end
ハッシュのインスタンスで呼び出されると(配列は他のすべてのクラスと同様にOKであり、#[]
定義されています)、このメソッドは、Hash#[]
既に置換されていない限り(複数の呼び出し中のスタックオーバーフローを防ぐために必要です)、元のメソッドを格納します。次に、カスタム実装を挿入します。メソッドの#[]
、nil/exceptionの代わりに空のクラスインスタンスを返します。安全な値の取得を使用するには:
a = { 'foo' => { 'bar' => [1, 2, 3] } }
p (weaken_checks_for_brackets_accessor a)['foo']['bar']
p "1 #{a['foo']}"
p "2 #{a['foo']['bar']}"
p "3 #{a['foo']['bar']['ghgh']}"
p "4 #{a['foo']['bar']['ghgh'][0]}"
p "5 #{a['foo']['bar']['ghgh'][0]['olala']}"
降伏:
#⇒ [1, 2, 3]
#⇒ "1 {\"bar\"=>[1, 2, 3]}"
#⇒ "2 [1, 2, 3]"
#⇒ "3 []"
#⇒ "4 []"
#⇒ "5 []"