In Ruby, how can I get instance variables in a hash instead of an array?
Asked Answered
L

5

13

I have a Ruby class. I want to get an instance variable from an argument to a method in that class. I can do get all of the instance variables as an array:

self.instance_variables

However, I want to get the instance variable named arg, specifically:

class MyClass
  def get_instance_variable(arg)
    hash_of_instance_variables[arg]
  end
end

object.get_instance_variable('my_instance_var')

How do I compute hash_of_instance_variables?

Lew answered 13/5, 2010 at 21:15 Comment(2)
Can you elaborate? Your question is not very clear.Mansfield
It looks like you're hoping to build a hash that maps instance variables to their values so that you can retrieve the value of the instance variable. If so, why? Use instance_variable_get.Tarrance
K
25

To create a hash of all instance variables you can use the following code:

class Object
  def instance_variables_hash
    Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
  end
end

But as cam mentioned in his comment, you should use instance_variable_get method instead:

object.instance_variable_get :@my_instance_var
Kaitlynkaitlynn answered 7/12, 2011 at 14:55 Comment(0)
G
13

Question is quite old but found rails solution for this: instance_values

This is first answer in google so maybe it will help someone.

Goblet answered 20/10, 2014 at 13:14 Comment(3)
Thanks for helping the community. I no longer use ruby/rails, moved on to node.js. BestsLew
The code used by Rails is almost identical to the accepted answer with the exception that Rails strips the leading @.Hensel
instance_values worked for me and was simpler. Thanks! (now tested with Rails 6)Circumsolar
S
1
class MyClass    
def variables_to_hash
      h = {}
      instance_variables.each{|a|
        s = a.to_s
        n = s[1..s.size]
        v = instance_variable_get a
        h[n] = v
      }
      h
    end
end
Sibilant answered 7/12, 2011 at 14:5 Comment(1)
Note that s[1..s.size] can be replaced with s[1..-1].Hensel
H
0

For Ruby 2.6+, you can pass a block to the to_h method, leading to very DRY syntax:

# Some instance variables
instance_variable_set(:@a, 'dog')
#=> "dog"
instance_variable_set(:@b, 'cat')
#=> "cat"

# Array of instance variable names
instance_variables
#=> [:@a, :@b]

# Hash of instance variable names and values, including leading @
instance_variables.to_h { |k| [k, instance_variable_get(k)] }
#=> { :@a => "dog", :@b => "cat" }

# Hash of instance variable names and values, excluding leading @
instance_variables.to_h { |k| [k[1..-1].to_sym, instance_variable_get(k)] }
#=> { :a => "dog", :b => "cat" }
Helbonnas answered 20/12, 2022 at 6:34 Comment(0)
P
-1

Ruby on Rails has a couple of built-in ways to do this that you might find meet your needs.

user = User.new(first: 'brian', last: 'case')

user.attributes

{"first"=>"brian", "last"=>"case"}

user.serializeable_hash

{"first"=>"brian", "last"=>"case"}

Pentarchy answered 25/3, 2016 at 22:59 Comment(1)
This only applies to Rails models (instances of ActiveRecord::Base). For an arbitrary Ruby object, @sufleR's answer works.Delvalle

© 2022 - 2024 — McMap. All rights reserved.