List local_variables in a def by means of a method

Hello,

As I work with ruby in combination with a programs API , i’m not able
to use a debugger. (at least I think ::slight_smile:

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 :slight_smile:

Thank you Bartosz

I can work from here!