What are Contexts in Elixir?

In Elixir, contexts are modules that group related functions together based on the domain of the application being built. They define a clear public API for interacting with different parts of the application, promoting organization and encapsulation of functionality. Contexts help prevent spaghetti code by providing a structured way to access and manipulate data and business logic.

Defining a Context Module

Context modules are typically created to encapsulate related functions and data operations within a specific domain of the application. Here's an example of defining a context module in Elixir:

The InventoryManagement context will delegate functions to query and manipulate inventory data.

defmodule MyApp.InventoryManagement do
  alias MyApp.InventoryManagement.Query
  alias MyApp.InventoryManagement.Schema

  defdelegate get_product!(id), to: Query.ProductStore
  defdelegate create_product(params), to: Query.ProductStore
  defdelegate update_product(id, params), to: Query.ProductStore
end

In this example:

  • We define an InventoryManagement context module to encapsulate functions related to managing inventory data.

  • We use aliases to reference modules for querying and manipulating inventory data (Query and Schema).

  • We delegate specific functions to corresponding modules within the context (ProductStore in this case) to handle operations like retrieving, creating, and updating products.

Using Context Functions

Once a context module is defined, its functions can be called from other parts of the application to perform specific operations within that domain. Here's how you can use functions from the InventoryManagement context:

# Retrieve a product by ID using the InventoryManagement context
product = MyApp.InventoryManagement.get_product!(123)

# Create a new product using the InventoryManagement context
new_product = MyApp.InventoryManagement.create_product(name: "Widget A", price: 20.99, quantity: 100)

# Update an existing product using the InventoryManagement context
updated_product = MyApp.InventoryManagement.update_product(456, price: 25.99)

In this example:

  • We retrieve a product by ID, create a new product, and update an existing product using functions delegated to the MyApp.InventoryManagement context module.

  • The context module abstracts the details of interacting with the underlying data store (e.g., ProductStore) and provides a clean and consistent interface for managing inventory data operations.

By leveraging the context module, we ensure that inventory-related functions are organized, encapsulated, and easily accessible throughout the application.