3

次のYAML構造があるとしましょう。

books:
  book_one: "Some name"
  book_two: "Some other name"

次のようにファイルをロードすると、次のようになります。

f = YAML.load_file("my.yml")

book_one次のようにアクセスできますf["books"]["book_one"]books.book_oneのような文字列を受け入れて同じ値を返すことができるビルトインはありますか?

編集:これは私がこれまでに持っているものであり、それはうまくいくようです:

  ...
  @yfile = YAML.load_file("my.yml")
  ...


  def strings_for(key)
    key_components = key.split(".")
    container      = @yfile
    key_components.each_with_index do |kc,idx|
      if container && container.kind_of?(Hash) && container.keys.include?(kc)
        container  = container[kc]
      else
        container = nil
      end
    end
    container
  end
4

2 に答える 2

1

そのためにOpenStructと再帰関数を使用できます。次のようになります。

require 'ostruct'

def deep_open_struct(hash)
  internal_hashes = {}
  hash.each do |key,value|
    if value.kind_of?( Hash )
      internal_hashes[key] = value
    end
  end
  if internal_hashes.empty?
    OpenStruct.new(hash)
  else
    duplicate = hash.dup
    internal_hashes.each do |key,value|
      duplicate[key] = deep_open_struct(value)
    end
    OpenStruct.new(duplicate)
  end
end

f = YAML.load_file('my.yml')
struct = deep_open_struct(f)
puts struct.books.book_one
于 2012-06-21T12:01:31.207 に答える
1

私は拡張ライブラリでこれを使用します:

class OpenStruct
  def self.new_recursive(hash)
    pairs = hash.map do |key, value|
      new_value = value.is_a?(Hash) ? new_recursive(value) : value
      [key, new_value]
    end
    new(Hash[pairs])
  end
end

実際に:

struct = OpenStruct.new_recursive(:a => 1, :b => {:c => 3})
struct.a #=> 1
struct.b.c #=> 3
于 2012-06-21T12:35:30.197 に答える