diff --git a/lib/params.ex b/lib/params.ex index 1766087..4e01ce3 100644 --- a/lib/params.ex +++ b/lib/params.ex @@ -10,6 +10,12 @@ defmodule Strukt.Params do when is_map(params) and map_size(params) == 0, do: params + # Scalar params have no fields to map. Preserve them so Ecto can report the type mismatch + # instead of crashing in get_params_field_value/3. + def transform(_module, params, _struct) + when not is_map(params) and not is_list(params) and not is_nil(params), + do: params + def transform(module, params, nil = _struct) when is_struct(params) do transform_from_struct(module, params, params) end diff --git a/test/strukt_test.exs b/test/strukt_test.exs index 83a920b..6e41940 100644 --- a/test/strukt_test.exs +++ b/test/strukt_test.exs @@ -499,6 +499,32 @@ defmodule Strukt.Test do }) end + test "return error when an embeds_many item has the wrong type" do + assert {:error, + %Ecto.Changeset{ + action: :insert, + changes: %{}, + errors: [items: {"is invalid", [validation: :embed, type: {:array, :map}]}], + valid?: false + }} = + Fixtures.CustomFieldsWithEmbeddedSchema.new(%{ + items: ["item"] + }) + end + + test "return error when passing wrong typed value to embeds_one field" do + assert {:error, + %Ecto.Changeset{ + action: :insert, + changes: %{}, + errors: [meta: {"is invalid", [validation: :embed, type: :map]}], + valid?: false + }} = + Fixtures.CustomFieldsWithEmbeddedSchema.new(%{ + meta: "metadata" + }) + end + test "parse custom fields with boolean value" do assert {:ok, %Strukt.Test.Fixtures.CustomFieldsWithBoolean{enabled: false, uuid: uuid}} = Fixtures.CustomFieldsWithBoolean.new(%{Enabled: false})