tutorial - ¿Puedes evaluar el código en el contexto de una persona que llama en Ruby?
ruby wikipedia (5)
Aquí hay un truco de sintaxis más fácil, usando un enlace de bloqueo pasado:
def loginfo &block
what = yield.to_s
evaled = eval(what, block.binding)
Rails.logger.info "#{what} = #{evaled.inspect}"
end
llamado así:
x = 1
loginfo{ :x }
se desconectará:
x = 1
Esencialmente me pregunto si se puede hacer lo siguiente en Ruby.
Así por ejemplo:
def bar(symbol)
# magic code goes here, it outputs "a = 100"
end
def foo
a = 100
bar(:a)
end
No hay una forma integrada de obtener un enlace de llamantes en Ruby en 1.8.X o 1.9.X.
Puede utilizar https://github.com/banister/binding_of_caller para solucionar el problema.
En MRI 2.0 puede usar RubyVM :: DebugInspector, consulte: https://github.com/banister/binding_of_caller/blob/master/lib/binding_of_caller/mri2.rb
Muestra de trabajo en MRI 2.0:
require ''debug_inspector''
def bar(symbol)
RubyVM::DebugInspector.open do |inspector|
val = eval(symbol.to_s, inspector.frame_binding(2))
puts "#{symbol}: #{val}"
end
end
def foo
a = 100
bar(:a)
end
foo
# a: 100
Revisa el artículo de Encuadernaciones Variables en Ruby
class Reference
def initialize(var_name, vars)
@getter = eval "lambda { #{var_name} }", vars
@setter = eval "lambda { |v| #{var_name} = v }", vars
end
def value
@getter.call
end
def value=(new_value)
@setter.call(new_value)
end
end
def ref(&block)
Reference.new(block.call, block.binding)
end
def bar(ref)
# magic code goes here, it outputs "a = 100"
p ref.value
end
def foo
a = 100
bar(ref{:a})
end
foo
Solo para tu información, aquí hay una "manera pirata". Esta es mi (re) implementación del conocido ppp.rb:
#!/usr/bin/ruby
#
# better ppp.rb
#
require ''continuation'' if RUBY_VERSION >= ''1.9.0''
def ppp(*sym)
cc = nil
ok = false
set_trace_func lambda {|event, file, lineno, id, binding, klass|
if ok
set_trace_func nil
cc.call(binding)
else
ok = event == "return"
end
}
return unless bb = callcc{|c| cc = c; nil }
sym.map{|s| v = eval(s.to_s, bb); puts "#{s.inspect} = #{v}"; v }
end
a = 1
s = "hello"
ppp :a, :s
exit 0
Esto falla actualmente con 1.9. [012] Debido a un error en el set_trace_func de ruby.
Tienes que pasar el contexto de foo
a la bar
:
def foo
a = 100
bar(:a, binding)
end
def bar(sym, b)
puts "#{sym} is #{eval(sym.to_s, b)}"
end