jdobrzanski

jdobrzanski

My question is around Ecto.Changeset and the need to validate entire models, not just the passed in params. Basically, I’ve found a useful pattern is to write a set of validations; for a specific action; against the model after the params are filter; and after the params are applied. The first two items were awkward to do in rails 4 while the later easy. So if a model is loaded from the database, the passed in params in combination to the fields already set on the model (or perhaps in the session) are what are validated. Validating just the passed in params is also useful (eg. enforcing that the password was sent along with the sensitive account update request) but done less often.

Ecto.Changest is exciting because it decouples the changes from the model, however, most of the validations run only against the params, not the fields in the data after the params are applied. What I want is the option to validate_change, etc using not get_change nor really even get_field but just the data field after the params are filtered and cast. Obviously if the changes make the model invalid then the model won’t be saved (and one could image a copy of the un-modified struct along with the modified version anyways). Technically using get_field could work as well.

Rewriting new functions that apply the changes and then validate the model seem to not be in spirit with Ecto.Changeset and I wish there is a solution that could work with existing models and libraries that leverage it.
I am looking for thoughts around how these types of changes are meant to be handled in elixir (especially during a typical request to update a resource in Phoenix) and how that pattern can fit into this. Radical departures to what I am looking for are great to hear but having a specific answer is also appreciated.

Showing Posts 1 to 5

LostKobrakai

LostKobrakai

get_change(changeset, :field) is basically the same as changeset |> apply_changes() |> Map.get(:field), so I’m not really sure what you’re missing for it. Also Ecto.Changeset does validate just the changes, as the idea is that a given source struct is already valid and only the params need to be validated, but you can just as well validate any given change against it’s consequences for the validity of the whole struct.

NobbZ

NobbZ

Can you give a more concrete example of what you want to achieve but currently is not possible?

I’m not sure if I understand what you want to say.

But it sounds as if you want to validate if a combination of fields is still valid even when only one has been changed?

Lets say the sum of :a and :b always have to be 10?

Shoouldn’t that be easily possible by a custom validator?

Something like:

if get_field(cs, :a) + get_field(cs, :b) != 10 do
  cs
  |> add_error(:a, "Must sum to 10", [other: :b])
  |> add_error(:b, "Must sum to 10", [other: :a])
else
  cs
end
peerreynders

peerreynders

I think that is usually referred to as cross-field validation (in contrast to field level validation).

Shouldn’t that be easily possible by a custom validator?

+1


Ecto.Changeset.get_field/3:

While get_change/3 only looks at the current changes to retrieve a value, this function looks at the changes and then falls back on the data, finally returning default if no value is available.

jdobrzanski

jdobrzanski OP

Thanks for the help! I’ve had to move ahead today with progress so I’m basically taking @NobbZ advice. Soon I want to take the time to post concrete examples with embedded form schemas, ecto schemas, hybrids, etc. Once all of the examples are laid out it should be clear what the general pattern that I am looking for is that works well with each example.

OvermindDL1

OvermindDL1

Or go the python way and add a Future module built-in to Elixir or so that when used like use Future, otp: 21 then it compiles with OTP 21 features or so, though this might require the Elixir source itself to be built for multiple OTP versions and to load them based on the declaration (thus the use Future, ... bit might have to be in the mix.exs file?).

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews