これは私の問題です。私はAndrea Pavoniのネストされたハッシュを使ってクラスを初期化することができます。Ruby:ネストされたハッシュといくつかの既定の既定値を持つRubyクラスを初期化します
オリジナルの挙動デフォルトなし(上で次のように動作がなるよう
require 'ostruct'
class DeepStruct < OpenStruct
def initialize(hash=nil)
@table = {}
@hash_table = {}
if hash
hash.each do |k,v|
@table[k.to_sym] = (v.is_a?(Hash) ? self.class.new(v) : v)
@hash_table[k.to_sym] = v
new_ostruct_member(k)
end
end
end
def to_h
@hash_table
end
end
しかし、私は、特定のデフォルト値を持つ(クラス)のハッシュを含める方法を見つけることができませんコード):
default_h = {a: {dc: 2}, dd: {de: 4}}
:クラス内で定義された次default_hで
input_hash = {a: {b: 1}}
new_object = DeepStruct.new hash
new_object.a # => #<DeepStruct b=1>
new_object.a.b # => 1
new_object.a.to_h # => {b: 1}
デフォルトのハッシュと (実際には、ネストされたハッシュのためdeep_mergeを使用して)
{:a=>{:dc=>2, :b=>1}, :dd=>{:de=>4}}
行動を次のように10
input_hashとdefault_hはマージする必要がありますする必要があります:
new_object = DeepStruct.new hash
new_object.a.b # => 1
new_object.a.dc # => 2
new_object.a.to_h # => {:dc=>2, :b=>1}
私は方法を見つけることができませんクラス内でこの動作を実装します。私は本当にこの問題の助けを感謝します。
編集:今すぐクラスにDavidのコードを使用しようとしている:
class CompMedia
require 'ostruct'
attr_accessor :merged_h
def initialize(hash)
defaults = {a: {dc: 2}, dd: {de: 4}}
@merged_h = {}
deep_update(merged_h, defaults)
deep_update(merged_h, hash)
@merged_h
end
def deep_update(dest, src)
src.each do |key, value|
if value.is_a?(Hash)
dest[key] = {} if !dest[key].is_a?(Hash)
deep_update(dest[key], value)
else
dest[key] = value
end
end
end
def deep_open_struct(hash)
result = OpenStruct.new
hash.each do |key, value|
if value.is_a?(Hash)
result[key] = deep_open_struct(value)
else
result[key] = value
end
end
result
end
end # class CompMedia
input_hash = {a: {b: 1}}
cm = CompMedia.new(input_hash)
object = cm.deep_open_struct(cm.merged_h)
p object.marshal_dump # {:a=>#<OpenStruct dc=2, b=1>, :dd=>#<OpenStruct de=4>}
p object.a # <OpenStruct dc=2, b=1>
p object.a.marshal_dump # {:dc=>2, :b=>1}
p object.a.b # 1
p object.a.dc # 2
p object.dd # <OpenStruct de=4>
を明らかに、私は簡単な方法でopenstructオブジェクトからネストされたハッシュの要素を取得する方法を発見していません。 私の目的は、クラスに含まれるデフォルト(ネストされた)ハッシュと(ネストされた)入力ハッシュで初期化されるクラスを作成することです。また、クラス内でハッシュを処理するメソッドを追加できるようにしたい。私はまだそこにいません。誰かが使ってコードを作ることができない限り、私は私の解決策として最後のバージョンを検討する
class CompMedia
attr_accessor :merged_h
def initialize(hash)
defaults = {a: {dc: 2}, dd: {de: 4}}
@merged_h = {}
deep_update(merged_h, defaults)
deep_update(merged_h, hash)
@merged_h
end
def deep_update(dest, src)
src.each do |key, value|
if value.is_a?(Hash)
dest[key] = {} if !dest[key].is_a?(Hash)
deep_update(dest[key], value)
else
dest[key] = value
end
end
end
def multiply_by(k)
merged_h[:a][:dc] * k
end
end
input_hash = {a: {b: 1}}
cm = CompMedia.new(input_hash)
p cm.merged_h # {:a=>{:dc=>2, :b=>1}, :dd=>{:de=>4}}
p cm.merged_h[:a] # {:dc=>2, :b=>1}
p cm.merged_h[:a][:dc] # 2
p cm.merged_h[:dd] # {:de=>4}
p cm.multiply_by(10) # 20
:
一方、私はマージされたハッシュを使用することができ、これは少し面倒な表記でいえ働くだろう私が望むOpenStructの仕事。
これはうまくいきますが、デフォルトのハッシュを含むクラスが必要で、マージされたハッシュ(デフォルト+入力)で初期化されている必要があります。その理由は、ハッシュの内容を処理するメソッドを追加したいからです。私はあなたのコードでそれに取り組んでおり、何かを見つけたら投稿します。なぜOpenStructをサブクラス化するのが悪い考えですか? – JMor
デフォルトのハッシュを保持するクラスを持つのは難しくありません。コードをそのままこの投稿に残して、内部的に使用するクラスを作成することができます。 –
私はそれをしました。しかし、私は、マージされたハッシュにアクセスするクラスのメソッドに苦労しています。 – JMor