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 <название>, так что в нашем случае используем: ```shell mix ecto.gen.migration create_people ``` Это создаст новый файл в папке
priv/repo/migrationsс меткой времени в имени файла. Если мы перейдем в наш каталог и откроем миграцию, мы должны увидеть что-то вроде этого: ```elixir defmodule Friends.Repo.Migrations.CreatePeople do use Ecto.Migration def change do end end ``` Начнем с изменения функции
change/0, чтобы создать новую таблицу
peopleс полями
nameи
age: ```elixir 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. Перейдем в командную строку и запустим нашу миграцию: ```shell mix ecto.migrate ``` ### Схемы Теперь, когда мы создали нашу начальную таблицу, нам нужно сообщить Ecto больше о ней, и мы делаем это через схемы. Схема — это модуль, который определяет сопоставления с полями таблиц базы данных. Хотя Ecto предпочитает использовать множественное число для имен таблиц в базе данных, схема обычно имеет единственное число, поэтому мы создадим схему
Personдля нашей таблицы. Создадим новую схему в
lib/friends/person.ex: ```elixir 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и создав нового человека: ```elixir iex> %Friends.Person{} %Friends.Person{age: 0, name: nil} ``` Как и ожидалось, мы получаем нового
Personс примененным значением по умолчанию для
age`.
Теперь давайте создадим “реального” человека:
elixir iex> person = %Friends.Person{name: "Tom", age: 11} %Friends.Person{age: 11, name: "Tom"}
Поскольку схемы — это просто структуры, мы можем взаимодействовать с нашими данными так, как мы привыкли:
elixir iex> person.name "Tom" iex> Map.get(person, :name) "Tom" iex> %{name: name} = person %Friends.Person{age: 11, name: "Tom"} iex> name "Tom"
Точно так же мы можем обновлять наши схемы, как и любые другие карты или структуры в Elixir:
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!