在Ruby中列出attr_accessors的最快/一线方式?

时间:2010-03-21 14:04:26

标签: ruby introspection

列出用attr_accessor定义的所有方法的最短,单行方法是什么?我想这样做,如果我有一个类MyBaseClass,任何扩展它的东西,我可以在子类中定义attr_accessor。像这样:

class MyBaseClass < Hash
  def attributes
    # ??
  end
end

class SubClass < MyBaseClass
  attr_accessor :id, :title, :body
end

puts SubClass.new.attributes.inspect #=> [id, title, body]

如何仅显示attr_readerattr_writer定义?

6 个答案:

答案 0 :(得分:41)

将属性提取到数组中,将它们分配给constant,然后将splat分配到attr_accessor

class SubClass < MyBaseClass
  ATTRS = [:id, :title, :body]
  attr_accessor(*ATTRS)
end

现在您可以通过常量访问它们:

puts SubClass.ATTRS #=> [:id, :title, :body]

答案 1 :(得分:39)

没有办法(单行或其他方式)列出attr_accessor定义的所有方法,只列出attr_accessor定义的方法,而不定义自己的attr_accessor。

这是一个覆盖MyBaseClass中的attr_accessor的解决方案,用于记住使用attr_accessor创建的方法:

class MyBaseClass
  def self.attr_accessor(*vars)
    @attributes ||= []
    @attributes.concat vars
    super(*vars)
  end

  def self.attributes
    @attributes
  end

  def attributes
    self.class.attributes
  end
end

class SubClass < MyBaseClass
  attr_accessor :id, :title, :body
end

SubClass.new.attributes.inspect #=> [:id, :title, :body]

答案 2 :(得分:6)

继承人使用mixin而不是继承:

module TrackAttributes
  def attr_readers
    self.class.instance_variable_get('@attr_readers')
  end

  def attr_writers
    self.class.instance_variable_get('@attr_writers')
  end

  def attr_accessors
    self.class.instance_variable_get('@attr_accessors')
  end

  def self.included(klass)
    klass.send :define_singleton_method, :attr_reader, ->(*params) do
      @attr_readers ||= []
      @attr_readers.concat params
      super(*params)
    end

    klass.send :define_singleton_method, :attr_writer, ->(*params) do
      @attr_writers ||= []
      @attr_writers.concat params
      super(*params)
    end

    klass.send :define_singleton_method, :attr_accessor, ->(*params) do
      @attr_accessors ||= []
      @attr_accessors.concat params
      super(*params)
    end
  end
end

class MyClass
  include TrackAttributes

  attr_accessor :id, :title, :body
end

MyClass.new.attr_accessors #=> [:id, :title, :body]

答案 3 :(得分:2)

跟进Christian的回复,但修改为使用ActiveSupport :: Concern ......

module TrackAttributes
  extend ActiveSupport::Concern

  included do
    define_singleton_method(:attr_reader) do |*params|
      @attr_readers ||= []
      @attr_readers.concat params
      super(*params)
    end

    define_singleton_method(:attr_writer) do |*params|
      @attr_writers ||= []
      @attr_writers.concat params
      super(*params)
    end

    define_singleton_method(:attr_accessor) do |*params|
      @attr_accessors ||= []
      @attr_accessors.concat params
      super(*params)
    end
  end

  def attr_readers
    self.class.instance_variable_get('@attr_readers')
  end

  def attr_writers
    self.class.instance_variable_get('@attr_writers')
  end

  def attr_accessors
    self.class.instance_variable_get('@attr_accessors')
  end

end

答案 4 :(得分:2)

类定义

class MyBaseClass
  attr_writer :an_attr_writer
  attr_reader :an_attr_reader

  def instance_m
  end

  def self.class_m
  end
end

class SubClass < MyBaseClass
  attr_accessor :id

  def sub_instance_m
  end

  def self.class_sub_m
  end
end

作为类方法调用

p SubClass.instance_methods - Object.methods    
p MyBaseClass.instance_methods - Object.methods

调用实例方法

a = SubClass.new
b = MyBaseClass.new

p a.methods - Object.methods
p b.methods - Object.methods

两者都会输出相同的

#=> [:id, :sub_instance_m, :id=, :an_attr_reader, :instance_m, :an_attr_writer=]
#=> [:an_attr_reader, :instance_m, :an_attr_writer=]

如何判断哪个是作家读者和访问者?

attr_accessor既是attr_writer又是attr_reader

attr_reader在方法名称

之后输出no =

attr_writer在方法名称

之后输出=

您始终可以使用正则表达式来过滤该输出。

答案 5 :(得分:0)

可以使用等号匹配逻辑对其进行过滤:

X (T r t) b