Сохранение вложенных данных в базе данных в одной транзакции - PullRequest
0 голосов
/ 19 января 2019

У меня есть 3 модели:

class Address < ApplicationRecord
    has_one :company_address
end
class CompanyAddress < ApplicationRecord
    belongs_to :address, dependent: :destroy
    belongs_to :address_type
end
class Company < ApplicationRecord
  has_many :company_addresses
end

Я получаю данные JSON из другого приложения.

Данные состоят из атрибутов компании и одного / ни одногоили много company_address, который состоит только из одного адреса каждый

Я хочу иметь возможность вставлять и обновлять данные автоматически, и если что-то не получается, я хочу выполнить миграцию обратно

Когда я установил require on strong_params Я не получаю массив company_addresses, однако, когда я использую только permit, он работает нормально

Это не работает:

params.require(:company)
          .permit([
          :short, :name, :company_legal_form_id,
          :company_role_id, :parent_id, :email,
          :fax, :phone, :description,
          :comment, :changed_by,
          company_addresses: [
              :company_id, :address_type_id, :addition,
              :comment, :changed_by,
              address: [
                  :street, :zip, :city,
                  :country_id, :other1, :other2,
                  :other3, :comment, :changed_by
              ]
          ]
      ])

Это работает:

params.permit([
          :short, :name, :company_legal_form_id,
          :company_role_id, :parent_id, :email,
          :fax, :phone, :description,
          :comment, :changed_by,
          company_addresses: [
              :company_id, :address_type_id, :addition,
              :comment, :changed_by,
              address: [
                  :street, :zip, :city,
                  :country_id, :other1, :other2,
                  :other3, :comment, :changed_by
              ]
          ]
      ])

Итак, я создал Form-Object с именем CompanyForm с помощью этих методов.

class CompanyForm
  include ActiveModel::Model

  attr_accessor(
      :company_attributes
  )

  def save
    @company_id = company_attributes.delete('id')

    company_addresses_attributes = company_attributes.delete('company_addresses')

    company_attributes[:changed_by] = 'user'
    company.update!(p company_attributes)
    @company_id = company.id

    if company_addresses_attributes.empty?
      company.company_addresses.destroy_all
    end

    company_addresses_attributes.each do |company_address_attributes|
      @company_address_id = find_company_address_id(company_address_attributes)

      address_attributes = company_address_attributes.delete('address')
      @address_id = find_address_id(address_attributes)

      address_attributes[:changed_by] = 'user'
      address.assign_attributes(p address_attributes)
      @address_id = address.id

      company_address[:changed_by] = 'user'
      company_address.build_address(@address.attributes)
      company_address.assign_attributes(p company_address_attributes)

      company.company_addresses.update!(p company_address.attributes)
    end
  end

  private
    def company
      @company ||= Company.find_by(id: @company_id) || Company.new()
    end

    def address
      @address ||= Address.find_by(id: @address_id) || Address.new()
    end

    def company_address
      @company_address ||= CompanyAddress.find_by(id: @company_address_id) || CompanyAddress.new()
    end

    def find_company_id(params)
      params.dig(:id)
    end

    def find_company_address_id(params)
      params.dig(:id)
    end

    def find_address_id(params)
      params.dig(:id)
    end
end

Первый вопрос: почему я тоже не могу получить company_address, когда я устанавливаю require on: company?

Второй вопрос, как я могу получить свой кодработать без проблем?Я знаю, что код действительно ужасен, однако я новичок в Rails и Ruby в целом.

1 Ответ

0 голосов
/ 19 января 2019

Похоже, проблема с самим JSON - было бы полезно, если бы вы предоставили реальный пример JSON, отправленный в этом запросе. Структура может отличаться от ожидаемой (например, «компания» вложена в другой ключ). Попробуйте использовать binding.pry в первой строке контроллера, который обрабатывает этот запрос, и выясните, какие значения возвращаются из params и params.require(:company), это может привести вас к ответу.

...