2013-02-06 39 views
6

Tôi đang tạo cấu hình cho dịch vụ của mình trong thuộc tính đầu bếp. Tuy nhiên, tại một số điểm, tôi cần phải biến thuộc tính mash thành một băm ruby ​​đơn giản. Điều này được sử dụng để làm việc tốt trong Chef 10:đầu bếp 11: bất kỳ cách nào để biến các thuộc tính thành một băm ruby?

node.myapp.config.to_hash 

Tuy nhiên, bắt đầu với đầu bếp 11, điều này không hoạt động. Chỉ có cấp cao nhất của thuộc tính được chuyển đổi thành băm, sau đó các giá trị lồng nhau còn lại các đối tượng mash không thể thay đổi được. Sửa đổi chúng dẫn đến các lỗi như sau:

Đầu bếp :: Ngoại lệ :: ImmutableAttributeModification ---------------------------- -------------------- Thuộc tính nút là chỉ đọc khi bạn không chỉ định mức ưu tiên nào được đặt. Để thiết lập một mã sử dụng thuộc tính như `node.default [ "key"] = "giá trị"'

Tôi đã thử một loạt các cách để có được xung quanh vấn đề này mà không có tác dụng:

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

các json phân tích cú pháp hack, mà có vẻ như nó nên làm việc lớn, kết quả trong:

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

có cách nào đáng tin cậy thực tế, viết tắt của bao gồm một chức năng phân tích lồng nhau trong mỗi sách dạy nấu ăn, để chuyển đổi thuộc tính cho một đơn giản , bình thường, đi od ruby ​​cũ băm?

+1

Tại sao bạn cần băm? –

+0

tôi không cần nó - tôi có thể bỏ bất cứ lúc nào tôi muốn! nhưng nghiêm túc, tôi đang xây dựng một tập tin cấu hình ra khỏi rất nhiều thuộc tính khác nhau, và tôi cần phải sửa đổi chúng trước khi viết chúng vào tập tin cấu hình. nó thực sự hữu ích để chuyển đổi các thuộc tính thành một băm, thay đổi chúng, và sau đó sử dụng băm. –

Trả lời

7

sau một thiếu vang dội của câu trả lời cả hai ở đây và trên mailing list Opscode đầu bếp, tôi đã kết thúc sử dụng hack như sau:

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 

tôi đặt này vào thư viện dir trong sách dạy nấu ăn của tôi; bây giờ tôi có thể sử dụng attribute.to_hash trong cả hai đầu bếp 10 (mà đã làm việc đúng cách và không bị ảnh hưởng bởi miếng vá khỉ này) và đầu bếp 11. Tôi cũng đã báo cáo điều này như một lỗi để opscode:

nếu bạn don ' t muốn phải khỉ-vá đầu bếp của bạn, nói lên về vấn đề này: http://tickets.opscode.com/browse/CHEF-3857

+0

BTW điều này không hoạt động nếu băm của bạn chứa mảng – David

+1

Cập nhật với phiên bản có vẻ hoạt động với các mảng. – David

+0

Tôi không thể chấp nhận chỉnh sửa được đề xuất của David, vì vậy tôi đã thực hiện một ý chính: https: //gist.github.com/igor47/5997028; tôi đã không phải khắc phục vấn đề của mảng lồng nhau, nhưng nó chắc chắn sẽ là một vấn đề. –

-1

Câu trả lời trên là một chút không cần thiết. Bạn chỉ có thể làm điều này:

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

điều này không đúng; bởi vì 'to_hash' là nông, bạn sẽ kết thúc với các đối tượng' ImmutableMash' làm giá trị. hàm 'to_json' không biết cách xử lý kiểu đối tượng này và sẽ làm việc như thế nào. đó là toàn bộ vấn đề của câu hỏi này. –

2

tôi đã cùng một vấn đề và sau nhiều hacking xung quanh đến với điều này:

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

kiểm tra nào để phân tích sâu mà là mất tích từ các phương pháp khác được đề xuất và tôi kết thúc với một băm mà tôi có thể sửa đổi và vượt qua xung quanh khi cần thiết.

+0

Đối với một lớp lót, '' 'JSON.parse (hash.to_json, symbolize_names: true)' ''. Khá xấu, nhưng dễ bảo trì hơn các giải pháp phức tạp hơn. – Afforess

1

Tôi hy vọng tôi không phải là quá muộn để dự buổi tiệc nhưng việc sáp nhập các đối tượng nút với một băm trống đã làm nó cho tôi:

chef (12.6.0)> {}.merge(node).class 
=> Hash 
Các vấn đề liên quan