2015-12-23 13 views
8

Sto impostando del codice di traccia sul mio programma e vorrei sapere quali metodi sono definiti tramite attr_accessor. Usando TracePoint, posso rilevare quando si chiama attr_accessor, ma non so come ottenerlo per dirmi gli argomenti che ha ricevuto. Qualche idea?Ottieni tutte le variabili definite tramite `attr_accessor` senza sovrascrivere` attr_accessor`

+1

È possibile ottenere solo tutte le variabili di istanza. Se questo non è abbastanza buono, dovrai strumentare attr_accessor in un modo o nell'altro. Non c'è modo di evitare questo. –

+0

Indica se il metodo è stato definito usando 'attr_accessor' o se stai cercando metodi che siano metodi di accesso delle variabili di istanza? –

+0

attr_accessor è quello che sto cercando. Il resto posso ottenere facilmente con TracePoint. –

risposta

0

è possibile utilizzare obj.methods() per trovare tutti i metodi disponibili sull'istanza (metodi inc di superclassi) e obj.methods(false) per ottenere solo il metodo definito sull'oggetto Singleton corrente. Non sono sicuro che sia possibile rilevare se questi metodi sono stati creati tramite attr_accessor sebbene

+0

Quindi questo non risponde veramente alla domanda, vero? :) –

6

Nel titolo della domanda, è stato chiesto un elenco di variabili, ma questo risponde al corpo della domanda, che ha chiesto un elenco dei metodi definiti .

Questo metodo non interferisce con il controllo delle variabili di istanza, che introdurranno rumore se si avvia manualmente l'aggiornamento o si creano altre variabili di istanza.

module MethodTracer 
    TracePoint.trace(:c_call) do |t| 
    if (t.method_id == :attr_accessor) 
     t.self.extend(MethodTracer) 

     methods = t.self::Methods ||= [] 
     MethodTracer.send(:define_method, :method_added) {|m| methods << m } 
    end 
    end 

    TracePoint.trace(:c_return) do |t| 
    if (t.method_id == :attr_accessor) 
     MethodTracer.send(:remove_method, :method_added) 
    end 
    end 
end 

class Foo 
    attr_accessor :a, :b 
    attr_accessor :c 

    def foo; end 
end 

Foo::Methods # => [:a, :a=, :b, :b=, :c, :c=] 

Ho memorizzato i nomi dei metodi nella costante Methods, ma ovviamente è possibile memorizzare ovunque è più conveniente per voi.

La definizione/rimozione di method_added su MethodTracer assicura che non si sia verificato alcun problema con Foo.method_added definito dall'utente. Questa metodologia, tuttavia, richiede che se si definisce Foo.method_added prima delle chiamate a attr_accessor, sarà necessario chiamare super al suo interno. In caso contrario, salterai temporaneamente il valore method_added definito da MethodTracer.

+3

Questa sembra essere l'unica risposta corretta. – sawa

+1

Come nota a margine, ho passato un po 'di tempo a cercare di capire come usare 'TracePoint' per ottenere i nomi dei metodi passati a' attr_accessor'. L'ho trovato abbastanza impossibile. –

+2

Ho provato a. E così ha fatto l'OP. Questo era il punto centrale della domanda. E solo tu hai raggiunto la soluzione. – sawa