Skip to main content

Ecto Overview

Ecto is a database wrapper and query generator for Elixir, a functional programming language built on top of the Erlang virtual machine (BEAM).

Ecto provides a high-level API for interacting with databases, making it easier to work with data and perform database operations.

In this tutorial, we will explore the history, features, and examples of using Ecto in Elixir applications.

History of Ecto

Ecto was initially released in 2015 by José Valim, the creator of Elixir. It was created to provide a powerful and flexible way to interact with databases in Elixir applications. Since then, Ecto has become one of the most popular database libraries in the Elixir ecosystem, widely used for building scalable and reliable applications.

Features of Ecto

Ecto offers a wide range of features that simplify database operations and provide powerful abstractions for working with data. Some of the key features of Ecto include:

  1. Database Adapter Support: Ecto supports multiple database adapters, including PostgreSQL, MySQL, SQLite, and more. This allows developers to work with their preferred database systems.

  2. Schema and Migration: Ecto provides a schema-based approach to define and work with database tables. Schemas define the structure and relationships of the data, while migrations handle the creation and alteration of database tables.

    Example:

    defmodule MyApp.User do
    use Ecto.Schema

    schema "users" do
    field :name, :string
    field :age, :integer
    timestamps()
    end
    end
  3. CRUD Operations: Ecto simplifies the process of performing CRUD (Create, Read, Update, Delete) operations on the database. It provides functions like Repo.insert, Repo.get, Repo.update, and Repo.delete to perform these operations.

    Example:

    user = %MyApp.User{name: "John", age: 25}
    MyApp.Repo.insert(user)
  4. Querying: Ecto offers a powerful query DSL (Domain Specific Language) for constructing database queries. It supports various operators, joins, aggregations, and sorting to build complex queries.

    Example:

    query = from u in MyApp.User, where: u.age > 18, select: u.name
    MyApp.Repo.all(query)
  5. Transactions: Ecto supports database transactions, allowing multiple database operations to be grouped together and executed atomically. This ensures data consistency and integrity.

    Example:

    MyApp.Repo.transaction(fn ->
    MyApp.Repo.insert(user1)
    MyApp.Repo.insert(user2)
    end)
  6. Associations: Ecto provides a convenient way to define and work with database associations, such as one-to-one, one-to-many, and many-to-many relationships. This simplifies data retrieval and manipulation.

    Example:

    defmodule MyApp.Post do
    use Ecto.Schema

    schema "posts" do
    belongs_to :user, MyApp.User
    field :title, :string
    field :body, :string
    timestamps()
    end
    end
  7. Data Validation: Ecto includes built-in support for data validation. It allows developers to define validation rules for fields, ensuring that the data meets specific criteria before being saved to the database.

    Example:

    defmodule MyApp.User do
    use Ecto.Schema

    schema "users" do
    field :name, :string
    field :age, :integer
    timestamps()
    validate_required([:name, :age])
    validate_number(:age, greater_than: 0)
    end
    end

Examples of Using Ecto

Let's explore a few examples of using Ecto in practical scenarios:

  1. Connecting to a Database:

    # config/config.exs
    config :my_app, MyApp.Repo,
    adapter: Ecto.Adapters.Postgres,
    username: "postgres",
    password: "password",
    database: "my_app_dev",
    hostname: "localhost",
    pool_size: 10

    # lib/my_app/repo.ex
    defmodule MyApp.Repo do
    use Ecto.Repo, otp_app: :my_app
    end

    This example demonstrates how to configure Ecto to connect to a PostgreSQL database using the Ecto.Adapters.Postgres adapter.

  2. Performing CRUD Operations:

    user = %MyApp.User{name: "Alice", age: 30}
    MyApp.Repo.insert(user)

    In this example, we create a new user record and insert it into the database using the Repo.insert function.

  3. Querying Data:

    query = from u in MyApp.User, where: u.age > 18, select: u.name
    MyApp.Repo.all(query)

    This example demonstrates how to construct a query to retrieve the names of users over 18 years old.

  4. Working with Associations:

    user = %MyApp.User{name: "Bob", age: 25}
    post = %MyApp.Post{title: "Hello", body: "World", user: user}
    MyApp.Repo.insert(post)

    Here, we create a new post associated with a user and insert it into the database.

These examples provide a glimpse of how Ecto can be used to interact with databases in Elixir applications. For more information and detailed documentation, refer to the official Ecto website.