トップ 最新 追記 RDF

雄也の?日坊主日記


2007-05-06

_ [Ruby] Hash#to_struct

YAMLから読み込んだ設定値(ハッシュ)をメソッドでアクセスするような目的で再帰的にした.

ちょっと思いついたので書いてみたが...ハッシュのインスタンスメソッドである必要はないかも...

Hash#structuralizeも考えたが,打鍵数が短いこともあってHash#to_structにした.

module CoreExtensions
  module Hash
    module Conversions
      def to_struct(recursively = true)
        if recursively
          return inject({}) { |result, (key, value)|
            if value.respond_to?(:to_struct)
              value = value.to_struct
            end
            result[key] = value
            result
          }.to_struct(false)
        else
          k = keys
          result_class = Struct.new(nil, *k.collect { |key| key.to_sym })
          return result_class.new(*k.collect { |key| self[key] })
        end
      end
    end
  end
end

class Hash
  include CoreExtensions::Hash::Conversions
end

if __FILE__ == $0
  require "test/unit"

  class HashToStructTest < Test::Unit::TestCase
    def test_to_struct__recursive
      o = {
        "abc" => 10,
        :def => "ghi",
        "jkl" => {
          :mno => true,
          "10" => false,
        },
      }.to_struct
      assert_equal(10, o.abc)
      assert_equal("ghi", o.def)
      assert_equal(true, o.jkl.mno)
      assert_equal(false, o.jkl["10"])
    end

    def test_to_struct__not_recursive
      base = {
        "abc" => 10,
        :def => "ghi",
        "jkl" => {
          :mno => true,
          "10" => false,
        },
      }
      o = base.to_struct(false)
      assert_equal(10, o.abc)
      assert_equal("ghi", o.def)
      assert_raise(NoMethodError) do
        assert_equal(true, o.jkl.mno)
      end
      assert_equal(base["jkl"], o.jkl)
    end
  end
end

2004|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|
2006|05|
2007|04|05|09|10|11|
2008|04|05|08|10|11|
2009|02|03|04|05|06|07|08|09|10|11|
2010|02|03|04|07|10|
2011|04|08|
2012|02|10|
2014|05|06|08|
2018|03|
楽天で探す
楽天市場
キーワードから探す
楽天トラベル