Goal
-
hash['key']
ではなく、hash.key
でアクセスさせる - クラス拡張の影響を特定の範囲内におさえるため、Hashクラス拡張せずに対応する
- hashインスタンスに拡張モジュールをextendする
Code
hash_ext.rb
require 'pp'
module HashExtension
def method_missing(method, *params)
if method.to_s[-1,1] == "="
# シンボルキーに優先的に書き込む
key = method.to_s[0..-2].gsub(':', '')
key = self.has_key?(key.to_sym) ? key.to_sym :
( self.has_key?(key.to_s) ? key.to_s : key.to_sym )
self[key] = params.first
else
# シンボルキーとストリングキー両方存在する場合、
# シンボルキーを優先的に返す
key = self.has_key?(method.to_sym) ? method.to_sym : method.to_s
self[key]
end
end
end
hash1 = { name: 'Isaac Newton', age: 372 }
hash2 = { name: 'Carolus Fridericus Gauss', age: 237 }
##
## hash1のオブジェクトのみmethod_missing機能拡張する
##
hash1.extend HashExtension
##
## hash1オブジェクトはメソッドよびだしでハッシュ要素にアクセスできるが、
## HashExtensionをextendしていないhash2オブジェクトには拡張の影響が及んでいないことを確認
##
p hash1.name
# "Isaac Newton"
p hash2.name
# hash_ext.rb:17:in `<main>': undefined method `name' for {:name=>"Carolus Fridericus Gauss", :age=>237}:Hash (NoMethodError)
##
## 代入時はキーが存在すれば上書き、存在しなければ追加することを確認
##
hash1.name = "Sir Isaac Newton"
hash1.role = "physicist"
pp hash1
# {:name=>"Sir Isaac Newton", :age=>372, :role=>"physicist"}
Environment
% uname -a
Linux *** 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
% ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
% cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m