In upgrading from Ecto 2 to Ecto 3 I’m dealing with a failing test. If I use ExMachina build(:address)
I’ll get an error trying to put_embed/3
:
** (ArgumentError) unknown field `:__meta__` in %Orders.Schemas.InlineAddress{address: #Ecto.Association.NotLoaded<association :address is not loaded>, address_id: nil, city: nil, country_code: nil, delivery_instructions: nil, full_name: nil, id: nil, inserted_at: nil, line1: nil, line2: nil, override: nil, phone_number: nil, sap_id: nil, state_or_region: nil, type: nil, updated_at: nil, version: 1, zip_code: nil}
code: exec(order: order, send_email: send_email_mock, send_csv: send_csv_mock, csv: true)
stacktrace:
(ecto 3.6.2) lib/ecto/changeset.ex:1225: Ecto.Changeset.put_change/7
(stdlib 3.17) maps.erl:410: :maps.fold_1/3
(ecto 3.6.2) lib/ecto/changeset.ex:396: Ecto.Changeset.change/2
(ecto 3.6.2) lib/ecto/changeset/relation.ex:198: Ecto.Changeset.Relation.do_change/4
(ecto 3.6.2) lib/ecto/changeset/relation.ex:326: Ecto.Changeset.Relation.single_change/5
(ecto 3.6.2) lib/ecto/changeset/relation.ex:165: Ecto.Changeset.Relation.change/3
(ecto 3.6.2) lib/ecto/changeset.ex:1213: Ecto.Changeset.put_change/7
(ecto 3.6.2) lib/ecto/changeset.ex:1423: Ecto.Changeset.put_relation/5
(packsize_data 0.0.1) ...accounting/schemas/vendor_po.ex:52: Accounting.VendorPO.changeset/2
vendor_po.ex
referenced looks like:
def changeset(%VendorPO{} = po, attrs) do
po
|> cast(attrs, ~w[customer_po_number]a)
|> put_embed_from_params(:shipping_address)
end
defp put_embed_from_params(changeset, key) do
put_embed(changeset, key, changeset.params["#{key}"])
end
Changing the test to params_for(:address)
works. I don’t see anything in the Ecto docs that indicates something changed, to the contrary the documentation for put_assoc/3
states:
changesets or structs - when a changeset or struct is given, they are treated as the canonical data and the associated data currently stored in the association is ignored.