【问题标题】:Is there a builtin to access a nested yaml string?是否有内置函数可以访问嵌套的 yaml 字符串?
【发布时间】:2012-06-21 11:50:29
【问题描述】:

假设我们有以下 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

【问题讨论】:

  • 看看this类和第三个例子here
  • 顺便说一句,inject - gist 可以做得更好。这就是我在其中一个项目中使用的。
  • 你看过YAML中的YPath方法吗?我看起来像一个强大的东西,但我怀疑我自己会转向它。

标签: ruby-on-rails ruby yaml


【解决方案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

【讨论】:

    【解决方案2】:

    我在我的扩展库中使用它:

    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
    

    【讨论】:

    • 注意不好 :-) 如果它还将散列数组转换为 OpenStructs 数组,这对于解析 YAML 很有用。我刚刚在我的扩展库中添加了 Hash#to_ostruct
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    相关资源
    最近更新 更多