Cra*_*ein 9 elixir ecto phoenix-framework
我是凤凰城/ Elixir的新手,我正试图围绕变革集团.
我知道它包含一组用于创建或更新模型的更改.
我想知道的是,在将更改推送到数据库之前,是否以及如何修改更改.
我的用例如下:
由于不变性约束,我甚至不确定是否可以直接修改变更集,但我可以创建另一个变更集以插入仓库.
欢迎任何建议,并毫不犹豫地指出我可能正在做的不良做法或愚蠢的事情!
编辑以下评论:我正在寻找类似的东西:
defp put_specialty_array(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{specialty: spec}} ->
put_change(changeset, :specialty, String.split(spec, ","))
_ ->
changeset
end
end
Run Code Online (Sandbox Code Playgroud)
小智 11
我相信你要找的是一个自定义的Ecto.Type.我一直这样做,效果很好!它看起来像这样:
defmodule MyApp.Tags do
@behaviour Ecto.Type
def type, do: {:array, :string}
def cast(nil), do: {:ok, nil} # if nil is valid to you
def cast(str) when is_binary(str) do
str
|> String.replace(~r/\s/, "") # remove all whitespace
|> String.split(",")
|> cast
end
def cast(arr) when is_list(arr) do
if Enum.all?(arr, &String.valid?/1), do: {:ok, arr}, else: :error
end
def cast(_), do: :error
def dump(val) when is_list(val), do: {:ok, val}
def dump(_), do: :error
def load(val) when is_list(val), do: {:ok, val}
def load(_), do: :error
end
Run Code Online (Sandbox Code Playgroud)
然后在迁移中添加具有正确类型的列
add :tags, {:array, :string}
Run Code Online (Sandbox Code Playgroud)
最后在您的架构中指定您创建的字段类型.
field :tags, MyApp.Tags
Run Code Online (Sandbox Code Playgroud)
然后,您只需将其添加为变更集中的字段即可.如果您的类型:error的强制转换返回,那么变更集将出现类似的错误{:tags, ["is invalid"]}.您不必担心模型或控制器中的字段处理.如果用户为值发布字符串数组或只是逗号分隔的字符串,它将起作用.
如果需要以不同的格式将值保存到数据库,则只需更改返回值,def type并确保def dump返回该类型的值,并且def load可以将该类型的值读取到所需的任何内部表示形式.一种常见的模式是为内部表示定义一个结构,以便您可以自己实现Poison to_json,甚至可以返回一个简单的字符串.一个例子可能是12.12345N,123.12345W在json 中编码的LatLng类型,在postgres中存储为某种GIS类型,但是有一个类似的结构%LatLng{lat: 12.12345, lng: -123.12345}允许你在elixir中做一些简单的数学运算.DateTime格式的工作方式非常类似(有一个elixir结构,db驱动程序的元组格式和json的ISO格式).
我认为这对密码字段非常有用,顺便说一句.您可以压缩JSON表示,使用结构来表示算法,算法的参数将哈希与盐分开,或者其他任何使生活变得容易的事情.在您的代码中,要更新密码,它就是Ecto.Changeset.change(user, password: "changeme").
我意识到这是一个6个月大的问题,你可能已经找到了一些东西,但我最终来自谷歌搜索,并假设其他人也会.