Как l oop над сильными параметрами при создании ассоциаций - PullRequest
0 голосов
/ 04 апреля 2020

Не путать с циклическим изменением параметров, как l oop над сильными параметрами?

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

name: 'Foo',
tax_rate_component: {
  components: [{name: 'cgm', rate: '2'}, {...}]
}

В ruby, tax_rate имеет много tax_rate_components (учет). Входящий создаст tax_rate, затем его tax_rate_components. Вот что работает:

Контроллер Rails:

# We'll assume all required data are passed and no errors are thrown
def create
  tax_rate = @organisation.tax_rates.build(rate_params)
  tax_rate.save # Would be in an "if" statement

  create_tax_rate_components(tax_rate) # We skip the error checking
  render json: tax_rate, include: [:tax_rate_components]
end

  private

  def find_organisation
  end

  # Somewhere inside here I need to be using rate_component_params
  def create_tax_rate_components(tax_rate)
    components = params[:tax_rate_component][:components]
    components.map do |tc|
      tax_rate.tax_rate_components.build(
        name: tc[:name],
        rate: tc[:rate]
      ).save
    end
  end

  def rate_params
    params.require(:tax_rate).permit(:name)
  end

  # I need to use this
  def rate_component_params
    params.require(:tax_rate_component).permit(
      components: [[:name, :rate]]
    )
  end

Мне нужно использовать rate_component_params при создании tax_rate_components, но как? Есть ли чистый способ создания tax_rate и tax_rate_components с использованием сильных параметров?

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

1 Ответ

1 голос
/ 04 апреля 2020

Вы почти на месте:

def rate_component_params
  params.require(:tax_rate_component).permit(
    components: [:name, :rate]
  )
end

Когда вы передаете массив символов, Rails разрешит га sh с этими ключами. В Rails также есть встроенный метод создания вложенных записей из параметров, а именно ActiveRecord::NestedAttributes. Например:

class TaxRate < ApplicationRecord
  has_many :tax_rate_components
  accepts_nested_attributes_for :tax_rate_components
end

Это создает сеттер с именем tax_rate_component_attributes=, который принимает массив хэшей и создает записи. Он также решает множество проблем с вашим решением, таких как оборачивание всего этого в одну транзакцию и обновление / удаление.

Если ваш API «заблокирован» и вы не можете изменить подпись, вы можете измените параметры или создайте специальный установщик так, чтобы они передавались в установщик вложенных атрибутов.

def rate_params
  params.permit(
    :name,
    tax_rates_component: {
      components: [:name, :rate]
    }
  ).tap do |p|
    attrs = p.dig(:tax_rate_component, :components)
    if attrs 
      p[:tax_rate_component_attributes] = attrs
      p.delete(:tax_rate_component)
    end
  end
end

С этим вы можете избавиться от всего create_tax_rate_components boondoggle.

def create
  tax_rate = @organisation.tax_rates.new(rate_params)
  if tax_rate.save
    render json: tax_rate, include: [:tax_rate_components]
  else
    head :unprocessable_entity # or whateveer
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...