Friday, October 21, 2022
HomeWeb DevelopmentConstructing REST API with Elixir and Phoenix

Constructing REST API with Elixir and Phoenix


Phoenix is the most cherished framework by builders in 2022, and by some margin too. It’s nice for internet improvement as a part of the Elixir ecosystem and its reliability and scalability make it a good selection for any challenge.

On this tutorial, we’ll discover what Elixir is, the Phoenix internet framework, and the best way to construct REST API with Elixir and Phoenix in your tasks.

Skip forward

What’s Elixir and the Phoenix internet framework?

Elixir is a purposeful, dynamically-typed language that’s constructed on high of Erlang. Jose Valim, who developed Elixir, labored on the Ruby on Rails group and created it when he was making an attempt to resolve efficiency bottlenecks with Ruby on Rails and Erlang.

Because of this, the syntax of Elixir has many similarities with Ruby on Rails syntax.

Elixir is especially used to create extremely scalable purposes which are fault-tolerant and simply maintainable. Among the key options of Elixir are:

  1. It compiles the code into byte code that runs on Erlang VM
  2. It emphasizes greater order features and recursions
  3. Highly effective sample matching
  4. It’s a dynamically typed language, so it checks all the kinds at runtime moderately than compile time

Advantages of Elixir

Since Elixir is constructed on high of BEAM, an Erlang VM, it has some key traits that assist to construct nice apps. These traits are:

  1. Concurrency: Elixir makes use of course of threads for execution. These threads are remoted, CPU-based, and talk by messages
  2. Scalability: Scaling an Elixir software is straightforward because it makes use of light-weight threads that may run with few processes
  3. Reliability: Constructing fault-tolerant purposes is among the principal options of Elixir. When an Elixir software fails in manufacturing, the supervisor system restarts the light-weight course of shortly, which reduces downtime

Relating to constructing internet purposes, it’s tough to construct primary functionalities from scratch each time, which is the place the Phoenix internet framework comes into the image.

Introduction to Phoenix

Phoenix is an online framework within the Elixir ecosystem. It comes with modules out-the-box that assist construct extremely scalable and fault-tolerant purposes. Phoenix is a Mannequin-View-Controller (MVC) framework much like Ruby on Rails and Django.

One of many killer options of Phoenix framework is LiveView. Phoenix LiveView is a library that’s constructed on high of Phoenix which helps in constructing real-time purposes with out writing client-side JavaScript. It calculates the web page adjustments and push updates by WebSocket.

How Phoenix works

Plugs are the fundamental factor of Phoenix. Plugs are a specification for composing an online software with features — Phoenix receives an incoming request and converts it into Conn, which is an information construction that handles requests and responses in HTTP connections.

Phoenix Plugs Web App Functions

Conn information construction is handed by a number of plugs to finish the performance and return a response. To simplify it:

  1. Receives a request
  2. Converts it to conn
  3. Passes by a number of plugs
  4. Returns response

Lifecycle of Phoenix requests

As we’ve famous, an incoming request in phoenix goes by a number of plugs to return the required response — let’s look into the main points of the plugs and course of:

Incoming Request To Endpoints

Phoenix receives a request on the endpoint and the endpoint converts it right into a Conn information construction, forwarding it to the router.

The router pipelines the Conn information construction into the controller, and the controller interacts with the mannequin to fetch information from the database and render it utilizing templates. Templates could be HTML or JSON recordsdata. Right here, the endpoint, router, and controllers are plugs — every little thing in Phoenix is a composable operate that transforms information into completely different construction.

Making a REST API utilizing Elixir and Phoenix

Now we’re aware of the Phoenix internet framework, let’s construct a REST API with Elixir and Phoenix to make use of for a challenge. Right here, we’re going to create a REST API which delivers customers data to a Postgres database.

The API will serve person data beneath /api/customers, with GET, PUT, POST, DELETE requests.

To do that, we have to create database schema with required fields which are saved within the database:

  1. id → Major key within the desk.
  2. identify → String accommodates person identify.
  3. e-mail → Electronic mail subject, it ought to be distinctive.
  4. function → Consumer function.
  5. handle → Consumer handle.

Conditions

Earlier than you proceed additional, I’d advocate you meet the next conditions:

  1. Fundamental understanding of the Elixir syntax. You possibly can seek advice from the official docs to get began with the syntax
  2. Set up Elixir in your machine. We are going to talk about the best way to set up Elixir within the upcoming part
  3. Have Postgres put in in your machine. Alternatively, you possibly can run Postgres utilizing Docker (which is what we will probably be doing on this tutorial)
  4. Having the Postman shopper or an alternative choice to take a look at APIs

Getting began

At the start, let’s set up Elixir in your machine. To put in elixir on macOS, you should use Homebrew package deal supervisor.

Putting in Elixir on macOS

Earlier than set up, replace Homebrew utilizing:

$ brew replace

After this, you possibly can set up Elixir utilizing the next:

$ brew set up elixir

