54

请帮助我获取在类中声明的所有实例变量,就像instance_methods向我展示类中可用的所有方法一样。

class A
  attr_accessor :ab, :ac
end

puts A.instance_methods  #gives ab and ac

puts A.something         #gives me @ab @ac...
4

5 回答 5

82

您可以使用instance_variables

A.instance_variables

但这可能不是您想要的,因为这会获取class A中的实例变量,而不是该类的实例。所以你可能想要:

a = A.new
a.instance_variables

但请注意,仅调用attr_accessor不会定义任何实例变量(它只是定义方法),因此在您明确设置它们之前,实例中不会有任何变量。

a = A.new
a.instance_variables #=> []
a.ab = 'foo'
a.instance_variables #=> [:@ab]
于 2012-08-12T21:09:22.937 回答
15

如果要获取所有实例变量值,可以尝试以下操作:

class A
  attr_accessor :foo, :bar

  def context
    self.instance_variables.map do |attribute|
      { attribute => self.instance_variable_get(attribute) }
    end
  end
end

a = A.new
a.foo = "foo"
a.bar = 42
a.context #=> [{ :@foo => "foo" }, { :@bar => 42 }]
于 2016-05-31T10:35:27.850 回答
1

这不是万无一失的-可以在与模式匹配的类上定义其他方法-但我发现适合我需要的一种方法是

A.instance_methods.grep(/[a-z_]+=/).map{ |m| m.to_s.gsub(/^(.+)=$/, '@\1') }
于 2018-09-06T22:28:20.437 回答
1

如果您想以属性的方式获取所有实例变量的哈希,请按照 Aschen 的回答,您可以这样做

class A
  attr_accessor :foo, :bar

    def attributes
    self.instance_variables.map do |attribute|
      key = attribute.to_s.gsub('@','')
      [key, self.instance_variable_get(attribute)]
    end.to_h
  end
end
a = A.new
a.foo = "foo"
a.bar = 42
a.context #=> {'foo' => 'foo', 'bar' => 42}
于 2018-11-26T20:56:44.003 回答
0

基于@Obromios 的答案,我添加了.to_h.to_s到一个类,以允许愉快、灵活地转储适合显示给最终用户的属性。

这个特定的类(不是 ActiveRecord 模型)将在不同情况下设置各种属性。打印时只会出现那些具有值的属性myvar.to_s,这是我的愿望。

class LocalError
  attr_accessor :product_code, :event_description, :error_code, :error_column, :error_row 

  def to_h
    instance_variables.map do |attribute|
      key = attribute.to_s.gsub('@', '')
      [key, self.instance_variable_get(attribute)]
    end.to_h
  end

  def to_s
    to_h.to_s
  end
end

这使我可以将这个简单的代码放在邮件模板中:

Data error:   <%= @data_error %>

它产生(例如):

Data error:   {"event_description"=>"invalid date", "error_row"=>13}

这很好,因为将来不需要更新邮件程序,因为 LocalError 属性会发生变化。

于 2020-10-09T15:36:51.113 回答