ecto changeset add asso c для существующих - PullRequest
0 голосов
/ 15 февраля 2020

Доброе утро! Я достиг момента, когда я борюсь. Подводя итог, я пытаюсь создать схему / модель, которая имеет ассоциацию, в которой связанная схема / модель уже существует. Каждый найденный мной пример больше похож на вложенные атрибуты Rails. Вот мои различные вещи кода:

Схема (и ее функция набора изменений) с ассоциациями:

schema "payor_procedure_mappings" do
  belongs_to :payor, Payor
  belongs_to :procedure, Procedure
  field :payor_procedure_name, :string
  field :payor_procedure_id, :string

  timestamps()
end

def changeset(model, params \\ %{}) do 
  model
  |> cast(params, all_params())
  |> validate_required(required())
  |> cast_assoc(:payor, params[:payor])  # <--- LINE 50 from stacktrace
end

defp required do
  :payor_procedure_name,
  :payor_procedure_id
]

Существующая схема, которую я хочу связать с этим:

schema "payors" do
  field :name, :string, null: :false
  field :polling_url, :string, null: :false

  timestamps()
end

def changeset(model, params \\ %{}) do 
  model
  |> cast(params, all_params())
  |> validate_required(required())
end 

Вот код, в котором я пытаюсь установить связь:

test "valid if all required params are present", %{procedure: procedure, payor: payor} do 
  params = %{
    payor: payor,
    payor_procedure_name: "That one thing we do to patients",
    payor_procedure_id: "2342"
  }

changeset = 
  %PayorProcedureMapping{}
  |> PayorProcedureMapping.changeset(params)   # THIS IS LINE 28 from stacktrace

  assert changeset.valid?
end

(Обратите внимание, что плательщиком во втором аргументе тестовой функции является уже загруженная структура схемы / модели)

Для ясности, мои передаваемые параметры выглядят так:

%{
  payor: %ReimbursementMonitor.Schemas.Payor{
    __meta__: #Ecto.Schema.Metadata<:loaded, "payors">,
    id: 12,
    inserted_at: ~N[2020-02-15 16:30:16],
    name: "test_name",
    polling_url: "www.example.com",
    updated_at: ~N[2020-02-15 16:30:16]
  },
  payor_procedure_id: "2342",
  payor_procedure_name: "That one thing we do to patients"
}

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

** (FunctionClauseError) no function clause matching in Keyword.get_lazy/3

 The following arguments were given to Keyword.get_lazy/3:

     # 1
     nil

     # 2
     :with

     # 3
     #Function<5.89690842/0 in Ecto.Changeset.cast_relation/4>

 Attempted function clauses (showing 1 out of 1):

def get_lazy(keywords, key, fun) when is_list(keywords) and is_atom(key) and is_function(fun, 0)
  code: |> PayorProcedureMapping.changeset(params)
  stacktrace:
    (elixir) lib/keyword.ex:223: Keyword.get_lazy/3
    (ecto) lib/ecto/changeset.ex:778: Ecto.Changeset.cast_relation/4
    (reimbursement_monitor) lib/reimbursement_monitor/schemas/payor_procedure_mapping.ex:50: ReimbursementMonitor.Schemas.PayorProcedureMapping.changeset/2
    test/schemas/payor_procedure_mapping_test.exs:28: (test)

Полное раскрытие, я искал в Google тонну, но примеры, которые мне удалось найти, - это создание или создание схемы плательщика в то время вставлен payor_procedure_mappings.

Я чувствую, что я в сорняках. Я хотел бы получить несколько указаний о том, где go посмотреть, хорошие примеры того, о чем я спрашиваю.

Заранее спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 16 февраля 2020

Как указано в документации для Ecto.Changeset.cast_assoc/3

cast_assoc/3, выполняется сопоставление записей, извлеченных из базы данных (предварительная загрузка), и сравнивает их с предоставленными параметрами из внешнего источника.

Тем не менее, пример по ссылке выше именно то, что вам нужно:

- |> cast_assoc(:payor, params[:payor])
+ |> cast_assoc(:payor, with: &Payor.changeset/2)

Сообщение об ошибке также намекает на наличие ключевого слова with: ключ ожидается.

0 голосов
/ 16 февраля 2020

Можете ли вы попробовать следующее:

# the params that you pass in
%{
  payor_id: 12,
  payor_procedure_id: "2342",
  payor_procedure_name: "That one thing we do to patients"
}

# the changeset function for payor_procedure_mappings
def changeset(model, params \\ %{}) do 
  model
  |> cast(params, all_params())
  |> validate_required(required())
end

Я думаю, что цель cast_assoc - создать новую связанную запись (записи), поэтому вы нашли только примеры для этого. Поскольку вы хотите связать только создаваемую вами запись payor_procedure_mappings с существующей записью payor, я считаю, что вам просто нужно установить соответствующий идентификатор.

...