在变更集属性进入数据库之前对其进行转换

问题描述 投票:0回答:2

我将一个textarea添加到Elixir表单中,然后将值设置为string并将字符串放入jsonb类型的数据库元数据列中。 textarea中的字符串我希望用新行分割并存储arraystrings而不是只有一个大字符串。

我已经改变了类型如下。

field :names, {:array, :string} 

但是我不确定如何使用Ecto拦截这些数据并在它进入数据库之前将其拆分。

我看过:

似乎我可以在架构中添加validation函数,这是我的尝试。

def changeset(schema, params \\ %{}) do
    schema
    |> cast(params, @required, @optional)
    |> validate_name()
end

defp validate_names(changeset) do
    # fetch_field(changeset, :names)
    # Map.put(changeset, :names, String.split(:names, "\r\n"))
end

如何更改Elixir对象中一个属性的值?

更新:

person_metadata.ex

defmodule DB.PersonMetadata do
  use DB.Schema

  embedded_schema do
    field :names, :string
  end

  @required ~w()
  @optional ~w(names)

  def changeset(schema, params \\ %{}) do
    schema
    |> cast(params, @required, @optional)
    |> validate_names()
  end

  defp validate_names(changeset) do
    case get_field(changeset, :names) do
      # Don't do anything if names don't exist
      nil ->
        changeset

      # Update names if they do exist
      names ->
        new_names = String.split(names, "\n")
        put_change(changeset, :names, new_names)
    end
  end

  def types, do: @types
end
elixir phoenix-framework ecto
2个回答
2
投票

试试这个:

defp validate_names(changeset) do
  case get_field(changeset, :names) do
    # Don't do anything if names don't exist
    nil ->
      changeset

    # Update names if they do exist
    names ->
      new_names = String.split(names, "\r\n")
      put_change(changeset, :names, new_names)
  end
end

0
投票

似乎整个自定义函数现在可以(因为何时?)被Ecto.Changeset.update_change/3取代

 |> update_change(:names, fn
     nil -> nil # or preferably []?
     names -> String.split(names, ~r{\r?\n})
    end)

或者作为一种风格问题

 |> update_change(:names, &my_name_splitter/1)
© www.soinside.com 2019 - 2024. All rights reserved.