2016-08-23 81 views
2

我有一個玩具項目可以幫助我學習Elixir/Phoenix。Elixir的自定義類型

我從csv導入一些數據,我想根據我的變更集將這些記錄插入到數據庫中。

我的問題是,有時通常包含一個整數的列之一將有「不適用」。這會導致變更集無效,因爲它應該如此。

我不確定Elixir的標準方法是什麼。

在這種情況下,我只是想「N/A」轉換爲0。

你通常會寫這個,做那個轉換自定義類型?

https://hexdocs.pm/ecto/Ecto.Type.html

在Rails我可能會解決這個問題上使用了定製的setter模型或在before_save什麼的。

回答

4

我會在模型的changeset函數中通過「修復」params來執行此操作,然後將其發送到cast進行驗證。

範例模型與:count整數字段:

def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(fix_params(params), [:count]) 
    |> validate_required([:count]) 
end 

defp fix_params(%{count: "n/a"} = params), do: %{params | count: 0} 
defp fix_params(params), do: params 

演示:

iex(1)> Counter.changeset(%Counter{}, %{count: 123}) 
#Ecto.Changeset<action: nil, changes: %{count: 123}, errors: [], 
data: #MyApp.Counter<>, valid?: true> 
iex(2)> Counter.changeset(%Counter{}, %{count: "n/a"}) 
#Ecto.Changeset<action: nil, changes: %{count: 0}, errors: [], 
data: #MyApp.Counter<>, valid?: true> 
iex(3)> Counter.changeset(%Counter{}, %{count: "foo"}) 
#Ecto.Changeset<action: nil, changes: %{}, 
errors: [count: {"is invalid", [type: :integer]}], data: #MyApp.Counter<>, 
valid?: false> 

如果要任何非整數值轉換爲0時,可以這樣做:

defp fix_params(%{count: count} = params) when not is_integer(count), do: %{params | count: 0} 
defp fix_params(params), do: params 

演示:

iex(1)> Counter.changeset(%Counter{}, %{count: "foo"}) 
#Ecto.Changeset<action: nil, changes: %{count: 0}, errors: [], 
data: #MyApp.Counter<>, valid?: true> 
+0

Thanks @Dogbert!我沒有看到很多使用自定義類型的好例子。這是最受歡迎的http://learningelixir.joekain.com/custom-types-in-ecto/。我猜想使用自定義類型與「更乾淨」功能的決定歸結爲你需要做的複雜性? – jacklin