Hello,
As I work with ruby in combination with a programs API , i’m not able
to use a debugger. (at least I think :
So i’m looking for a way to list my variables.
This is what I have:
def listvar
instance_variables.each {|inst| puts “#{inst} is #{inst.class} and is
equal to #{eval(inst).inspect}” }
local_variables.each {|var| puts “#{var} is #{var.class} and is equal
to #{eval(var).inspect}” }
end
module Test
@foo = ‘good’
def self.one
foo = ‘good’
foo1 = ‘better’
foo2 = ‘somehing’
@foo.upcase!
listvar
end
def self.two
foo = 1
foo1 = 2
foo2 = 3
@foo.reverse!
listvar
end
end
Test.one ==> @foo is String and is equal to “GOOD”
Test.two ==> @foo is String and is equal to “DOOG”
So it works for instance_variables only, not for local_variables.
If I want to list the local variables for self.one I have to do
it like this:
def self.one
foo = ‘good’
foo1 = ‘better’
foo2 = ‘somehing’
@foo.upcase!
local_variables.each {|var| puts “#{var} is #{var.class} and is
equal to #{eval(var).inspect}” }
end
==>
foo is String and is equal to 1
foo1 is String and is equal to 2
foo2 is String and is equal to 3
But its not nice!!! How can i achieve this by calling a method,
just like with the instance_variables??
Thnx
Liquid
You can’t. The “listvar” method has a different scope than “one” or
“two”, and thus different local variables. You could try passing a
binding to the “listvar” method, but I don’t know if it’s worth the
hassle.
– Matma R.
Bartosz Dziewoński wrote in post #1058785:
You can’t. The “listvar” method has a different scope than “one” or
“two”, and thus different local variables. You could try passing a
binding to the “listvar” method, but I don’t know if it’s worth the
hassle.
– Matma R.
Thnx Matma,
It would be very convenient for me to get a list of my vars in a simple
way.
So once I’m through the hassle of writing the method ,I can use it over
and over again and enjoy!
But how can I use these bindings??
Like this:
class A
def stuff
a = 4
foo = ‘asd’
list_vars(binding())
end
def list_vars bnd
bnd.eval(‘local_variables’).each{|var|
puts “#{var} is #{bnd.eval(var.to_s).class} and is equal to
#{bnd.eval(var.to_s).inspect}”
}
end
end
A.new.stuff
This will print:
a is Fixnum and is equal to 4
foo is String and is equal to “asd”
The method “binding” will return a magical value that basically
contains the entire state of a script in this particular place. You
can then eval code as if it appeared in that place, and you will have
access to all variables available there.
– Matma R.
Ronnie Aa wrote in post #1058797:
Thank you Bartosz
I can work from here!
Aside: every time you pass a block, you are also passing a binding
implicitly. So you can change this to:
class A
def stuff
a = 4
foo = ‘asd’
list_vars {}
end
def list_vars &blk
bnd = blk.binding
bnd.eval(‘local_variables’).each{|var|
val = bnd.eval(var.to_s)
puts “#{var} is #{val.class} and is equal to #{val.inspect}”
}
end
end
A.new.stuff
If you can think of something useful to do with the block, then it will
look less odd than passing an empty one 