2009-08-31 9 views

risposta

15

Non v'è alcun incorporato in modo da far legare i chiamanti ing in Ruby in 1.8.X o 1.9.X.

È possibile utilizzare https://github.com/banister/binding_of_caller per aggirare.

In risonanza magnetica 2.0 è possibile utilizzare RubyVM :: DebugInspector, vedi: campione Lavorare https://github.com/banister/binding_of_caller/blob/master/lib/binding_of_caller/mri2.rb

in 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 
+0

Ecco un esempio del modo fragile di usare set_trace_func per farlo: http://stackoverflow.com/questions/1314592/how-can-i-get-the-binding-from-methodmissing/1315612#1315612 – rampion

+2

Dovrebbe includere dichiarazione di non responsabilità : Si prega di non farlo a meno che non lo si * in effetti * usandolo per il debug di qualche tipo. – tmandry

3

check out articolo 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 sembra molto interessante , Mi chiedo se questo può essere fatto senza il blocco però ... –

+0

Non penso che si possa fare senza il blocco in ruby ​​1.8. X. Non ho familiarità con Ruby 1.9.x, quindi le cose potrebbero essere diverse lì. – neoneye

+0

In Ruby 2.1 è ancora necessario il blocco, ma l'implementazione di 'Reference' può essere ripristinata usando le chiamate a [' Binding # local_variable_get'] (http://www.ruby-doc.org/core-2.1.0/Binding. html # method-i-local_variable_get) e ['Binding # vars.local_variable_set'] (http://www.ruby-doc.org/core-2.1.0/Binding.html#method-i-local_variable_set). Anche se l'attuale implementazione consente probabilmente chiamate a metodi di lettura e scrittura oltre alle variabili locali, mentre la nuova implementazione non ... – Ajedi32

17

Devi passare foo 's contesto bar:

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

@fotanus, no. Noterai che la data della mia risposta è anteriore al rubino 2 di 3,5 anni. –

+0

Siamo spiacenti, hai ragione. – fotanus

6

Proprio A proposito, ecco un "modo hacky". Questa è la mia (ri) attuazione ppp.rb noto:.

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

Questo attualmente non riesce e 1.9 [012] a causa di un bug in set_trace_func di Ruby.

+0

Molto interessante! L'ho adattato per creare [la mia versione di caller_binding] (http://rubychallenger.blogspot.com/2011/07/caller-binding.html). Ma [cosa è ppp?] (Http://stackoverflow.com/questions/6884122/ruby-what-is-ppp-rb) –

7

Ecco un hack sintassi più semplice, con un passato nel blocco vincolante:

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

chiamati in questo modo:

x = 1 
    loginfo{ :x } 

sarà disconnettersi:

x = 1 
+1

FYI ha aggiornato la mia risposta –

Problemi correlati