title: Transform a changeset property before it goes into the database
body: <p>I added a <code>textarea</code> to an Elixir form, and I set the value to a <code>string</code> and have got the string into a database metadata column that is of a <code>jsonb</code> type. The string in the <code>textarea</code> I wish to split by new-line and store an <code>array</code> of <code>strings</code> rather then just one big string.</p>
  
  <p>I have since changed the type as follows.</p>
  
  <pre><code>field :names, {:array, :string} 
  </code></pre>
  
  <p>However I am unsure how to use Ecto to intercept this data and split it before it enters the database. </p>
  
  <p>I have looked at:</p>
  
  <ul>
  <li><a href="https://hexdocs.pm/ecto/Ecto.Changeset.html" rel="nofollow noreferrer">Ecto.Changeset</a> Documentation</li>
  <li><a href="https://devhints.io/phoenix-ecto" rel="nofollow noreferrer">Phoenix: Ecto cheatsheet</a></li>
  <li><a href="http://cultofmetatron.io/2017/04/22/thinking-in-ecto---schemas-and-changesets/" rel="nofollow noreferrer">Thinking in Ecto - schemas and changesets</a> Blog Post</li>
  </ul>
  
  <p>It seems that I can add a <code>validation</code> function to the schema, this is my attempt.</p>
  
  <pre><code>def changeset(schema, params \\ %{}) do
      schema
      |&gt; cast(params, @required, @optional)
      |&gt; validate_name()
  end
  
  defp validate_names(changeset) do
      # fetch_field(changeset, :names)
      # Map.put(changeset, :names, String.split(:names, "\r\n"))
  end
  </code></pre>
  
  <p>How do I change the value of one property in an Elixir object?</p>
  
  <p>Update:</p>
  
  <blockquote>
    <p>person_metadata.ex</p>
  </blockquote>
  
  <pre><code>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
      |&gt; cast(params, @required, @optional)
      |&gt; validate_names()
    end
  
    defp validate_names(changeset) do
      case get_field(changeset, :names) do
        # Don't do anything if names don't exist
        nil -&gt;
          changeset
  
        # Update names if they do exist
        names -&gt;
          new_names = String.split(names, "\n")
          put_change(changeset, :names, new_names)
      end
    end
  
    def types, do: @types
  end
  </code></pre>