2016-05-21 23 views
1

我有一個應用程序,用戶可以發送自定義數據,它將存儲在我的應用程序中。目前,我做這樣的事情:多態嵌入式JSON值類型?

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 

目前我省的一切作爲一個字符串,並保持一個類型字段轉換我的應用程序和數據庫之間的數據類型。另外,我必須將所有內容都轉換爲字符串,因爲Ecto(AFAIK)不支持在嵌入式JSON中使用多態類型。

這是關於索引字段和值問題嗎?

我想用自定義的外生型的,但這是不可能的,因爲我是如何依賴於我的轉換函數的兩個值(鑄造日期的時候,我看到的字段名稱爲「_at」結束)

有沒有更好的方法來實現這個目標?

回答

1

如果您使用Postgres作爲您的數據庫,那麼您想要的行爲已經存在。您需要在架構中使用:map數據類型。你可以這樣做:

defmodule MyApp.CustomField do 
    use Ecto.Schema 
    import Ecto.Changeset 
    alias MyApp.{ Time } 

    embedded_schema do 
    field :data, :map 
    end 
end 

然後你可以做%CustomField{data: %{"field" => "custom", "value" => 1}} |> Repo.insert!1這裏將在您的data列中以JSON形式存儲爲整數。當您從數據庫中獲取此記錄時,Ecto將使用像毒藥這樣的JSON序列化程序來解碼JSON數據,並且它將在Elixir中以整數形式返回1

+0

但是這樣就不可能做任何驗證,是嗎? – Tarlen

+0

用這個做驗證仍然是可能的。你有什麼樣的驗證?你他們沒有工作嗎? – Gjaldon

+0

例如值的長度 – Tarlen