Elegant way to add to_hash (or to_h) method in Struct?

I use Struct instead of a simple Hash in the project to provide a semantic name for the collection of value pairs. However, when I built the structure, I need to output a hash value. I'm in Ruby 1.9.3. Example:

MyMeaninfulName = Struct.new(:alpha, :beta, :gamma) do
  def to_hash
    self.members.inject({}) {|h,m| h[m] = self[m]; h}
  end
end

my_var = MyMeaningfulName.new
my_var.to_hash # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 

Is there a reason why Struct does not include the to_hash method? This looks like a natural form, but perhaps there is a main reason why it is not included.

Secondly, is there a more elegant way to create a general to_hash method in Struct (usually through monkeypatching, and through module or inheritance).

+5
source share
4 answers

Try the following:

class Struct
  old_new = self.method(:new)
  def self.new(*args) 
    obj = old_new.call(*args)
    obj.class_exec do
      def to_hash
        self.members.inject({}) {|h,m| h[m] = self[m]; h}
      end
    end
    return obj
  end
end
0
source

, ruby ​​1.9.3, ruby ​​2.0.0 Struct to_h .

MyMeaningfulName = Struct.new(:alpha, :beta, :gamma)

my_var = MyMeaningfulName.new
my_var.to_h # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 
+3

or that:

class Struct
  def to_hash
    self.class.members.inject({}) {|h,m| h[m] = self[m]}
  end
end

(note the extra class for member access)

+2
source

I do not know why, this seems obvious. Fortunately, you can use it as a hash in many places, as it implements parenthesis operators.

Anyway, it's pretty elegant:

MyMeaningfulName = Struct.new :alpha, :beta, :gamma do
  def to_hash
    Hash[members.zip values]
  end
end

my_var = MyMeaningfulName.new 1, 2, 3
my_var.to_hash # => {:alpha=>1, :beta=>2, :gamma=>3}
+2
source

All Articles