在Ruby中,我怎么知道方法是否属于属性访问器?

时间:2011-09-20 21:29:22

标签: ruby-on-rails ruby metaprogramming

我有以下问题:

我正在使用 alias_method_chain 重命名特定类的所有实例方法,以便为它们提供额外的行为。我使用以下代码行获取所有实例方法:

self.class.instance_methods(false)

通过这样做,我得到了所有的实例方法,但我也得到了使用attr_accessor / attr_reader / attr_writer定义的gettes和setter。 我需要做的是检测从前一行代码返回的方法是访问器方法,因为我不想重命名这些方法。

很明显,我可以检测方法名称末尾是否有“=”,这会使它成为一个setter,如果存在,我可以看看是否定义了getter,但是当只有getter时会发生什么一个吸气剂定义?我该怎么检查?特别考虑到类方法“instance_variables”的属性在初始化之前不可用?

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

您可以扩展attr_reader ...以存储方法。

class Object
  class << self
    attr_reader :accessors
    attr_reader :setters
    attr_reader :getters

    alias :attr_accessor_old :attr_accessor
    def attr_accessor(methname)
      (@accessors ||= [] ) << methname
      attr_accessor_old methname
    end

    alias :attr_writer_old :attr_writer
    def attr_writer(methname)
      (@setters ||= [] ) << "#{methname}=".to_sym
      attr_writer_old methname
    end

    alias :attr_reader_old :attr_reader
    def attr_reader(methname)
      (@getters ||= [] ) << methname
      attr_reader_old methname
    end

  end
end

class Test
  attr_accessor :acc
  attr_reader :read
  attr_writer :write
end
Test.instance_methods(false).each{|meth|
  puts "#{meth} is an accessor" if Test.accessors.include?(meth)
  puts "#{meth} is a setter" if Test.setters.include?(meth)
  puts "#{meth} is a getter" if Test.getters.include?(meth)
}

结果:

acc is an accessor
read is a getter
write= is a setter