I would like to allow user input to include the decimal to input monetary values (doing UI validation with cleave.js), but have Ecto change the value to an int to save to the database.
Currently the form shows the following error when I click the form save button, which I can’t locate in any of the Phoenix or Ecto libraries:
"Please enter a valid value. The two nearest valid values are .."
This occurs whether or not the text_input using the cleave js tool (ie, appears to not be related to the cleave library).
Based on this info, it appears the message is coming from the Ecto validators. Any ideas how I can change Ecto to allow string, then intercept to remove the decimal for Ecto to write the record to the db?
Maybe you can create a custom ecto type that would convert decimals and floats to integers in dump or whatever callback is used to prepare the data for writing to db.
defmodule MyAlmostInteger do
@behaviour Ecto.Type
def type, do: :integer
def cast(number) when is_number(number) do
{:ok, number}
end
def cast(%Decimal{} = decimal) do
{:ok, decimal}
end
def cast(_other), do: :error
def load(int) when is_integer(int) do
{:ok, int}
end
def dump(%Decimal{} = decimal) do
{:ok, Decimal.to_integer(decimal)}
end
def dump(float) when is_float(float) do
{:ok, Float.to_integer(float)}
end
def dump(int) when is_integer(int) do
{:ok, int}
end
def dump(_other), do: :error
end
then in your schema
schema "some_table" do
# ...
field :some_column, MyAlmostInteger
# ...
end