3

宝石を探しているか、少なくともこの問題に取り組む方法を考えていますが、私が持っているものは正確にはエレガントではありません:)

アイデアは簡単です。次のようなハッシュをマップしたいと思います。

{ :name => 'foo',
  :age  => 15,
  :job => {
        :job_name => 'bar',
        :position => 'something'
    ...
  }
}

クラス (フラットなメンバー構造を持つ) または Struct のオブジェクトには、次のようなものがあります。

class Person {
  @name
  @age
  @job_name
  ...
}

皆さんありがとう。

4

3 に答える 3

1

サブエントリキーがエントリキーを含むことと競合しないことが確実であると仮定すると、動作するはずのコードがいくつかあります...

require 'ostruct'

def flatten_hash(hash)
  hash = hash.dup
  hash.entries.each do |k,v|
    next unless v.is_a?(Hash)
    v = flatten_hash(v)
    hash.delete(k)
    hash.merge! v
  end
  hash
end

def flat_struct_from_hash(hash)
  hash = flatten_hash(hash)
  OpenStruct.new(hash)
end
于 2012-08-13T13:46:02.963 に答える
0

私が使用したソリューションは、同じキー名の問題を解決しますが、フラットなクラス構造を提供しません。idtypeなどの予約された名前の値を処理する必要があることを覚えておいてください。

   require 'ostruct'

   def to_open_struct(element)
     struct = OpenStruct.new
     element.each do |k,v|
       value = Hash === v ? to_open_struct(v) : v
       eval("object.#{k}=value")
     end
     return struct
   end
于 2012-08-13T13:55:14.617 に答える
0

事前に鍵を知っている別の答え

class Job
  attr_accessor :job_name, :position

  def initialize(params = {})
    self.job_name = params.fetch(:job_name, nil)
    self.position = params.fetch(:position, nil)
  end
end

class Person
  attr_accessor :name, :age, :job

  def initialize(params = {})
    self.name = params.fetch(:name, nil)
    self.age = params.fetch(:age, nil)
    self.job = Job.new(params.fetch(:job, {}))
  end
end


hash = { :name => 'foo', :age => 1, :job => { :job_name => 'bar', :position => 'soetmhing' }}
p = Person.new(hash)

p.name
==> "foo"

p.job
==> #<Job:0x96cacd8 @job_name="bar", @position="soetmhing">

p.job.name
==> "bar"
于 2012-08-13T13:56:49.063 に答える