2013-02-06 65 views
6

我爲廚師屬性中的服務生成配置。然而,在某些時候,我需要將屬性mash變成一個簡單的ruby哈希。這用於在廚師10中工作良好:廚師11:任何將屬性變成紅寶石散列的方法?

node.myapp.config.to_hash 

但是,從廚師11開始,這是行不通的。只有屬性的頂層被轉換爲散列,然後嵌套值保留不可變的mash對象。修改它們會導致類似的錯誤:

Chef :: Exceptions :: ImmutableAttributeModification ---------------------------- --------------------當您沒有指定要設置的優先級別時,節點屬性是隻讀的。要 設置屬性利用代碼,比如`node.default [「鑰匙」] =「值」」

我已經嘗試了一堆的方式來解決這個問題,它不工作:

node.myapp.config.dup.to_hash 
JSON.parse(node.myapp.config.to_json) 

的JSON解析黑客攻擊,這似乎像它應該工作的偉大,在結果:

JSON::ParserError 
unexpected token at '"#<Chef::Node::Attribute:0x000000020eee88>"' 

是否有任何實際可靠的方式,總之包括每個食譜嵌套解析功能,屬性轉換爲簡單的,普通,去吧od老紅寶石哈希?

+1

爲什麼需要哈希? –

+0

我不需要它 - 我可以放棄任何我想要的時間!但嚴重的是,我正在構建一個配置文件出了很多不同的屬性,我需要修改它們,然後將它們寫入配置文件。將屬性轉換爲散列,對它們進行變異,然後使用散列是非常有用的。 –

回答

7

後一個響亮的回答缺乏的都在這裏和Opscode公司廚師郵件列表上,我結束了使用下面的技巧:

class Chef 
    class Node 
    class ImmutableMash 
     def to_hash 
     h = {} 
     self.each do |k,v| 
      if v.respond_to?('to_hash') 
      h[k] = v.to_hash 
      else 
      h[k] = v 
      end 
     end 
     return h 
     end 
    end 
    end 
end 

我要把它放到我的菜譜目錄庫;現在我可以在這兩個廚師10使用attribute.to_hash(已經工作正常並且通過這種猴子補丁不受影響)和廚師11.我也報這個bug到Opscode公司:

如果你不」我想告訴你這個問題: http://tickets.opscode.com/browse/CHEF-3857

+0

順便說一句,如果你的散列包含數組,那麼這是行不通的 – David

+1

更新了一個似乎可以與數組一起工作的版本。 – David

+0

我無法接受David的建議編輯,所以我將其做了一個要點:https://gist.github。com/igor47/5997028;我沒有必須克服嵌套數組的問題,但它肯定會成爲一個問題。 –

-1

上面的答案有點不必要。你可以這樣做:

json = node[:whatever][:whatever].to_hash.to_json 
JSON.parse(json) 
+0

這是不正確的;因爲'to_hash'很淺,你最終會以'ImmutableMash'對象作爲值。 'to_json'函數不知道如何處理這種類型的對象,並將barf。這是這個問題的重點。 –

2

我有同樣的問題,經過大量黑客周圍想出了這個:

json_string = node[:attr_tree].inspect.gsub(/\=\>/,':') 
my_hash = JSON.parse(json_string, {:symbolize_names => true}) 

檢查並提出了從其他方法缺失的深層解析和我最後得到一個散列,我可以根據需要修改和傳遞。

+0

對於1-liner,'''JSON.parse(hash.to_json,symbolize_names:true)'''。相當邪惡,但比更復雜的解決方案更容易維護。 – Afforess

1

我希望我不是太晚了黨但空哈希合併節點對象爲我做:

chef (12.6.0)> {}.merge(node).class 
=> Hash