Reimond Hill
Reimond Hill

Reputation: 4760

Converting a class into a hash in Ruby

I am trying to convert any class into a hash using ruby. The initial implementation I have done:

class Object
    def to_hash
        instance_variables.map{ |v| 
            Hash[v.to_s.delete("@").to_sym, instance_variable_get(v)] }.inject(:merge)
   end
end

Everything seemed to work ok. But when I tried the following code:

class Person
    attr_accessor :name, :pet
    def initialize(name, pet)
       @name = name
       @pet = pet
    end
end

class Pet
    attr_accessor :name, :age 
    def initialize(name, age)
       @name = name
       @age = age
    end
end


tom =  Person.new("Tom", Pet.new("Tobby", 5))
puts tom.to_hash

I have got the following output

{:name=>"Tom", :pet=>#<Pet:0x0055ff94072378 @name="Tobby", @age=5>}

I am unable to hash the attribute pet of type Pet (or any other custom class)

Any ideas?

Edit That's what I would expect to be returned:

{:name=>"Tom", :pet=>{ :name=>"Tobby", :age=>5}}

Upvotes: 0

Views: 541

Answers (1)

spickermann
spickermann

Reputation: 106812

When you want to have associated objects to be returned as a hash too hen you have to call to_hash recursively:

class Object
  def to_hash
    return self if instance_variables.empty?

    instance_variables
      .map { |v| [v.to_s.delete("@").to_sym, instance_variable_get(v).to_hash] }
      .to_h
  end
end

tom =  Person.new("Tom", Pet.new("Tobby", 5))
puts tom.to_hash
#=> { :name=>"Tom", :pet => { :name=>"Tobby", :age=>5 } }

Upvotes: 5

Related Questions