Save JSON/embed without specifying types?

34 views
Skip to first unread message

Nytz12

unread,
May 20, 2016, 3:11:28 PM5/20/16
to elixir-lang-talk
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?


Reply all
Reply to author
Forward
0 new messages