2009-08-31 13 views

Respuesta

15

No es ningún incorporado en forma de conseguir que un llamador se una ing en Ruby en 1.8.X o 1.9.X.

Puede usar https://github.com/banister/binding_of_caller para evitar el problema.

En la RM 2.0 se puede utilizar RubyVM :: DebugInspector, consulte: https://github.com/banister/binding_of_caller/blob/master/lib/binding_of_caller/mri2.rb

muestra de trabajo en RM 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 
+0

aquí hay un ejemplo de la forma frágil de usar set_trace_func para hacerlo: http://stackoverflow.com/questions/1314592/how-can-i-get-the-binding-from-methodmissing/1315612#1315612 – rampion

+2

Debe incluir una exención de responsabilidad : Por favor, no hagas esto a menos que * en realidad * lo estés usando para la depuración de algún tipo. – tmandry

3

Comprobar artículo a cabo Variable Bindings in 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 
+0

+1 ve muy interesante , Me pregunto si esto se puede hacer sin el bloque ... –

+0

No creo que se pueda hacer sin el bloque en ruby ​​1.8. X. No estoy familiarizado con ruby ​​1.9.x, así que las cosas pueden ser diferentes allí. – neoneye

+0

En Ruby 2.1 todavía necesita el bloque, pero la implementación de 'Referencia' se puede volver a hacer mediante llamadas a [' Binding # local_variable_get'] (http://www.ruby-doc.org/core-2.1.0/Binding. html # method-i-local_variable_get) y ['Binding # vars.local_variable_set'] (http://www.ruby-doc.org/core-2.1.0/Binding.html#method-i-local_variable_set). Aunque, la implementación actual probablemente permite llamadas a métodos de lectura y escritura además de variables locales, mientras que la nueva implementación no ... – Ajedi32

17

Tienes que pasar foo 's marco de bar:

def foo 
    a = 100 
    bar(:a, binding) 
end 
def bar(sym, b) 
    puts "#{sym} is #{eval(sym.to_s, b)}" 
end 
+3

@fotanus, uh no. Notarás que la fecha de mi respuesta es anterior a ruby ​​2 por 3.5 años. –

+0

Lo sentimos, tienes razón. – fotanus

6

Para su información, aquí hay un "camino hacky". Este es mi (re) puesta en práctica de ppp.rb conocido:.

#!/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 

Esta falla en la actualidad con 1,9 [012] debido a un error en set_trace_func de ruby.

+0

¡Muy interesante! Lo he adaptado para compilar [mi propia versión de caller_binding] (http://rubychallenger.blogspot.com/2011/07/caller-binding.html). Pero [¿qué es ppp?] (Http://stackoverflow.com/questions/6884122/ruby-what-is-ppp-rb) –

7

Aquí un corte de sintaxis más fácil, usando una pasa en el bloque de unión:

def loginfo &block 
    what = yield.to_s 
    evaled = eval(what, block.binding) 
    Rails.logger.info "#{what} = #{evaled.inspect}" 
    end 

llama así:

x = 1 
    loginfo{ :x } 

va a cerrar la sesión:

x = 1 
+1

FYI actualizó mi respuesta –

Cuestiones relacionadas