2015-12-23 7 views
8

Ich setze einen Trace-Code in meinem Programm und würde gerne wissen, welche Methoden durch attr_accessor definiert sind. Mit TracePoint kann ich erkennen, wenn attr_accessor aufgerufen wird, aber ich weiß nicht, wie man es bekommt, um mir die Argumente zu nennen, die es erhielt. Irgendwelche Ideen?Alle durch 'attr_accessor` definierten Variablen ohne Überschreiben `attr_accessor`

+1

Sie können _all_ Instanzvariablen abrufen. Wenn das nicht gut genug ist, müssen Sie attr_accessor auf die eine oder andere Weise instrumentieren. Keine Möglichkeit, das zu vermeiden. –

+0

Ist es wichtig, ob die Methode mit 'attr_accessor' definiert wurde oder Sie nach Methoden suchen, die Accessormethoden von Instanzvariablen sind? –

+0

attr_accessor ist, was ich suche. Den Rest kann ich einfach mit TracePoint bekommen. –

Antwort

0

Sie können obj.methods() verwenden, um alle verfügbaren Methoden für die Instanz zu finden (inc-Methoden von Superklassen), und obj.methods(false), um nur die für das aktuelle Singleton-Objekt definierte Methode zu ermitteln. Ich bin nicht sicher, ob es möglich ist zu erkennen, ob diese Methoden erstellt wurden über attr_accessor, obwohl

+0

Dann beantwortet das nicht wirklich die Frage, oder? :) –

6

In der Frage Titel, Sie nach einer Liste von Variablen gefragt, aber dies beantwortet den Fragenkörper, der für eine Liste der definierten Methoden fragte .

Diese Methode überprüft nicht die Instanzvariablen, bei denen Rauschen auftritt, wenn Sie mit der manuellen Aktualisierung oder dem Erstellen anderer Instanzvariablen beginnen.

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=] 

Ich habe die Methodennamen in der Methods Konstante gespeichert, aber natürlich können Sie sie speichern, wo auch immer für Sie am bequemsten ist.

Definieren/Entfernen method_added auf MethodTracer sorgt dafür, dass Sie nicht Foo.method_added Sie selbst definiert haben klobber. Diese Methode erfordert jedoch, dass Sie, wenn Sie Foo.method_added vor Ihren Anrufen zu attr_accessor definieren, müssen Sie super darin aufrufen. Andernfalls überspringen Sie das temporäre method_added definiert durch MethodTracer.

+3

Dies scheint die einzig richtige Antwort zu sein. – sawa

+1

Als eine Randnotiz habe ich einige Zeit damit verbracht, herauszufinden, wie man 'TracePoint' benutzt, um die Namen der Methoden zu erhalten, die an 'attr_accessor' übergeben werden. Ich fand es ziemlich unmöglich. –

+2

Ich habe versucht. Und auch das OP. Das war der springende Punkt der Frage. Und nur du hast die Lösung erreicht. – sawa

Verwandte Themen