Ecto es la herramienta principal para interactuar con bases de datos en el ecosistema de Elixir. Más que un simple ORM, Ecto combina la construcción de consultas, validaciones y migraciones, brindando una experiencia robusta y funcional.
Ecto es un toolkit para bases de datos en Elixir que se compone de tres partes principales:
- Ecto.Schema: Define la estructura de los datos.
- Ecto.Changeset: Maneja validaciones y transformaciones.
- Ecto.Query: Facilita la construcción de consultas.
Para empezar debemos añadir las dependencias en mix.exs:
defp deps do
[
{:ecto_sql, "~> 3.10"},
{:postgrex, ">= 0.0.0"} # Adaptador para PostgreSQL
]
end
Luego debemos configurar el repositorio en config/config.exs:
config :mi_app, MiApp.Repo,
database: "mi_app_db",
username: "usuario",
password: "contraseña",
hostname: "localhost"
config :mi_app, ecto_repos: [MiApp.Repo]
Crear el repositorio:
mix ecto.gen.repo -r MiApp.Repo
Para luego ejecutar migraciones iniciales:
mix ecto.create
Creamos un módulo para tu esquema, que representa una tabla en la base de datos:
defmodule MiApp.Usuario do
use Ecto.Schema
schema "usuarios" do
field :nombre, :stringfield :email, :string
field :edad, :integer
timestamps()
end
end
Y ahora hagamos consultas básicas con Ecto.Query. Ecto ofrece una sintaxis declarativa para construir consultas SQL. Ejemplo:
import Ecto.Query
# Obtener todos los usuarios
query = from u in "usuarios", select: u
MiApp.Repo.all(query)
# Filtrar usuarios mayores de 18 años
query = from u in MiApp.Usuario, where: u.edad > 18, select: u.nombre
MiApp.Repo.all(query)
Los cambios en los datos se gestionan con Ecto.Changeset, lo que facilita aplicar validaciones.
defmodule MiApp.Usuario do
use Ecto.Schema
import Ecto.Changeset
schema "usuarios" do
field :nombre, :string
field :email, :string
field :edad, :integer
timestamps()
end
def cambios_usuario(usuario, attrs) do
usuario
|> cast(attrs, [:nombre, :email, :edad])
|> validate_required([:nombre, :email])
|> validate_format(:email, ~r/@/)
|> validate_number(:edad, greater_than_or_equal_to: 0)
end
end
Ecto permite definir relaciones como has_many, belongs_to y many_to_many. Veamos un ejemplo:
defmodule MiApp.Usuario do
use Ecto.Schema
schema "usuarios" do
field :nombre, :string
has_many :posts, MiApp.Post
timestamps()
end
end
defmodule MiApp.Post do
use Ecto.Schema
schema "posts" do
field :titulo, :string
belongs_to :usuario, MiApp.Usuario
timestamps()
end
end
Consultas relacionales:
query = from u in MiApp.Usuario, preload: [:posts]
usuarios = MiApp.Repo.all(query)
Ahora actualización de registros:
usuario = MiApp.Repo.get(MiApp.Usuario, 1)
cambioset = MiApp.Usuario.cambios_usuario(usuario, %{nombre: "Nuevo Nombre"})
MiApp.Repo.update(cambioset)
Y Borramos:
usuario = MiApp.Repo.get(MiApp.Usuario, 1)
MiApp.Repo.delete(usuario)
Las migraciones permiten gestionar cambios en el esquema de la base de datos.
Crear una migración:
mix ecto.gen.migration crea_usuarios
Editar la migración:
defmodule MiApp.Repo.Migrations.CreaUsuarios do
use Ecto.Migration
def change do
create table(:usuarios) do
add :nombre, :string
add :email, :string
add :edad, :integer
timestamps()
end
end
end
Ejecutar migración:
mix ecto.migrate
Ecto transforma la interacción con bases de datos en una experiencia declarativa, segura y extensible. Ya sea que estés manejando datos simples o esquemas complejos, Ecto te da las herramientas para hacerlo de manera eficiente.