Do you want to pick up from where you left of?
Take me there

Basics

Ecto — это официальный проект на Elixir, предоставляющий оболочку для работы с базами данных и интегрированный язык запросов. С помощью Ecto мы можем создавать миграции, определять схемы, вставлять и обновлять записи, а также выполнять запросы к ним.

Адаптеры

Ecto поддерживает различные базы данных через использование адаптеров. Несколько примеров адаптеров:

В этом уроке мы настроим Ecto для использования адаптера PostgreSQL.

Начало работы

В этом уроке мы рассмотрим три части Ecto:

Для начала мы создадим приложение с деревом надзора.

mix new friends --sup
cd friends

Добавьте зависимости ecto и postgrex в ваш файл mix.exs.

  defp deps do
    [
      {:ecto_sql, "~> 3.2"},
      {:postgrex, "~> 0.15"}
    ]
  end

Получите зависимости с помощью команды

mix deps.get

Создание Репозитория

Репозиторий в Ecto сопоставляется с хранилищем данных, таким как наша база данных Postgres. Вся связь с базой данных будет осуществляться с использованием этого репозитория.

Настройте репозиторий, выполнив команду:

mix ecto.gen.repo -r Friends.Repo

Это создаст конфигурацию, необходимую в config/config.exs для подключения к базе данных, включая используемый адаптер. Это конфигурационный файл для нашего приложения Friends.

config :friends, Friends.Repo,
  database: "friends_repo",
  username: "postgres",
  password: "",
  hostname: "localhost"

Это настраивает, как Ecto будет подключаться к базе данных. Вам может потребоваться настроить базу данных с соответствующими учетными данными.

Также создается модуль Friends.Repo внутри lib/friends/repo.ex.

defmodule Friends.Repo do
  use Ecto.Repo,
    otp_app: :friends,
    adapter: Ecto.Adapters.Postgres
end

Мы будем использовать модуль Friends.Repo для выполнения запросов к базе данных. Мы также указываем этому модулю искать информацию о конфигурации базы данных в приложении Elixir :friends и выбрали адаптер Ecto.Adapters.Postgres.

Далее мы настроим Friends.Repo как супервизор в дереве надзора нашего приложения в lib/friends/application.ex. Это запустит процесс Ecto при запуске нашего приложения.

  def start(_type, _args) do
    # Список всех дочерних процессов для надзора
    children = [
      Friends.Repo,
    ]

  ...

После этого нам нужно добавить следующую строку в файл config/config.exs:

config :friends, ecto_repos: [Friends.Repo]

Это позволит нашему приложению выполнять команды ecto mix из командной строки.

Мы завершили настройку репозитория! Теперь мы можем создать базу данных в postgres с помощью этой команды:

mix ecto.create

Ecto использует информацию из файла config/config.exs, чтобы определить, как подключиться к Postgres и какое имя дать базе данных.

Если вы получите какие-либо ошибки, убедитесь, что информация о конфигурации верна и что ваш экземпляр postgres запущен.

Миграции

Для создания и изменения таблиц в базе данных postgres Ecto предоставляет нам миграции. Каждая миграция описывает набор действий, которые должны быть выполнены в нашей базе данных, такие как создание или обновление таблиц.

Поскольку в нашей базе данных еще нет таблиц, нам нужно создать миграцию, чтобы добавить их. В Ecto принято использовать множественное число для имен таблиц. Для нашего приложения нам понадобится таблица people, поэтому начнем с миграций для нее.

Лучший способ создать миграцию — это использовать задачу mix ecto.gen.migration <название>, так что в нашем случае используем:

mix ecto.gen.migration create_people

Это создаст новый файл в папке priv/repo/migrations с меткой времени в имени файла. Если мы перейдем в наш каталог и откроем миграцию, мы должны увидеть что-то вроде этого:

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do

  end
end

Начнем с изменения функции change/0, чтобы создать новую таблицу people с полями name и age:

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do
    create table(:people) do
      add :name, :string, null: false
      add :age, :integer, default: 0
    end
  end
end

Вы можете видеть, что мы также определили тип данных для столбцов. Кроме того, мы включили опции null: false и default: 0.

Перейдем в командную строку и запустим нашу миграцию:

mix ecto.migrate

Схемы

Теперь, когда мы создали нашу начальную таблицу, нам нужно сообщить Ecto больше о ней, и мы делаем это через схемы. Схема — это модуль, который определяет сопоставления с полями таблиц базы данных.

Хотя Ecto предпочитает использовать множественное число для имен таблиц в базе данных, схема обычно имеет единственное число, поэтому мы создадим схему Person для нашей таблицы.

Создадим новую схему в lib/friends/person.ex:

defmodule Friends.Person do
  use Ecto.Schema

  schema "people" do
    field :name, :string
    field :age, :integer, default: 0
  end
end

Здесь мы видим, что модуль Friends.Person сообщает Ecto, что эта схема относится к таблице people и что у нас есть два столбца: name, который является строкой, и age, целое число с значением по умолчанию 0.

Давайте взглянем на нашу схему, открыв iex -S mix и создав нового человека:

iex> %Friends.Person{}
%Friends.Person{age: 0, name: nil}

Как и ожидалось, мы получаем нового Person с примененным значением по умолчанию для age. Теперь давайте создадим “реального” человека:

iex> person = %Friends.Person{name: "Tom", age: 11}
%Friends.Person{age: 11, name: "Tom"}

Поскольку схемы — это просто структуры, мы можем взаимодействовать с нашими данными так, как мы привыкли:

iex> person.name
"Tom"
iex> Map.get(person, :name)
"Tom"
iex> %{name: name} = person
%Friends.Person{age: 11, name: "Tom"}
iex> name
"Tom"

Точно так же мы можем обновлять наши схемы, как и любые другие карты или структуры в Elixir:

iex> person = %{person | age: 18}
%Friends.Person{age: 18, name: "Tom"}
iex> Map.put(person, :name, "Jerry")
%Friends.Person{age: 18, name: "Jerry"}

В нашем следующем уроке о Changesets мы рассмотрим, как проверять наши изменения данных и, наконец, как сохранять их в нашу базу данных.

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!