Я изучаю рубин и играю с образцами данных. Я преобразовал следующий хеш в массив объектов следующим образом.
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">]>
Однако я хочу преобразовать массив объектов с идентификаторами в массив значений идентификаторов. например, [#<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">]>
Кто-нибудь знает как это сделать?





Вам нужно будет рекурсивно проверять дочерний узел, пока вы не найдете 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">]>
Это самый высокий хэш, который я видел за долгое время. В реальной жизни подумайте о том, чтобы сделать некоторые сокращения, например, сделать одну следующую строку:
{ activity: [{ id: "1A" }, { id: "2A" }], id: "GA" }(или дажеgoal: [{ activity: [{ id: "1A" }, { id: "2A" }], id: "GA" }],). Разве это не так ясно? Полезно иметь возможность просматривать весь объект без необходимости прокручивать его по вертикали (и тем более по горизонтали). Конечно, если заплатить строчкой кода ...