Using ex_money_sql with Ash
metlnerd:
I’m hoping to use the
Money
type defined in the
ex_money
library as an attribute in Ash resources. This library has a companion,
ex_money_sql
that creates a Postgres migration and creates a custom type:
def up do
execute("CREATE TYPE public.money_with_currency AS (currency_code varchar, amount numeric);")
end
In the documentation, there’s a
Money
struct, a
:money_with_currency
, a
Money.Ecto.Composite.Type
all used in various places. I’m very new to Elixir, Ash, and Ecto so it’s all a bit confusing.
I’m assuming I need a Custom Ash Type (right?), but not sure which identifiers mean what - for example, the existing examples for an Ash custom type all use an atom like
:map
or
:string
for
storage_type
, but it isn’t clear to me how they get defined, and if Ash would be able to see custom types in Postgres. Should I bypass the
_sql
library and roll my own
:map
-based solution?
ZachDaniel:
I believe using
storage_type
of
:money_with_currency
should pretty much do it for you as that will end up mapping to the exact sql type. There are a lot of layers there, basically because we build on top of ecto and they have some named storage types (like :map)
metlnerd:
Thanks, I ended up with this:
metlnerd:
defmodule Worthy.AshMoney do
use Ash.Type
@impl true
def storage_type, do: :money_with_currency
@impl true
def cast_input(value, _) do
Ecto.Type.cast(Money.Ecto.Composite.Type, value)
end
@impl true
def cast_stored(value, _) do
Ecto.Type.load(Money.Ecto.Composite.Type, value)
end
@impl true
def dump_to_native(value, _) do
Ecto.Type.dump(Money.Ecto.Composite.Type, value)
end
end
ZachDaniel:
You’ll probably want to handle nil values in those callbacks
ZachDaniel:
Unlike ecto we give types control over nil values
metlnerd:
SG, thanks