如何在 ruby 中将对象转换为数组

How to convert an Object to array in ruby

我有一个 class(例如)3 个属性,我想将 class 的属性转换为一个数组,这样我就可以将它们存储到我的 csv 文件中。

class Human
   attr_accessor :name,:Lname,:id
   ....
end

当我创建时:

 human1=Human.new("nice","human",1)

我需要一个 return ["nice","human",1].

的函数

是否有我没有找到的预定义的,或者我必须重新定义 to_a 才能完成工作。

注意:class 有超过 3 个属性

is there a function to go through the object attribute or not?

不,没有内置的方法可以真正做你想做的事,你可能会掉入一个常见的初学者陷阱。

attr_accessor 不会“定义属性”,因为 Ruby 实际上并不像其他语言那样具有 properties/attributes/members。它为实例变量定义了 setter 和 getter 方法。 Ruby 不跟踪假定对象具有哪些属性 - 仅跟踪已设置的实际实例变量。

但是 Ruby 确实提供了构建您想要的任何类型的属性系统的基本构造块。这是一个非常简单(也很垃圾)的例子:

class Human
  # this is a class instance variable
  @attributes = []
    
  # a class method that we use for "defining attributes"
  def self.attribute(name)
    attr_accessor name
    @attributes << name
  end

  attribute(:name)
  attribute(:l_name)
  attribute(:id)

  def initialize(**kwargs)
    kwargs.each {|k,v| send("#{k}=", v) }
  end

  # the attributes that are defined for this class
  def self.attributes
    @attributes
  end

  # cast a human to an array
  def to_a
    self.class.attributes.map{ |attr| send(attr) }
  end

  # cast a human to an hash
  def to_h
    self.class.attributes.each_with_object({}) do |attr, hash| 
      hash[attr] = send(attr)
    end
  end
end
jd = Human.new(
  name: 'John',
  l_name: 'Doe',
  id: 1
)

jd.to_a # ['John', Doe, 1]
jd.to_h # {:name=>"John", :l_name=>"Doe", :id=>1}   

我们在这里创建了一个 class 方法 attribute,它在声明时将“属性”的名称添加到 class 实例变量中。因此 class “知道”它有什么属性。然后它像往常一样使用 attr_accessor 创建 setter 和 getter。

当我们“提取”属性(to_ato_h)时,我们使用我们在 class 中定义的列表来调用每个对应的 setter。

通常这种功能会进入模块或基础 class,而不是代表您的业务逻辑的实际 classes。例如 Rails 通过 ActiveModel::AttributesActiveRecord::Attributes 提供这种功能。

I need a function that return ["nice","human",1]

创建这样的方法很简单。如果它专门用于 CSV,我会相应地命名它,例如:

class Human
   attr_accessor :name, :lname, :id

   # ...

   def to_csv
     [name, lname, id]
   end
end

要生成 CSV:

require 'csv'

human1 = Human.new("nice", "human", 1)

csv_string = CSV.generate do |csv|
  csv << ['name', 'lname', 'id']
  csv << human1.to_csv
end

puts csv_string
# name,lname,id
# nice,human,1

请注意,我已将上例中的 Lname 重命名为 lname。大写保留用于常量。