silverdr

silverdr

Ecto.Schema / Ecto.Changeset - optional, conditionally present fields

I have a – let’s call it ‘Parent’ schema, which embeds_one child schema. Basically a set of largely mutually exclusive key/value pairs. Something like (simplified here - actual schema is far larger):

		field :type, :string
		field :time, :time
		field :dom, :integer
		field :dow, :integer

Depending on the value in :type one of the following fields is required, while others are not relevant. I do all the casting, validating, including conditional validate_required in custom validating functions and I end up with a ready to use, valid changeset that gets persisted in a JSON field in the DB.

The problem is that ALL the fields get stored, even if they are not needed. I would like to have only the relevant fields to end up in the DB but at best I get something like:

{
  "type": "dow", 
  "time": null,
  "dom": null,
  "dow": 1
}

What can I do to have only

{
  "type": "dow", 
  "dow": 1
}

persisted, instead?

Most Liked

dimitarvp

dimitarvp

Instead of embedding a record, can’t you just have that be a free-from singular JSON field whose contents depend on the type column? That’s what I would do because that would also emulate pretty closely what strongly statically typed languages do with sum types (enums in Rust).

garrison

garrison

What you’re really looking for here is a “polymorphic embedded schema”, which is something that comes up every so often. I think someone even wrote a library for it, though I’ve never used it.

My personal opinion: If your data is unstructured, just use a map field (JSON column) and don’t worry so much about the schema - that’s what unstructured means, after all!

If your data is structured and you are worried about the schema, then you should probably be using actual tables. That’s what they’re for!

Of course, if you wanted to go in the opposite direction with an even more degenerate solution, I bet you could put the embedded schema in a virtual field and then parse it back out at the end of the parent’s changeset, drop the nulls, and dump it into a real map field. Of course, then your data wouldn’t be structured on the way out of the DB, but you could probably cook up a solution to that too if you really wanted. The Ecto.Type hack is probably better, though.

silverdr

silverdr

The question is “how”. I don’t see any straightforward path towards that, unless I drop the embeds_one from my “parent” model.

I see, roger.

Thanks for pointing out. This doesn’t bother me that much though as this config is read-heavy. If it’s get completely replaced once in a while doesn’t matter so much as reading it “all the time”.

Yup, precisely that.

No, I don’t :slight_smile: I index data, by which I want to retrieve (possibly aggregated) information. I don’t need to aggregate any information on configs as of now :wink:

It does. While I am not in the thousand keys range and don’t expect to ever get there. The hundred one doesn’t seem completely improbable. Which is the main reason I started this thread – how do I store only what is needed for a given configuration rather than just “everything”, including 90% of noise.

Where Next?

Popular in Questions Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
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
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement