将由OpenStruct创建的对象数组转换为值数组

时间:2018-10-01 14:53:05

标签: ruby-on-rails arrays ruby

我正在学习红宝石,并且正在使用示例数据。我将以下哈希转换为对象数组,如下所示。

class Openstruct
  require 'JSON'
  require 'ostruct'

  HASH = {
    items: [
      {
        health: [
          {
            goal: [
              {
                activity: [
                  {
                    id: "1A"
                  },
                  {
                    id: "2A"
                  }
                ],
                id: "GA"
              }
            ],
            activity: [
              {
                id: "1B"
              },
              {
                id: "2B"
              }
            ],
            id: "GB"
          }
        ],
        goal: [
          {
            activity: [
              {
                id: "1C"
              },
              {
                id: "2C"
              },
            ],
            id: "3c"
          }
        ],
        createdAt: "2018-01-01",
        updatedAt: "2018-01-01",
        id: "DA"
      }
    ],
  }

  def self.all
    json = HASH.to_json
    JSON.parse(json, object_class: OpenStruct)
  end

end

以上返回结果给我

#<OpenStruct items=
  [#<OpenStruct health=
      [#<OpenStruct goal=
        [#<OpenStruct activity=
          [#<OpenStruct id="1A">, #<OpenStruct id="2A">], id="GA">], 
          activity=[#<OpenStruct id="1B">, #<OpenStruct id="2B">], id="GB">], 
          goal=[#<OpenStruct activity=[#<OpenStruct id="1C">, #<OpenStruct id="2C">], id="3c">], 
          createdAt="2018-01-01", 
          updatedAt="2018-01-01", 
          id="DA">]>

但是,我想将具有id的对象数组转换为id的值数组。例如[#<OpenStruct id="1A">, #<OpenStruct id="2A">]-> [“ 1A”,“ 2A”]。所以我想要的最终结果如下:

#<OpenStruct items=
  [#<OpenStruct health=
      [#<OpenStruct goal=
        [#<OpenStruct activity=
          ["1A","2A"], id="GA">], 
          activity=["1B", 2B"], id="GB">], 
          goal=[#<OpenStruct activity=["1C","2C"], id="3c">], 
          createdAt="2018-01-01", 
          updatedAt="2018-01-01", 
          id="DA">]>

有人知道怎么做吗?

1 个答案:

答案 0 :(得分:0)

您将必须递归检查子节点,直到找到仅包含OpenStruct元素的:id。以下是示例数据的工作代码。

def self.convert_struct_id(os)
  # Get possible attributes of any open_struct
  attributes = os.to_h.keys

  # Only get id_value if :id is the only attribute of open_struct
  if attributes.length == 1 && attributes.first == :id
    id_value = os.send(:id)
    return id_value
  end

  # Iterate through attributes
  attributes.each do |attr|
    # Get child elements
    data = os.send(attr)
    case data
    when OpenStruct
      convert_struct_id(data)
    when Array
      # Recursively process for child node
      data.map! { |d| convert_struct_id(d) }
    end
  end
  return os
end

您的self.all方法将如下所示

def self.all
  json = HASH.to_json
  os = JSON.parse(json, object_class: OpenStruct)
  res = convert_struct_id(os)
end

结果:

=> #<OpenStruct items=[#<OpenStruct health=[#<OpenStruct goal=[#<OpenStruct activity=["1A", "2A"], id="GA">], activity=["1B", "2B"], id="GB">], goal=[#<OpenStruct activity=["1C", "2C"], id="3c">], createdAt="2018-01-01", updatedAt="2018-01-01", id="DA">]>