views:

296

answers:

5

How can I convert :obj back into a variable called obj inside the def?

def foo(bar)
  bar.some_method_call
end

foo :obj

UPDATE: The final code is more elaborate than this but...

I like to be able to say
foo :obj
instead of
foo obj

I working on some DSL-like syntax. And this one change would let things read a little clearer.

A: 

You almost certainly can't. That definition won't have access to the calling scope's local variables. If you want to explain a little more fully what you're trying to do, we might be able to offer a useful alternative.

Chuck
see update and comments
tyndall
+4  A: 

What kind of variable is obj in your example? If it's a local variable of the scope where foo is called, it can't be accessed from inside foo, unless you pass the current binding as a second parameter.

If you want to access the instance variable @obj, it's easy:

def foo(bar)
  instance_variable_get("@#{bar}").length
end

@obj = "lala"
foo("obj") #=> 4
sepp2k
obj is outside of the scope of foo. +1 good info
tyndall
A: 

Do you mean the variable or the accessor method? Sepp2k gave the name for an instance variable; for an accessor use

def foo(bar)
  self.send(bar).some_method_call
end
Kathy Van Stone
A: 

You could use eval

def foo(bar)
  eval(bar.to_s).some_method_call
end
madlep
+1  A: 

It's a bit odd, but if you are willing to pass an empty block (or if you are passing one anyway), you can get the binding from the block, then call eval and pass the binding:

def foo(symbol, &block)
  binding = block.send(:binding)

  eval(symbol.to_s, binding)
end

var = 3

puts foo(:var) {}

This will print 3.

Alternatively, ActiveSupport apparently has something called Binding.of_caller that you may be able to use so you don't have to pass the block, but I don't know how well it works.

Another alternative is to call foo and pass the binding in:

def foo(binding, symbol)
  eval(symbol.to_s, binding)
end

binding = self.send(:binding)
var = 3

puts foo(binding, :var)
Topher Fangio