janosrusiczki
janosrusiczki

Reputation: 1931

Modify multidimensional array of symbols

At the moment I have something like:

arr = [
  :name,
  :address,
  cards_attributes: [
    :last_name,
    :first_name,
    phones_attributes: [
      :number,
      :_destroy
    ],
    emails_attributes: [
      :number,
      :_destroy
    ],
    ...
  ]
]

... and I want to turn it into something like:

arr = [
  :id, # <- new!
  :name,
  :address,
  cards_attributes: [
    :id, # <- new!
    :last_name,
    :first_name,
    phones_attributes: [
      :id, # <- new!
      :number,
      :_destroy
    ],
    emails_attributes: [
      :id, # <- new!
      :number,
      :_destroy
    ],
    ...
  ]
]

I know I can add a new symbol to the first level with arr.push(:id) but how do I add elements into the sub hashes?

Upvotes: 1

Views: 233

Answers (2)

ndnenkov
ndnenkov

Reputation: 36101

def add_id(collection)
  collection.unshift(:id) if collection.respond_to?(:unshift)

  collection.each do |key, value|
    add_id(key)   if key.respond_to?(:each)
    add_id(value) if value.respond_to?(:each)
  end
end

EDIT: For the following update

"My question was actually more about how to elegantly access the sub hashes?"

We can use the same general idea. As you didn't specify an operation to be executed on the hashes, the method will expect a block:

def traverse(collection)
  yield collection if collection.is_a? Hash

  collection.each do |key, value|
    traverse(key)   if key.respond_to?(:each)
    traverse(value) if value.respond_to?(:each)
  end
end

traverse(arr) { |hash| puts hash }

Upvotes: 3

sawa
sawa

Reputation: 168071

This was an answer to the original question before the edit

arr.unshift(:id)
arr[-1][:cards_attributes].unshift(:id)
arr[-1][:cards_attributes][-1][:phones_attributes].unshift(:id)

or if you don't like using indices,

arr.unshift(:id)
arr.last[:cards_attributes].unshift(:id)
arr.last[:cards_attributes].last[:phones_attributes].unshift(:id)

or, you can also do:

arr.unshift(:id)
arr.dig(-1, :cards_attributes).unshift(:id)
arr.dig(-1, :cards_attributes, -1, :phones_attributes).unshift(:id)

Upvotes: 1

Related Questions