Creating a text column using Ecto in Elixir's Phoenix framework
Tags: phoenix, ecto, elixir
Published: 2022-01-20 09:34:45

---
title: Creating a text column using Ecto in Elixir's Phoenix framework
published: true
description: 
tags: phoenix, ecto, elixir
---

If you're like me, you might be new to the Phoenix framework. Maybe you're building a blog and you want to use a `text` column for blog post content. You hastily glance though [Ecto's built-in types](https://hexdocs.pm/ecto/3.7.0/Ecto.Type.html#types), but you don't see a `text` type. You see `string`, but that turns into a `varchar` column after you run your migration. What gives&ndash;can you not create `text` columns with Phoenix & Ecto?

**Here's the good news: you _can_ create `text` columns with Phoenix.** It's actually super simple. Let's generate a blog post schema using Mix:

```sh
mix phx.gen.schema BlogPost blog_post title:string content:text
```

See where it says `content:text`? That's all there is to it. When you run `mix ecto.migrate`, the `content` column will have a type of `text`. However, it's worth exploring what this command actually does.

## Exploring the generated files

When we run the `mix phx.gen.schema` command, Phoenix generates two files:

- A **migration** file located at  `priv/repo/migrations/{datestring}_create_blog_posts.ex`
- A **schema** file located at `lib/{app_name}/blog_post.ex`

Let's first look at the **migration** file:

```elixir
defmodule Backend.Repo.Migrations.CreateBlogPost do
  use Ecto.Migration

  def change do
    create table(:blog_post) do
      add :title, :string
      add :content, :text

      timestamps()
    end
  end
end
```

This looks the way that we'd expect: we have a `content` column with a type of `text`. But `text` isn't a built-in Ecto type, so how does this work?

As user al2o3cr [points out](https://elixirforum.com/t/how-to-set-a-data-type-of-longtext-in-ecto-migration/36659/2) in the Elixir Forum: Ecto migrations will pass along any type that it doesn't recognize as-is (see [Ecto's source code](https://github.com/elixir-ecto/ecto_sql/blob/807246cd4b048417f350755153d7ad38b5ac294f/lib/ecto/adapters/myxql/connection.ex#L1064)).

Now let's look at the **schema** file at `lib/{app_name}/blog_post.ex`:

```elixir
defmodule Backend.BlogPost do
  use Ecto.Schema
  import Ecto.Changeset

  schema "blog_post" do
    field :content, :string
    field :title, :string

    timestamps()
  end

  # Other code...
end
```

Hold on, doesn't it say `field :content, :string` in the `schema` block? Why is it `:string` and not `:text`? What's going on here?

As the [Phoenix Docs mention](https://hexdocs.pm/phoenix/1.6.6/ecto.html#the-schema): 

> Ecto schemas are responsible for mapping Elixir values to external data sources, as well as mapping external data back into Elixir data structures.

The schema file is primarily concerned with the Elixir data type of the `content` column and mapping it to the database. It doesn't need to be concerned with the column type: that's already stored in the database once you've run your migration using `mix ecto.migrate`.

---

I hope this helps clarify what's going on under the hood as you use `text` columns in your own Phoenix apps. Special thank you to Nick Ciolpan for writing [this post](https://graffino.com/til/qRhKP0bQ5W-argumenterror-invalid-or-unknown-type-text-for-field) that helped me work through this problem.

If this saved you some time, please leave a like or a comment so I know it was helpful!