Cmeurer
Updating Changeset Errors
I am trying to update a changeset from an invalid set of changes to a valid set, but the errors do not reflect the change. The following is what I am experiencing, but not what I expected.
def changeset(foo \\ %__MODULE__{}, attrs) do
foo
|> cast(attrs, [:top_value, :bottom_value])
|> validate_required([:top_value, :bottom_value])
|> validate_number(:top_value, greater_than: 0)
|> validate_number(:bottom_value, greater_than: 0)
end
iex> cs = Foo.changeset(%{top_value: 10})
#Ecto.Changeset<
action: nil,
changes: %{top_value: 10},
errors: [bottom_value: {"can't be blank", [validation: :required]}],
data: #MyApp.Foo<>,
valid?: false
>
iex(6)> Foo.changeset(cs, %{bottom_value: 10})
#Ecto.Changeset<
action: nil,
changes: %{bottom_value: 10, top_value: 10},
errors: [bottom_value: {"can't be blank", [validation: :required]}],
data: #MyApp.Foo<>,
valid?: false
>
I would like to have the errors recalculated after updating the changeset. Is this possible? Am I using this changeset in an unsupported manner? I have also tried both Ecto.Changeset.put_change/3 and Ecto.Changeset.update_change/3. Any suggestions are appreciated.
Most Liked
LostKobrakai
It has come up, but it’s not really possible without complicating how changesets work by a lot.
changeset
|> validate_number(:field, less_than: 25)
|> validate_number(:field, greater_than: 10, less_than: 50)
How should this be handled, if there were the possibility to update errors? Especially imagining both validations actually being abstracted in multiple different purpose functions. It would take a great amount of validation specific logic to accurately update those errors, which doesn’t at all translate well to custom validations a user creates. Also users would need to know those update rules as well, to prevent any strange surprises.
LostKobrakai
You‘d need to remove those errors on your own. Validations are purely additive.
benwilson512
Instead of removing errors, simply pass the original struct back into the changeset function but with more parameters added.
mrroot5
Hello!
This is an old topic by I comes here after a few searches.
I solved this problem using the changeset with an empty struct and updating the attrs with put_change. Following @Cmeurer example will be something like this:
def changeset(attrs) do
# Always use an empty struct
%__MODULE__{}
|> cast(attrs, [:top_value, :bottom_value])
|> validate_required([:top_value, :bottom_value])
|> validate_number(:top_value, greater_than: 0)
|> validate_number(:bottom_value, greater_than: 0)
end
cs = Foo.changeset(%{top_value: 10})
# Here has an error
# In my case this put_change is done in another function
cs = Ecto.Changeset.put_change(cs, :bottom_value, 10)
# Here added bottom_value, changeset still has an error
cs = Foo.changeset(cs.changes)
# Here errors are gone and valid? == true







