How do I pass the name of an instance variable into an object?


#1

Hi,

Suppose I wanted to create a method for an object that allowed me to
pass in the name of an instance variable and to perform some task on the
variable. For the sake of simplicity, let’s say that I’d like to be
able to print out the value of the specified instance variable. Also,
I’d want the method to raise an exception if the name of the variable
getting passed into the object is not actually an instance variable in
the object.

The class would look something like this:

class SomeClass
def initialize
@a = 1
@b = ‘xxx’
end

def print_instance_variables(obj)
# some code goes here
end
end

And here’s how I’d like to be able to use it:

x = SomeClass.new
x.print_instance_variables(:a) # writes the value of @a to the console
x.print_instance_variables(:b) # writes the value of @b to the console
x.print_instance_variables(:a, :b) # writes the values of @a and @b to
the console
x.print_instance_variables(:z) # causes an exception because there is
no@z

Any suggestions would be greatly appreciated.

Thanks,

Glenn


#2

Glenn,

There may be a much better way to do this, but here’s what I threw
together:

class SomeClass
attr_accessor :a, :b
def initialize
@a = ‘A’
@b = ‘B’
end

def print_instance_variable(variable)
if instance_variables.include?("@#{variable}")
puts self.send("#{variable}")
else
raise ‘Not an instance variable.’
end
end
end

x = SomeClass.new
x.print_instance_variable(‘a’)

Hope that at least points you in the right direction.

– Josh
http://iammrjoshua.com

Glenn wrote:

Hi,

Suppose I wanted to create a method for an object that allowed me to
pass in the name of an instance variable and to perform some task on the
variable. For the sake of simplicity, let’s say that I’d like to be
able to print out the value of the specified instance variable. Also,
I’d want the method to raise an exception if the name of the variable
getting passed into the object is not actually an instance variable in
the object.

The class would look something like this:

class SomeClass
def initialize
@a = 1
@b = ‘xxx’
end

def print_instance_variables(obj)
# some code goes here
end
end

And here’s how I’d like to be able to use it:

x = SomeClass.new
x.print_instance_variables(:a) # writes the value of @a to the console
x.print_instance_variables(:b) # writes the value of @b to the console
x.print_instance_variables(:a, :b) # writes the values of @a and @b to
the console
x.print_instance_variables(:z) # causes an exception because there is
no@z

Any suggestions would be greatly appreciated.

Thanks,

Glenn


#3

Thanks Greg! Much nicer than what I threw together.

– Josh
http://iammrjoshua.com

Greg D. wrote:

On Wed, Dec 31, 2008 at 9:18 PM, Glenn removed_email_address@domain.invalid wrote:

end
x.print_instance_variables(:b) # writes the value of @b to the console
x.print_instance_variables(:a, :b) # writes the values of @a and @b to the console
x.print_instance_variables(:z) # causes an exception because there is no@z

Any suggestions would be greatly appreciated.

class SomeClass
def initialize
@a = 1
@b = ‘xxx’
end

def print_instance_variables( *args )
args.each do |arg|
raise unless instance_variable_defined?( “@#{ arg }” )
puts self.instance_variable_get( “@#{ arg }” )
end
end

end

x = SomeClass.new
x.print_instance_variables( :a )
x.print_instance_variables( :b )
x.print_instance_variables( :a, :b )
x.print_instance_variables( :z )


#4

On Wed, Dec 31, 2008 at 9:18 PM, Glenn removed_email_address@domain.invalid wrote:

end
x.print_instance_variables(:b) # writes the value of @b to the console
x.print_instance_variables(:a, :b) # writes the values of @a and @b to the console
x.print_instance_variables(:z) # causes an exception because there is no@z

Any suggestions would be greatly appreciated.

class SomeClass
def initialize
@a = 1
@b = ‘xxx’
end

def print_instance_variables( *args )
args.each do |arg|
raise unless instance_variable_defined?( “@#{ arg }” )
puts self.instance_variable_get( “@#{ arg }” )
end
end

end

x = SomeClass.new
x.print_instance_variables( :a )
x.print_instance_variables( :b )
x.print_instance_variables( :a, :b )
x.print_instance_variables( :z )


#5

Hi,

Thanks for your help!

I have a followup question. Can anyone tell me how I could create a
method that would allow me to add instance variables to an object?

The method would look something like this:

def add_instance_variable(x, y)

code goes here

end

In this example, x would be what I’d like to call the variable and y
would be the value of the new variable.

Thanks again,

Glenn


From: Greg D. removed_email_address@domain.invalid
To: ruby-talk ML removed_email_address@domain.invalid
Sent: Wednesday, December 31, 2008 11:58:11 PM
Subject: Re: How do I pass the name of an instance variable into an
object?

On Wed, Dec 31, 2008 at 9:18 PM, Glenn removed_email_address@domain.invalid wrote:

end
x.print_instance_variables(:b) # writes the value of @b to the console
x.print_instance_variables(:a, :b) # writes the values of @a and @b to the console
x.print_instance_variables(:z) # causes an exception because there is no@z

Any suggestions would be greatly appreciated.

class SomeClass
def initialize
@a = 1
@b = ‘xxx’
end

def print_instance_variables( *args )
args.each do |arg|
raise unless instance_variable_defined?( “@#{ arg }” )
puts self.instance_variable_get( “@#{ arg }” )
end
end

end

x = SomeClass.new
x.print_instance_variables( :a )
x.print_instance_variables( :b )
x.print_instance_variables( :a, :b )
x.print_instance_variables( :z )


#6

i just tried putting everything together and it worked great.
I thought i will share the consolidated code, so here it is:

class SomeClass
def initialize
@first = ‘first variable’
@second = ‘second variable’
end

def print_instance_variable(*args)
args.each do |arg|
begin
raise unless instance_variable_defined?("@#{arg}")
puts self.instance_variable_get("@#{arg}")
rescue => ex
puts “#{ex.class}: #{ex.message}”
end
end
end

def add_instance_variable(name, initial_value)
raise if instance_variable_defined?("@#{name}")
self.instance_variable_set("@#{name}", “#{initial_value}”)
end
end

x = SomeClass.new
x.print_instance_variable(:first)
x.print_instance_variable(:second)

puts “\n****************** printing both values in one method call
*************”
x.print_instance_variable :first, :second

puts “\n*************** should throw an exception, because the
instance variable is undefined **************”
x.print_instance_variable :third

x.add_instance_variable(:third, “third value”)

puts “\n*************** should print the third instance
variable**************”
x.print_instance_variable :third


#7

Glenn wrote:

Can anyone tell me how I could create a method that would allow me to add
instance variables to an object?

object.instance_variable_set(:@variable_name, “value”)

HTH,
Sebastian


#8

Glenn wrote:

I think that this is because of the quotes around initial_value in this
line:
self.instance_variable_set("@#{name}", “#{initial_value}”)
[…]
Do you think that there is any harm in leaving those quotes off?

Not at all. The only reason for them to be there in the first place
would be
to convert the value to a string (though initial_value.to_s would be a
more
readable way to do the same thing, in my opinion). Since you don’t want
that,
there is no downside to removing them.

HTH,
Sebastian


#9

Excellent! Thanks so much for your help.

I noticed that the class of the variable always seems to be String when
I use add_instance_variable. When I use instance_variable_set, though
it seems to preserve the class of the object in thee 2nd parameter.

In this case, x is a Fixnum:

s = SomeClass.new
s.instance_variable_set(’@x’, 22)

In this case, though, x is a String:

s = SomeClass.new
s.add_instance_variable(:x, 22)

I think that this is because of the quotes around initial_value in this
line:

self.instance_variable_set("@#{name}", “#{initial_value}”)

When I rewrote the line as:

self.instance_variable_set("@#{name}", initial_value )

It maintains the original class of that 2nd parameter. Do you think
that there is any harm in leaving those quotes off?

Glenn


From: Suman G. removed_email_address@domain.invalid
To: ruby-talk ML removed_email_address@domain.invalid
Sent: Thursday, January 1, 2009 12:46:51 PM
Subject: Re: How do I pass the name of an instance variable into an
object?

i just tried putting everything together and it worked great.
I thought i will share the consolidated code, so here it is:

class SomeClass
def initialize
@first = ‘first variable’
@second = ‘second variable’
end

def print_instance_variable(*args)
args.each do |arg|
begin
raise unless instance_variable_defined?("@#{arg}")
puts self.instance_variable_get("@#{arg}")
rescue => ex
puts “#{ex.class}: #{ex.message}”
end
end
end

def add_instance_variable(name, initial_value)
raise if instance_variable_defined?("@#{name}")
self.instance_variable_set("@#{name}", “#{initial_value}”)
end
end

x = SomeClass.new
x.print_instance_variable(:first)
x.print_instance_variable(:second)

puts “\n****************** printing both values in one method call
*************”
x.print_instance_variable :first, :second

puts “\n*************** should throw an exception, because the
instance variable is undefined **************”
x.print_instance_variable :third

x.add_instance_variable(:third, “third value”)

puts “\n*************** should print the third instance
variable**************”
x.print_instance_variable :third