mathieuprog / polymorphic_embed

Polymorphic embeds in Ecto
Apache License 2.0
341 stars 63 forks source link

Expected params to be a map with atoms or string keys, got a map with mixed keys. #17

Closed daveli closed 4 years ago

daveli commented 4 years ago

👋 I'm currently updating to 0.13.0 and I ran into an issue with cast_polymorphic_embed mixing both atom and string keys. I guess this can be fixed by converting both data_for_field and params_for_field into string keys (as atoms have a limit)?

mathieuprog commented 4 years ago

You have a mix of atom and string keys in the param map that you pass to cast? Normally cast complains about that. I guess you call cast before cast_polymorphic_embed?

daveli commented 4 years ago

Nope just string keys. data_for_field returns atoms as keys that is why it clashes :)

mathieuprog commented 4 years ago

We need a failing test case in any case to prevent this issue for any future update of the library. See if you can provide a test case. If not, you could copy the error stack trace.

daveli commented 4 years ago

Here is an example based on https://github.com/mathieuprog/polymorphic_embed/blob/v0.13.0/test/polymorphic_embed_test.exs#L190

reminder = %Reminder{
      date: ~U[2020-05-28 02:57:19Z],
      text: "This is an SMS reminder",
      channel: %SMS{
        provider: %TwilioSMSProvider{
          api_key: "foo"
        },
        number: "02/807.05.53",
        country_code: 32,
        result: %SMSResult{success: true},
        attempts: [
          %SMSAttempts{
            date: ~U[2020-05-28 07:27:05Z],
            result: %SMSResult{success: true}
          },
          %SMSAttempts{
            date: ~U[2020-05-28 07:27:05Z],
            result: %SMSResult{success: true}
          }
        ]
      }
    }

    changeset =
      reminder
      |> Reminder.changeset(%{
        "channel" => %{
          "__type__" => "sms",
          "number" => "54"
        }
      })

    changeset
    |> Repo.insert!()

    reminder =
      Reminder
      |> QueryBuilder.where(text: "This is an SMS reminder")
      |> Repo.one()

    assert reminder.channel.result.success

Where the changeset data is a string key map instead of atom key map.

mathieuprog commented 4 years ago

Try 0.14