You additionally want to put in the Elixir package deal supervisor Hex. Run the next command to put in Hex:

$ combine native.hex

To confirm that the set up is profitable, you possibly can run this to test the model:

$ elixir -v

Verify Elixir Installation Successful

(Observe: For different working methods, you possibly can refer the Elixir official information that gives a easy step-by-step information for set up)

Putting in Phoenix

Now we’ve put in Elixir, Let’s bootstrap a challenge utilizing the Phoenix framework to construct a REST API.

$ combine archive.set up hex phx_new 1.5.3

This installs Phoenix 1.5.3 in your machine. To create a brand new challenge, you have to run the next command within the terminal:

$ combine phx.new users_api --no-html --no-webpack --binary-id 

$ cd users_api

It will create a users_api listing, with all of the boilerplate for a Phoenix software. It follows a listing construction like this:

├── _build
├── property
├── config
├── deps
├── lib
│   ├── hi there
│   ├── hi there.ex
│   ├── hello_web
│   └── hello_web.ex
├── priv
└── take a look at

(Observe: The official Phoenix docs clarify the listing construction intimately, and you’ll seek advice from it right here)

The --no-html and  --no-webpack parameters instruct the command to not generate HTML recordsdata and static property since we’re solely constructing a REST API.

--binary-id will configure Ecto to make use of a UUID for database schemas comparable to main key values.

Now, we’ll scaffold the appliance with boilerplate code. Let’s run the Postgres database and join the appliance to the database.


Extra nice articles from LogRocket:


Arrange and configure database

Firstly, ensure you set up Docker in your machine. Working Postgres through Docker is straightforward; simply want run the next command:

$ docker run --name phoenix-postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5500:5432 -d postgres

Right here, we specify --name for the Docker container and atmosphere for POSTGRES_USER and POSTGRES_PASSWORD. We additionally have to map the port by specifying -p . Lastly, we pull the Docker picture in indifferent mode.

As soon as Postgres is up and operating, we configure the database within the Phoenix software. Phoenix supplies a config listing to setup databases, cron jobs, loggers, and stack traces within the software.

To configure the database within the improvement atmosphere, change config/dev.exs with Postgres database credentials.

# Configure your database
config :users_api, UsersApi.Repo,
  username: "postgres",
  password: "postgres",
  database: "users_api_dev",
  hostname: "localhost",
  port: "5500",
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

After this, you possibly can create a database for the event atmosphere like so:

$ combine ecto.create

And you may drop the database utilizing this:

$ combine ecto.drop

Schema and migration

When you create a database and configure it within the software, you have to mannequin the info to entry it contained in the app.

Phoenix contexts

Earlier than we begin with schema design, it’s essential to learn about Phoenix contexts. Contexts are modules that group the associated functionalities collectively. While you design an software, Phoenix helps to group modules primarily based on the context. Consider it like domains in Area-Pushed Design.

Context will group completely different modules collectively primarily based on the functionalities.

To present an instance, Elixir Logger.data/1 is made up of a number of modules, however we will entry these modules in a single Logger module context.

To create context for modeling, you should use the Phoenix generator command within the software:

$ combine phx.gen.context Admin Consumer customers 
  identify:string e-mail:string:distinctive function:string handle:string

Right here, we have now:

  • Admin, as a context’s module identify
  • Consumer, because the schema’s module identify
  • Customers, because the database desk identify

To outline the customers subject and its sort whereas producing the database desk, you possibly can seek advice from the schema subject definition from the hex docs.

When you run the command, it can create lib/admin/person.ex, which accommodates the schema definition.

defmodule UsersApi.Admin.Consumer do
  use Ecto.Schema
  import Ecto.Changeset
  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "customers" do
    subject :handle, :string
    subject :e-mail, :string
    subject :identify, :string
    subject :function, :string
    timestamps()
  finish
  @doc false
  def changeset(person, attrs) do
    person
    |> solid(attrs, [:name, :email, :role, :address])
    |> validate_required([:name, :email, :role, :address])
    |> unique_constraint(:e-mail)
  finish
finish

It additionally scaffolds the REST API for the customers module in users_api/admin.ex.

