Reputation: 59495
I added a textarea
to an Elixir form, and I set the value to a string
and have got the string into a database metadata column that is of a jsonb
type. The string in the textarea
I wish to split by new-line and store an array
of strings
rather then just one big string.
I have since changed the type as follows.
field :names, {:array, :string}
However I am unsure how to use Ecto to intercept this data and split it before it enters the database.
I have looked at:
It seems that I can add a validation
function to the schema, this is my attempt.
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
How do I change the value of one property in an Elixir object?
Update:
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
Upvotes: 0
Views: 2387
Reputation: 75820
Try this:
defp validate_names(changeset) do
case get_change(changeset, :names) do
# Update name if it's a string
names when is_binary(names) ->
new_names = String.split(names, "\r\n")
put_change(changeset, :names, new_names)
# Don't do anything if nil or already an array
_other ->
changeset
end
end
Upvotes: 4
Reputation: 1258
Seems the whole custom function can now (since when?) be replaced by Ecto.Changeset.update_change/3
|> update_change(:names, fn
nil -> nil # or preferably []?
names -> String.split(names, ~r{\r?\n})
end)
or as a matter of style
|> update_change(:names, &my_name_splitter/1)
Upvotes: 4