hrzndhrn/xema

any_of field for structs is not behaving as expected

Closed this issue · 1 comments

Hi,

given the following example

defmodule Foo do
  use Xema

  xema do
    field :value, :atom, const: :foo
  end
end

defmodule Bar do
  use Xema

  xema do
    field :value, :atom, const: :bar
  end
end

defmodule FooBar do
  use Xema

  xema do
    field :foobar, :any, one_of: [Foo, Bar]
  end
end

With this definition, the following code fails

iex(1)> Foo.cast %{value: :foo}
{:ok, %Foo{value: :foo}}

iex(2)> Bar.cast %{value: :bar}
{:ok, %Bar{value: :bar}}

iex(3)> FooBar.cast %{foobar: %{value: :foo}}
** (Protocol.UndefinedError) protocol Xema.Castable not implemented for %Bar{value: :foo} of type Bar (a struct). This protocol is implemented for the following type(s): OtherRequest, OneRequest, Date, DateTime, Tuple, Time, Decimal, NaiveDateTime, BitString, Float, Integer, Map, List, Atom
    (xema 0.13.10) lib/xema/castable.ex:1: Xema.Castable.impl_for!/1
    (xema 0.13.10) lib/xema/castable.ex:9: Xema.Castable.cast/2
    (xema 0.13.10) lib/xema.ex:755: Xema.castable_cast/2
    (xema 0.13.10) lib/xema.ex:736: Xema.do_cast/4
    (xema 0.13.10) lib/xema.ex:1079: anonymous fn/3 in Xema.do_cast_combiner/4
    (elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
    (xema 0.13.10) lib/xema.ex:1078: Xema.do_cast_combiner/4
    (xema 0.13.10) lib/xema.ex:834: anonymous fn/8 in Xema.cast_values/4

Implementing the castable protocol for both the structures, works only for one of the choices

iex(1)> FooBar.cast %{foobar: %{value: :bar}}
{:ok, %FooBar{foobar: %Bar{value: :bar}}}

iex(2)> FooBar.cast %{foobar: %{value: :foo}}
{:error,
 %Xema.ValidationError{
   message: nil,
   reason: %{
     properties: %{
       foobar: %{
         one_of: {:error,
          [
            %{module: Foo, value: %Bar{value: :foo}},
            %{properties: %{value: %{const: :bar, value: :foo}}}
          ]},
         value: %Bar{value: :foo}
       }
     }
   }
 }}

Thanks

Thanks for reporting. I will have a look.