Вложенная итерация по хешу - PullRequest
0 голосов
/ 04 мая 2020

У меня есть данные ниже, я пытаюсь обновить мои Модели. Данные это GraphQL. Компания может иметь несколько partners: [] (он же Персона), а partner может иметь несколько addresses[]. Я хочу обновить Person.addresses с помощью addresses: [] значений.

mutation updateCompanyPartner {
  updateCompanyPartner(input: {
    uuid: "4c537bd6-cfd5-4141-aefe-9fcaeaffbe51"
    partners: [
      {
        firstName: "Elon"
        lastName: "Musk"
        emailAddress: {
          value: "elon@musk.com"
        }
        addresses: [
        {
          lineOne: "10 New World str."
        },
        {
          lineOne: "10 Old World str."
        }]
      },
      {
        firstName: "Vladimir"
        lastName: "Putin"
        emailAddress: {
          value: "vladimir@putin.com"
        }
        addresses: [
        {
          lineOne: "10 Crimea str."
        },
        {
          lineOne: "10 Tsar str."
        }]
      }
    ]
  })
}

Сначала я повторяю все операции над partners[], а затем проверяю, существует ли value: "elon@musk.com.

Если это так, я нахожу специфику c Лицо, которому принадлежит это письмо (person = email_address.party.specific).

Далее я хочу перебрать каждый person.addresses.map и обновить с помощью addresses[]. Приведенный ниже код является попыткой достичь того, чего я хочу, однако итерация не выполняется должным образом. Причина, почему он не выполняется так, как ожидалось, ясна, однако я не могу понять, как мне сформировать итерацию, чтобы она корректно обновляла значения?

def create(args)
  partners_data = args[:partners]

  partners_data.map do |params| 
    email_address_data = params[:email_address]
    addresses_data = params[:addresses]

    email_address = EmailAddress.find_by(value: email_address_data[:value])

    if email_address.present?
      person = email_address.party.specific 

      person.addresses.map do |address|
        addresses_data.map do |address_data| 
          address.update!(address_data)      # This part is wrong, shouldn't be iterating this way.
        end
      end
    else
      ...
    end
  end
end

1 Ответ

0 голосов
/ 04 мая 2020

Проблема в том, что вы перебираете существующие адреса этого человека и обновляете каждый адрес всеми данными этого адреса. В результате каждый существующий адрес будет обновлен в соответствии с последним адресом.

# Iterate over each existing address
person.addresses.map do |address|
  # Iterate over each new address
  addresses_data.map do |address_data| 
    # Update the existing address with each new data in turn.
    # Only the last entry in addresses_data will stick.
    address.update!(address_data)
  end
end

(Обратите внимание, что map используется при создании нового массива из результата. Он будет работать, но это бесполезная трата ресурсов и запутанность. Когда вы просто хотите выполнить итерацию, используйте each.)

Вместо этого, итерируйте как person.addresses, так и addresses_data. Это можно сделать с помощью zip.

person.addresses.zip(addresses_data).each do |address, data|
  address.update!(data)
end

Предполагается, что person.addresses и address_data имеют одинаковую длину.

...