2009-08-04 20 views
2

"core.username"や "core.servers"のようなキーを持っていたRubyの設定クラスは、まさにそのようなYAMLファイルに格納されています。ネストされたハッシュの値を変更する

私はそれを入れ子にするように変更しようとしていますが、古い方法でキーを参照するすべての場所を変更する必要はありません。私は読者-方法でそれを管理している:

def [](key) 
    namespace, *rest = key.split(".") 

    target = @config[namespace] 
    rest.each do |k| 
    return nil unless target[k] 
    target = target[k] 
    end 

    target 
end 

しかし、私は働くライタークラスと同じことをしようとしたが、@config -hashに設定されていない場合。 @configは、YAML.load_file

evalと一緒に働くことができましたが、それは私が長く保管しておきたいことではありません。

def []=(key, value) 
    namespace, *rest = key.split(".") 

    target = "@config[\"#{namespace}\"]" 
    rest.each do |key| 
    target += "[\"#{key}\"]" 
    end 

    eval "#{target} = value" 
    self[key] 
end 

これを達成するための適切な方法はありますか?プラグインとコードは一切変更しないことが望ましいですか?

答えて

1
def []=(key, value) 
    subkeys = key.split(".") 
    lastkey = subkeys.pop 
    subhash = subkeys.inject(@config) do |hash, k| 
    hash[k] 
    end 
    subhash[lastkey] = value 
end 

編集:分割を修正しました。 PS:もしあなたが好きなら、[]メソッドのように注入を個々のループに置き換えることもできます。重要なことは、最後のキーで[]を呼ぶのではなく、[] =を使って値を設定することです。

+0

あなたは上の分割を忘れていました ""スペースの代わりに、しかしそれ以外のものは、魅力のように機能します。ありがとう! –

0

私は、再帰を使用:

def change(hash) 
    if hash.is_an? Hash 
    hash.inject({}) do |acc, kv| 
     hash[change(kv.first)] = change(kv.last) 
     hash 
    end 
    else 
    hash.to_s.split('.').trim # Do your fancy stuff here 
    end 
end 
関連する問題