Basics
Ecto — это официальный проект на Elixir, предоставляющий оболочку для работы с базами данных и интегрированный язык запросов. С помощью Ecto мы можем создавать миграции, определять схемы, вставлять и обновлять записи, а также выполнять запросы к ним.
Адаптеры
Ecto поддерживает различные базы данных через использование адаптеров. Несколько примеров адаптеров:
- PostgreSQL
- MySQL
- SQLite
В этом уроке мы настроим 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!