2012-06-21 26 views
3

比方說,我們有以下YAML結構:有沒有一個內置的訪問嵌套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 
+0

看一看[這](http://ruby-doc.org/stdlib-1.8.6/libdoc/yaml/rdoc/YAML/BaseNode.html)類和第三個例子[這裏]( http://yaml4r.sourceforge.net/doc/page/parsing_yaml_documents.htm)。 –

+0

順便說一句,你可以用'inject' - [gist](https://gist.github.com/9b3955823fbca9185833)做得更好。這是我在其中一個項目中使用的。 –

+0

酷一KL-7 :) – Geo

回答

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 
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 
+0

注意不好:-)如果它也將哈希數組轉換成OpenStruct數組,這對於解析YAML很有用。我只是在我的擴展庫中添加了'Hash#to_ostruct'。 –

相關問題