Hi
I have an app where users can send custom data.
Currently I do something like this:
defmodule MyApp.CustomField do
use Ecto.Schema
import Ecto.Changeset
alias MyApp.{ Time }
defmodule ValueTypes do
def c_INTEGER, do: "integer"
def c_BOOLEAN, do: "boolean"
def c_STRING, do: "string"
def c_TRUE, do: "true"
def c_FALSE, do: "false"
end
embedded_schema do
field :field
field :value
field :type
end
@required_fields ~w( field value )
@optional_fields ~w( type )
def changeset(model, params \\ :empty) do
{:ok, value, type} = cast(model.field, model.value)
params = %{value: value, type: type}
model
|> cast(params, @required_fields, @optional_fields)
|> validate_length(:field, min: 1, max: 20)
|> validate_length(:value, min: 1, max: 255)
|> put_change(:type, type)
end
# date in unix timestamp
def cast(field, value) when is_integer(value) do
value = Integer.to_string(value)
case String.slice(field, -3, 3) do
"_at" -> {:ok, value, ValueTypes.c_DATE}
_ -> {:ok, value, ValueTypes.c_INTEGER}
end
end
def cast(field, value) when is_boolean(value), do: {:ok, (if value, do:
ValueTypes.c_TRUE, else: ValueTypes.c_FALSE), ValueTypes.c_BOOLEAN}
def cast(field, value) when is_binary(value), do: {:ok, value, ValueTypes
.c_STRING}
def cast(field, value), do: {:error, "Invalid field value"}
end
Currently I save everything as a string and keep a Type field to convert
datatypes between my app and the DB. Also, I have to convert everything to
a string, because Ecto (AFAIK) does not support having polymorphic types in
embedded JSON.
I thought of using custom Ecto types, but this is not possible due to how I
depend on two values in my cast function (when casting dates, I look at the
end of the field name for "_at")
Is there a better way to accomplish this?
--
You received this message because you are subscribed to the Google Groups
"elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-talk/143d8c99-cdfa-48a1-9773-a7c909980c2c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.