defmodule UsersApi.Admin do
  @moduledoc """
  The Admin context.
  """
  import Ecto.Question, warn: false
  alias UsersApi.Repo
  alias UsersApi.Admin.Consumer
  @doc """
  Returns the listing of customers.
  ## Examples
      iex> list_users()
      [%User{}, ...]
  """
  def list_users do
    Repo.all(Consumer)
  finish
  @doc """
  Will get a single person.
  Raises `Ecto.NoResultsError` if the Consumer doesn't exist.
  ## Examples
      iex> get_user!(123)
      %Consumer{}
      iex> get_user!(456)
      ** (Ecto.NoResultsError)
  """
  def get_user!(id), do: Repo.get!(Consumer, id)
  @doc """
  Creates a person.
  ## Examples
      iex> create_user(%{subject: worth})
      {:okay, %Consumer{}}
      iex> create_user(%{subject: bad_value})
      {:error, %Ecto.Changeset{}}
  """
  def create_user(attrs  %{}) do
    %Consumer{}
    |> Consumer.changeset(attrs)
    |> Repo.insert()
  finish
  @doc """
  Updates a person.
  ## Examples
      iex> update_user(person, %{subject: new_value})
      {:okay, %Consumer{}}
      iex> update_user(person, %{subject: bad_value})
      {:error, %Ecto.Changeset{}}
  """
  def update_user(%Consumer{} = person, attrs) do
    person
    |> Consumer.changeset(attrs)
    |> Repo.replace()
  finish
  @doc """
  Deletes a person.
  ## Examples
      iex> delete_user(person)
      {:okay, %Consumer{}}
      iex> delete_user(person)
      {:error, %Ecto.Changeset{}}
  """
  def delete_user(%Consumer{} = person) do
    Repo.delete(person)
  finish
  @doc """
  Returns an `%Ecto.Changeset{}` for monitoring person adjustments.
  ## Examples
      iex> change_user(person)
      %Ecto.Changeset{information: %Consumer{}}
  """
  def change_user(%Consumer{} = person, attrs  %{}) do
    Consumer.changeset(person, attrs)
  finish
finish

Working migration

To run the migration for the outlined information schema, you have to run the next command:

$ combine ecto.migrate

When you run the migration, it can create a desk within the database with the outlined fields, as within the schema.

Scaffolding Controller and View

Now, we have now the database schema and mannequin outlined within the software, we have to wire it with Controller and View to return the response.

To generate Controller and View for a selected module, Phoenix supplies a generator command that may generate boilerplate code:

$ combine phx.gen.json Admin Consumer customers 
  identify:string e-mail:string:distinctive function:string handle:string --no-context --no-schema

The above command generates:

  • A CRUD Controller for the customers at lib/users_api_web/controllers/users_controller.ex
  • View, to render customers’ JSON at lib/users_api_web/view/users_view.ex

We additionally point out --no-context and --no-schema, since we already generated them whereas creating the database schema.

Phoenix additionally supplies users_api_web/controllers/fallback_controller.ex to deal with errors and fallbacks for any failures. We are able to edit them to deal with completely different error codes. For instance, you possibly can edit fallback controllers to deal with UnAuthorized errors.

defmodule MyFallbackController do
  use Phoenix.Controller

  def name(conn, {:error, :not_found}) do
    conn
    |> put_status(:not_found)
    |> put_view(MyErrorView)
    |> render(:"404")
  finish

  def name(conn, {:error, :unauthorized}) do
    conn
    |> put_status(403)
    |> put_view(MyErrorView)
    |> render(:"403")
  finish
finish

By default, Phoenix configures the fallback controller in the primary controller — you possibly can change them in users_api_web/controllers/user_controller.ex.

  action_fallback UsersApiWeb.FallbackController

When you create a controller and consider, you have to add a route for the controller in lib/users_api_web/router.ex.

defmodule UsersApiWeb.Router do
  use UsersApiWeb, :router
  pipeline :api do
    plug :accepts, ["json"]
  finish
  scope "/api", UsersApiWeb do
    pipe_through :api
    get "/customers", UserController, :index
    put "/customers", UserController, :edit
    submit "/customers", UserController, :create
    delete "/customers", UserController, :delete
  finish
  # Allows LiveDashboard just for improvement
  #
  # If you wish to use the LiveDashboard in manufacturing, you need to put
  # it behind authentication and permit solely admins to entry it.
  # In case your software doesn't have an admins-only part but,
  # you should use Plug.BasicAuth to arrange some primary authentication
  # so long as you're additionally utilizing SSL (which you need to anyway).
  if Combine.env() in [:dev, :test] do
    import Phoenix.LiveDashboard.Router
    scope "https://weblog.logrocket.com/" do
      pipe_through [:fetch_session, :protect_from_forgery]
      live_dashboard "/dashboard", metrics: UsersApiWeb.Telemetry
    finish
  finish
finish

As you possibly can see, you possibly can group completely different routes right into a single endpoint. Right here, we nest all of the /customers routes inside /api scope. Inside /api scope, we configure CRUD for the Customers API.

There may be one other simplified model for configuring a CRUD request for a module. We are able to use assets from the Phoenix router module:

assets "/customers", UserController

By configuring its assets like this; it simplifies all of the requests in a single line.

 scope "/api", UsersApiWeb do
    pipe_through :api
    assets "/customers", UserController, besides: [:new, :edit]

Now, you possibly can run the appliance utilizing the next:

$ combine phx.server

Run The Application Compiling

Conclusion

And also you’re performed! Thanks for following together with this tutorial, I hope you discovered it helpful and be happy to submit your findings within the feedback beneath. You possibly can take a look at the API at http://localhost:4000, and you’ll refer the whole code for this tutorial right here.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments