DEV Community

Tyler Smith
Tyler Smith

Posted on

Creating a text column using Ecto in Elixir's Phoenix framework

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, 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–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:

mix phx.gen.schema BlogPost blog_post title:string content:text
Enter fullscreen mode Exit fullscreen mode

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:

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

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

Enter fullscreen mode Exit fullscreen mode

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 in the Elixir Forum: Ecto migrations will pass along any type that it doesn't recognize as-is (see Ecto's source code).

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

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

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


  # Other code...
Enter fullscreen mode Exit fullscreen mode

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:

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 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!

Top comments (2)

nickciolpan profile image
Nick Ciolpan

Great job writing this!

tylerlwsmith profile image
Tyler Smith

Hey thanks Nick! 😊