Reputation: 593
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...
Upvotes: 59
Views: 51840
Reputation: 11
If you run byebug you can run simply run instance_variables
to get the list generated at runtime.
Might be a new feature. Running ruby 3.2.2
Upvotes: 0
Reputation: 6237
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.
Upvotes: 0
Reputation: 16373
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}
Upvotes: 1
Reputation: 11
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') }
Upvotes: 1
Reputation: 1771
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 }]
Upvotes: 18
Reputation: 96934
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]
Upvotes: 88