アクセサが好きならばハッシュよりも構造体がよい
Rubyのハッシュのアクセスを手抜きする方法 | おごちゃんの雑文
それはいいんだけど、こいつはJSONをハッシュに変換する。データがアクセス出来れば結局は 何でもいいのだけど、深い階層を持ったデータだとアクセスがなかなか面倒臭い。Rubyで構造 付きのものを扱うのはハッシュにするのが定石らしいのだけど、階層が深くなると面倒になる 。 hash['a']['b']['c'] みたいになるのは、キー入力が厄介。プログラム中でアクセスするのは別にどうってことない のだけど、即値があると面倒。みんなはどうしてるか知らないけど、面倒臭いなーと思ってい た。 そこで、これを、 hash.a.b.c のようにアクセスする方法を考えた。
method_missingはおすすめできない。既存のメソッドとたまたまかぶってしまったらハマる。
アクセサ好きならば構造体がよい。一旦根っこを構造体にしてしまえば、あとは芋蔓式に。ただし、キーが固定されている場合のみ。固定されている場合ならば、タイプミスでエラーが出てくれる。
def Struct(hash) Struct.new(*hash.keys).new(*hash.values.map{|s| Hash === s ? Struct(s) : s}) end obj = Struct(:a => {:b => {:c => { :d => [:foo, :bar, :baz] }}}) obj # => #<struct a=#<struct b=#<struct c=#<struct d=[:foo, :bar, :baz]>>>> obj.a # => #<struct b=#<struct c=#<struct d=[:foo, :bar, :baz]>>> obj.a.b # => #<struct c=#<struct d=[:foo, :bar, :baz]>> obj.a.b.c # => #<struct d=[:foo, :bar, :baz]> obj.a.b.c[0] # => [:foo, :bar, :baz] obj.a.b.c[0][2] # => :baz obj.a.b.c.d[2] # => :baz obj.a.b.c.d = 5 obj.a.b.c.d # => 5 obj.a.b.c # => #<struct d=5> obj.a.b = 77 obj # => #<struct a=#<struct b=77>> obj.a # => #<struct b=77> obj.a.b # => 77
標準ライブラリで定義されているOpenStructはハッシュっぽい構造体で同様にmethod_missingで定義されている。おすすめできない。
require 'ostruct' os = OpenStruct.new os.a = 1 os.a # => 1 os.b = 2 os # => #<OpenStruct a=1, b=2>
Rubyの構造体は萌えるで〜