elixir-ecto / ecto

A toolkit for data mapping and language integrated query.
https://hexdocs.pm/ecto
Apache License 2.0
6.15k stars 1.43k forks source link

`apply_changes/1` does not convert nested schemaless validation changeset #4514

Open azizk opened 5 hours ago

azizk commented 5 hours ago

Elixir version

1.16.3

Database and Version

13.16

Ecto Versions

3.12.3

Database Adapter and Versions (postgrex, myxql, etc)

0.19.1

Current behavior

Sometimes it's useful to validate maps without a schema, to avoid having to define another embedded struct or to do dynamic validations:

defmodule MySchema do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key false
  embedded_schema do
    field :extended, :map
  end

  def changeset(struct \\ %__MODULE__{}, params) do
    struct
    |> cast(params, [:extended])
    |> update_change(:extended, fn extended ->
      {%{}, %{foo: :integer, bar: :integer}}
      |> cast(extended || %{}, [:foo, :bar])
      |> validate_required([:bar])
    end)
  end
end

test "apply_changes/1 for nested schemaless changeset" do
  params = %{"extended" => %{"foo" => 1, "bar" => 2}}
  changeset = MySchema.changeset(%MySchema{}, params)

  %MySchema{extended: %{foo: 1, bar: 2}} = apply_changes(changeset)
end

Expected behavior

apply_changes/1 should convert the nested changeset to a map with atom keys.

josevalim commented 5 hours ago

While we don't support nesting schemaless changesets inside schemas, if you send a PR for this, we will be glad to review and support it. :)