Rubyでハッシュを構造体に変換するにはどうすればよいですか?
これを考えると:
h = { :a => 1, :b => 2 }
次のような構造体が必要です。
s.a == 1
s.b == 2
Rubyでハッシュを構造体に変換するにはどうすればよいですか?
これを考えると:
h = { :a => 1, :b => 2 }
次のような構造体が必要です。
s.a == 1
s.b == 2
すでに構造体が定義されていて、インスタンスをハッシュでインスタンス化したい場合:
Person = Struct.new(:first_name, :last_name, :age)
person_hash = { first_name: "Foo", last_name: "Bar", age: 29 }
person = Person.new(*person_hash.values_at(*Person.members))
=> #<struct Person first_name="Foo", last_name="Bar", age=29>
特にである必要がなくStruct
、代わりに である場合OpenStruct
:
pry(main)> require 'ostruct'
pry(main)> s = OpenStruct.new(h)
=> #<OpenStruct a=1, b=2>
pry(main)> puts s.a, s.b
1
2
Ruby 1.9以降ではハッシュキーの順序が保証されているため:
Struct.new(*h.keys).new(*h.values)
以下は、信頼できる方法でハッシュから構造体を作成します (Ruby ではハッシュの順序が保証されていないため)。
s = Struct.new(*(k = h.keys)).new(*h.values_at(*k))
値を構造体の適切な順序にマップする例を次に示します。
require 'securerandom'
Message = Struct.new(:to, :from, :message, :invitee)
message_params = {from: "my@email.address", to: "your@email.address",
invitee: SecureRandom.uuid, message: "hello"}
if Message.members.sort == message_params.keys.sort
# Do something with the return struct object here
Message.new *Message.members.map {|k| message_params[k] }
else
raise "Invalid keys for Message"
end
次のコードを使用して、ハッシュから構造体に変換できます。
Struct.new(*my_hash.keys.map(&:to_sym)).new(*my_hash.values)
文字列キーでエラーが発生するため、すべてのキーをシンボルに変換してください。NameError: identifier my_key needs to be constant
これは非常に強力なアクションであるため、個人的には Hash クラスにモンキー パッチを追加することをお勧めします。
# config/initializers/core_extensions.rb
Hash.class_eval do
def to_struct
Struct.new(*keys.map(&:to_sym)).new(*values)
end
end