Elixir Functions

 

Mastering Database Interaction with Ecto in Elixir: A Comprehensive Guide

Elixir, a functional, concurrent, general-purpose programming language, is built on the robust Erlang virtual machine (BEAM). Designed for creating scalable and maintainable applications with ease, it has become a preferred choice for businesses looking to hire Elixir developers for their projects.

One of the critical features that make Elixir so powerful is Ecto. Ecto is a domain-specific language used for writing queries and interacting with databases in Elixir. By providing a database wrapper, it ensures a tighter integration between databases and Elixir applications, contributing significantly to the skillset of Elixir developers.

In this blog post, we will delve into the basics of Ecto, discuss its features, and illustrate its practical usage. This can serve as a guide not only for those planning to hire Elixir developers but also for developers keen on mastering this powerful tool.

Mastering Database Interaction with Ecto in Elixir: A Comprehensive Guide

1. Ecto – An Overview

Ecto is not just an ORM (Object-Relational Mapping). Instead, it is a project that encompasses database wrappers and a data manipulation layer, providing a unified API to compose queries and perform database operations.

Ecto uses Elixir’s metaprogramming capabilities to provide a DSL for querying a repository of data. This approach simplifies data manipulation and allows developers to work with any data source, not just relational databases.

The key components of Ecto are:

  1. Schema: It is used to map any data source into Elixir structs.
  1. Changeset: It provides a way for filtering, casting, validating and defining constraints when manipulating structs.
  1. Repo: It is the layer responsible for communicating with the database.

Let’s explore these concepts further with examples.

2. Getting Started with Ecto

Before we start, ensure you have Elixir installed on your machine. Once Elixir is installed, you can create a new project with the Mix build tool.

```elixir
mix new ecto_example
cd ecto_example
```

To add Ecto and a database adapter (Postgrex for PostgreSQL) to your project, include the following in your `mix.exs` file:

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

Now fetch the dependencies:

```elixir
mix deps.get
```

3. Repo – The Gateway to the Database

First, we’ll create a Repo. You can think of a Repo as a gateway to your database. This is where you configure your database access. In the same application directory, create a new file `lib/ecto_example/repo.ex`:

```elixir
defmodule EctoExample.Repo do
  use Ecto.Repo, 
  otp_app: :ecto_example,
  adapter: Ecto.Adapters.Postgres
end
```

In `config/config.exs`, add the following configuration for the Repo:

```elixir
config :ecto_example, EctoExample.Repo,
  database: "ecto_example",
  username: "postgres",
  password: "postgres",
  hostname: "localhost"
```

To create the database, you can use Mix tasks provided by Ecto:

```elixir
mix ecto.create
```

4. Schema – Mapping Database to Elixir Structs

Next, we need to define a schema. A schema is a mapping from a database table to an Elixir struct. It defines the fields and their types, relationships, and more. Let’s create a `users` table and the associated User schema.

Create a new Ecto migration with:

```elixir
mix ecto.gen.migration create_users
```

This will create a new file in `priv/repo/migrations` with a timestamp in the filename. Open this file and update it:

```elixir
defmodule EctoExample.Repo.Migrations.CreateUsers do
  use Ecto.Migration

  def change do
    create table(:users) do
      add :name, :string
      add :email, :string

      timestamps()
    end

    create unique_index(:users, [:email])
  end
end
```

Now, you can run the migration with `mix ecto.migrate`.

Let’s define the User schema in `lib/ecto_example/user.ex`:

```elixir
defmodule EctoExample.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :email, :string

    timestamps()
  end
end
```

5. Changesets – Manipulating Structs and Data Validation

Changesets are a way to filter, cast, validate, and define constraints when manipulating structs. They play a crucial role in handling user input and avoiding invalid data in the database.

Let’s define a changeset for the User struct:

```elixir
defmodule EctoExample.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :email, :string

    timestamps()
  end

  def changeset(user, attrs) do
    user
    |> Ecto.Changeset.cast(attrs, [:name, :email])
    |> Ecto.Changeset.validate_required([:name, :email])
    |> Ecto.Changeset.unique_constraint(:email)
  end
end
```

Now you can create a user with the `Ecto.Repo.insert/2` function:

```elixir
iex> alias EctoExample.{Repo, User}
iex> Repo.insert(%User{name: "Alice", email: "alice@example.com"})
```

6. Querying Data with Ecto

Ecto provides a composable and flexible way to build database queries. Because they are built on top of macros, they are compile-time checked, meaning errors will be caught before they hit your database.

Let’s see an example:

```elixir
iex> alias EctoExample.{Repo, User}
iex> query = from u in User, where: u.email == "alice@example.com", select: u.name
iex> Repo.all(query)
```

This query fetches all users with the email “alice@example.com” and selects their names.

Ecto also provides a convenient syntax for updating and deleting entries:

```elixir
# Update Alice's email
iex> Repo.get_by(User, name: "Alice") |> User.changeset(%{email: "alice_new@example.com"}) |> Repo.update()

# Delete a user
iex> Repo.get_by(User, name: "Alice") |> Repo.delete()
```

Conclusion

Ecto is an incredibly powerful tool for working with databases in Elixir, which is why it’s widely adopted by Elixir developers. Its clean and intuitive API makes data handling a breeze, and its diverse functionalities have made it a go-to for Elixir developers worldwide. This article has just touched on the basics of what Ecto can do, and there’s so much more to explore. 

The wide usage of Ecto in Elixir applications further solidifies its importance in the ecosystem, making it an essential skill for Elixir developers to master. If you’re considering building robust and scalable applications, hiring Elixir developers with a strong understanding of Ecto can greatly benefit your projects.

From creating and migrating databases to manipulating and querying data, Ecto offers a comprehensive solution for database interaction in Elixir. It keeps your data and application seamlessly integrated, allowing for the development of sophisticated applications. So, whether you’re an Elixir developer looking to expand your skill set or you’re looking to hire Elixir developers for your project, understanding and using Ecto is key. Happy coding!

Previously at
Flag Argentina
Brazil
time icon
GMT-3
Tech Lead in Elixir with 3 years' experience. Passionate about Elixir/Phoenix and React Native. Full Stack Engineer, Event Organizer, Systems Analyst, Mobile Developer.