RubyのHash、僕が知らなかっただけかもしれないですが、便利な使い方を発見。
initializeでブロックを渡す
ブロックを渡すと、 []
でアクセスした時にそのブロックが評価されるようになります。
使用例:
require 'uri'
uri = Hash.new do |hash, key|
puts 'evaluated'
hash[key] = URI.parse(key) rescue nil
end
host = uri['http://google.com'].host
#=> evaluated
puts host
#=> google.com
host = uri['http://google.com'].host
#=>何も出力されない
puts host
#=> google.com
p uri
#=> {"http://google.com"=>#<URI::HTTP:0x0000010718edb0 URL:http://google.com>}
key
に対するアクセスに対して、自身にその key
がセットされていなければブロックを評価、ブロックには自身の hash
も渡されるので、 hash
にsetすることもできる。
コレ結構便利で、例えばDBへの処理を、同じクエリに対して複数行わないように結果をキャッシュするといった時、
require 'mysql2'
client = Mysql2::Client.new
db = Hash.new do |data, sql|
data[sql] = client.query(sql).to_a
end
# example
# 一回目はクエリが走る
user = db['SELECT * from users where id = 1']
# 二回めはクエリが走らない
user = db['SELECT * from users where id = 1']
みたいなことが可能です。
もう1年くらいrubyやってるのに知らなかった…