Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changeset doesn't consider existing data #10

Closed
bducharme opened this issue Oct 15, 2020 · 7 comments
Closed

Changeset doesn't consider existing data #10

bducharme opened this issue Oct 15, 2020 · 7 comments
Labels
enhancement New feature or request

Comments

@bducharme
Copy link

bducharme commented Oct 15, 2020

Hello!

In your documentation, one of the feature is the ability to add a changeset

Run changeset validations when a changeset/2 function is present (when absent, the library will introspect the fields to cast)

What I found is that the first parameter is always an empty struct and not the actual existing data. Meaning that even if I do not cast some field, it will be reset to nil because of the data.

Is there something I do wrong or a known workaround? Is it known and as designed?

Thank you!

Here's a simple example,

  schema "parent" do
    field(:child, Child)
  end

  def changeset(parent, attrs) do
    cast(parent, attrs, ~w(child)a)
  end
  embedded_schema "custom_child" do
    field(:first, :string)
    field(:second, :string)
  end

  def changeset(child, attrs) do
    cast(child, attrs, ~w(first)a)
  end

In this case, even if my existing child has a value for second, it won't be kept, unless I pass as attrs and cast it

@mathieuprog
Copy link
Owner

What I found is that the first parameter is always an empty struct and not the actual existing data. Meaning that even if I do not cast some field, it will be reset to nil because of the data.

I don't see how the first parameter is an empty struct. See here the code that checks for a changeset/2 function:
https://github.com/mathieuprog/polymorphic_embed/blob/v0.7.0/lib/polymorphic_embed/custom_type.ex#L90

Maybe you can add some logs and run deps.compile and see what happens?

Even better, create a failing test in the library's tests?

@mathieuprog
Copy link
Owner

@bducharme
Copy link
Author

By building on this test, if I do

  test "update part of embed" do
    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",
        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}
          }
        ]
      }
    }

    reminder
    |> Reminder.changeset(%{})
    |> Repo.insert()

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

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

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

    assert reminder.channel.result.success
  end

This will fail since result is now nil

@mathieuprog
Copy link
Owner

Nice! I'll look into this in the coming days. If it's urgent though I can share which steps we should take to better understand the issue and then solve it.

@bducharme
Copy link
Author

As a work around, I have a function that convert the polymorphic embed to a map and then I update this one with my changes and pass it all as the "new" attributes. I don't have much time to get really into it sadly, but I'll keep an eye for any new development on this matter! Thanks!

@mathieuprog
Copy link
Owner

mathieuprog commented Oct 18, 2020

Could you try with version 0.9.0? Ecto must be >=3.5.

See new example in the docs because API has changed:

  1. specify options directly on the field in the schema (no more intermediary module)
  2. use cast_polymorphic_embed/2

@bducharme
Copy link
Author

I cannot make the switch as of now, but looking at the Pull Request, this should fix this use case. Feel free to close and thank you for the responsiveness!

@mathieuprog mathieuprog added the enhancement New feature or request label Dec 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants