Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all variables defined through `attr_accessor` without overriding `attr_accessor`

I am setting some trace code on my program, and would like to know which methods are defined through attr_accessor. Using TracePoint, I can detect when attr_accessor is called, but I don't know how to get it to tell me the arguments it received. Any ideas?

like image 962
n_x_l Avatar asked Dec 23 '15 15:12

n_x_l


1 Answers

In the question title, you asked for a list of variables, but this answers the question body, which asked for a list of the methods defined.

This method doesn't bother checking instance variables, which will have noise introduced if you begin manually updating or creating other instance variables.

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

I've stored the method names in the Methods constant, but obviously you can store them wherever is most convenient for you.

Defining/removing method_added on MethodTracer ensures that you don't clobber any Foo.method_added you've defined yourself. This methodology, however, does require that if you define Foo.method_added before your calls to attr_accessor, you will need to call super inside it. Otherwise you will skip the temporary method_added defined by MethodTracer.

like image 148
user513951 Avatar answered Nov 11 '22 22:11

user513951