Cmeurer

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

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

LostKobrakai

You‘d need to remove those errors on your own. Validations are purely additive.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Instead of removing errors, simply pass the original struct back into the changeset function but with more parameters added.

mrroot5

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

Where Next?

Popular in Questions Top

JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
Fl4m3Ph03n1x
Background Let’s assume I have a typical GenServer that receives messages as requests, does some operation in a DB and returns responses....
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New

Other popular topics Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

We're in Beta

About us Mission Statement