Should I use old-fashioned DB lookup tables? What might be some alternatives?
I realize not all mapped values are the same. Some have a very small set number of KVs (int id => 5-point scale). Some have a larger (int id => country code). Some have an indefinite set of KVs.
In which cases (if not all) would you recommend DB lookup tables with Ash
relationships
. Would you recommend an alternative? I had considered for small sets to use a calculation, but I think that works with reads but not writes, right?6 Replies
Its hard to say really. I'd probably have to choose situationally.
I don't think size is really the constraint, its more like editability
I'd use lookup tables if I want to be able to dynamically at runtime change the list of things
For country codes, for example, I'd use an enum because its static, people aren't creating more country codes
Okay,
Ash.Type.Enum
is a good callout for certain situations. Is there an example of that usage (didn't see one in ash_hq) and how it works with Postgres?It doesn't create an enum type in postgres migrations or anything like that
it is just represented as a string under the hood
use Ash.Type.Enum, values: [:foo, :bar, :baz]
a string in postgres I meanI see. I wish there was a callback or something to specify underlying value. Something like:
That'd make Enum basically a complete in-code replacement for a static lookup table in the DB.
I suppose there's probably an escape hatch in Ash for something like this though. Be it in a
code_interface
or custom action or something like that.You could do that with a custom type pretty easily, but I'm curious why you'd want to bother with having a mapping at all and not just using the value
But you could do something like this:
Yeah, I think custom types is exactly what I'm looking for. I totally missed that section in the docs.
TLDR;
Yes, you should probably in many cases still use old-fashioned lookup tables. This gives the benefit of run-time editability and additions of values. For key/value mappings that are super-definitely static, two options exist:
Ash.Type.Enum
and making your own custom type.
For Enums, the atom is converted to a string (:ci_string
I think) and stored in DB like that. This can fall prey to larger table storage as you're storing copies of each string as opposed to an ID pointing at the same value. Custom types can help with this since you can define two-way translations.