获取通过`attr_accessor`定义的所有变量,而不覆盖`attr_accessor`

时间:2015-12-23 15:42:19

标签: ruby metaprogramming

我在我的程序中设置了一些跟踪代码,并想知道通过1.<?xml version="1.0" encoding="UTF-8"?> 2.<loginInformation xmlns="http://www.example.com/restapi" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 定义了哪些方法。使用attr_accessor,我可以检测到TracePoint何时被调用,但我不知道如何让它告诉我收到的论据。有任何想法吗?

2 个答案:

答案 0 :(得分:6)

在问题标题中,您要求提供变量列表,但这会回答问题正文,该问题正在询问所定义方法的列表。

此方法不会检查实例变量,如果您开始手动更新或创建其他实例变量,则会引入噪声。

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

我已将方法名称存储在Methods常量中,但显然您可以将它们存储在最方便的地方。

method_added上定义/删除MethodTracer可确保您不会破坏自己定义的任何Foo.method_added。但是,如果您在调用Foo.method_added之前定义attr_accessor,则需要使用此方法,您需要在其中调用super。否则,您将跳过method_added定义的临时MethodTracer

答案 1 :(得分:0)

您可以使用obj.methods()查找实例上可用的所有方法(包括来自超类的方法),obj.methods(false)只能获取当前单例对象上定义的方法。我不确定是否可以检测这些方法是否通过attr_accessor创建了