Get all instance variables declared in class

Ruby

Ruby Problem Overview


Please help me get all instance variables declared in a class the same way instance_methods shows me all methods available in a class.

class A
  attr_accessor :ab, :ac
end

puts A.instance_methods  #gives ab and ac

puts A.something         #gives me @ab @ac...

Ruby Solutions


Solution 1 - Ruby

You can use instance_variables:

A.instance_variables

but that’s probably not what you want, since that gets the instance variables in the class A, not an instance of that class. So you probably want:

a = A.new
a.instance_variables

But note that just calling attr_accessor doesn’t define any instance variables (it just defines methods), so there won’t be any in the instance until you set them explicitly.

a = A.new
a.instance_variables #=> []
a.ab = 'foo'
a.instance_variables #=> [:@ab]

Solution 2 - Ruby

If you want to get all instances variables values you can try something like this :

class A
  attr_accessor :foo, :bar

  def context
    self.instance_variables.map do |attribute|
      { attribute => self.instance_variable_get(attribute) }
    end
  end
end

a = A.new
a.foo = "foo"
a.bar = 42
a.context #=> [{ :@foo => "foo" }, { :@bar => 42 }]

Solution 3 - Ruby

It's not foolproof - additional methods could be defined on the class that match the pattern - but one way I found that has suited my needs is

A.instance_methods.grep(/[a-z_]+=/).map{ |m| m.to_s.gsub(/^(.+)=$/, '@\1') }

Solution 4 - Ruby

If you want to get a hash of all instance variables, in the manner of attributes, following on from Aschen's answer you can do

class A
  attr_accessor :foo, :bar

    def attributes
    self.instance_variables.map do |attribute|
      key = attribute.to_s.gsub('@','')
      [key, self.instance_variable_get(attribute)]
    end.to_h
  end
end
a = A.new
a.foo = "foo"
a.bar = 42
a.context #=> {'foo' => 'foo', 'bar' => 42}

Solution 5 - Ruby

Building on the answer from @Obromios , I added .to_h and .to_s to a class to allow for pleasant, flexible dumping of attributes suitable for display to an end user.

This particular class (not an ActiveRecord model) will have a variety of attributes set in different situations. Only those attribs that have values will appear when printing myvar.to_s, which was my desire.

class LocalError
  attr_accessor :product_code, :event_description, :error_code, :error_column, :error_row 

  def to_h
    instance_variables.map do |attribute|
      key = attribute.to_s.gsub('@', '')
      [key, self.instance_variable_get(attribute)]
    end.to_h
  end

  def to_s
    to_h.to_s
  end
end

This allows me to put this simple code in a mailer template:

Data error:   <%= @data_error %>

And it produces (for example):

Data error:   {"event_description"=>"invalid date", "error_row"=>13}

This is nice, as the mailer doesn't have to be updated as the LocalError attributes change in the future.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAkshay VishnoiView Question on Stackoverflow
Solution 1 - RubyAndrew MarshallView Answer on Stackoverflow
Solution 2 - RubyAschenView Answer on Stackoverflow
Solution 3 - RubyAdam StricklandView Answer on Stackoverflow
Solution 4 - RubyObromiosView Answer on Stackoverflow
Solution 5 - RubyDavid HempyView Answer on Stackoverflow