Using atom values with `fragment`

Hi!

I’ve been using Ecto.Enum a lot lately on citext fields on the database and atoms on the schema as it maps perfectly to Absinthe enums.
Recently I stumbled upon a small issue, though. For instance, when I want to use select on a given field to change its value in a query:

Object
|> select([obj], 
    %{obj | 
        status: fragment("CASE WHEN ? THEN 'IS_OLD' ELSE ? END", 
            obj.date < from_now(0, "day"), 
            obj.status)
|> Repo.all()

The problem here is that I can’t use atoms on fragments (it wouldn’t make sense from the database standpoint) but then it always returns a string back instead of atoms.

Is there any way I can achieve that that doesn’t involve mapping through the result and making the conversion?

Thank you!

You can use Ecto.Query.API.type/2:

type(
  fragment("CASE WHEN ? THEN 'IS_OLD' ELSE ? END", true, "MY_AWESOME_STATUS"),
  ^{:parameterized, Ecto.Enum, Ecto.Enum.init(values: [:IS_OLD, :MY_AWESOME_STATUS])}
)
3 Likes

Or type(fragment(…), obj.status) if :status is the Ecto.Enum field.

2 Likes

This is amazing!

And this is even better for my specific use case!

Thank you guys!