Getting Started with Hanami-API | Ruby
Published: 2023-06-20 17:45:40

---
title: Getting Started with Hanami-API | Ruby
published: true
date: 2023-04-03 17:16:23 UTC
tags: 
canonical_url: https://carlosmv.hashnode.dev/getting-started-with-hanami-api-ruby
---

DISCLAIMER: This is a very basic article about Hanami::API, showing how to perform CRUD operations without a database. I'm very new to Ruby, probably my code is not idiomatic.

Hanami-API is a lightweight and fast Ruby framework for building HTTP APIs. It is a part of the Hanami web framework, which is made up of smaller, single-purpose libraries that can be used independently or together in a Hanami application. The framework provides a simple and effective way to build and deploy HTTP APIs in Ruby, allowing developers to create endpoints with different HTTP methods, extract parameters from the URI, and parse the payload of incoming requests. In this article, we will explore how to get started with Hanami-API by creating endpoints for a simple to-do list application.

## Hanami

Hanami is a **full-stack** Ruby web framework. It's made up of smaller, single-purpose libraries.

Hanami is made of the following libraries:

- [**Hanami::Router**](https://github.com/hanami/router) - Rack-compatible HTTP router for Ruby

- [**Hanami::Controller**](https://github.com/hanami/controller) - Full-featured, fast and testable actions for Rack

- [**Hanami::View**](https://github.com/hanami/view) - Presentation with a separation between views and templates

- [**Hanami::Helpers**](https://github.com/hanami/helpers) - View helpers for Ruby applications

- [**Hanami::Mailer**](https://github.com/hanami/mailer) - Mail for Ruby applications

- [**Hanami::Assets**](https://github.com/hanami/assets) - Assets management for Ruby

According to its [README](https://github.com/hanami/hanami), these components are designed to be used independently or together in a Hanami application.

# Hanami::API

It's a minimal, extremely fast, lightweight Ruby framework for HTTP APIs.

### Requirements

- Ruby 3.0+ installed.

### Installation

First, we create a folder for our project. And in it, we create two files, `gemfile` and `config.ru`.

Inside `gemfile` file, we write the following lines:

```
gem "hanami-api"
gem "puma"

```

Then, inside config.ru, we write the following code:

```
# frozen_string_literal: true

require "bundler/setup"
require "hanami/api"

class App < Hanami::API
  get "/" do
    "Hello, world"
  end
end

run App.new

```

Then, we run `bundle exec rackup` in the command line.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1679946969870/e6ddbbb6-2800-4664-9b70-a36d7a18cb03.png)

## Creating the endpoints

We create a new file, `app.rb`, to write all our endpoints.

We will have 5 endpoints.

```
class App < Hanami::API
    list_tasks = [
        {"id": 1, "title": "Buy almonds"},
        {"id": 2, "title": "Buy Nuts"}
    ]
    get "/" do
      "Hello, world"
    end

    get "/tasks" do
       json list_tasks
    end

```

In `app.rb` file, we create the `App` class. In this class, we will put all our endpoints. We create an array with 2 hashmaps with items to buy.

We define a GET endpoint with the URI `/tasks`. This endpoint will show all the elements in the array. We use the `json` method to send the response in JSON format.

We have to make a few changes in the `config.ru` file. We replace the `App` class with `require_relative 'app'`.

```
require "bundler/setup"
require "hanami/api"
require "hanami/middleware/body_parser"

require_relative 'app'

run App.new

```

Now, we run `bundle exec rackup` .

Then we go try the endpoints we just create to see if have the response we expect.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680022644284/934f31d9-68c3-434a-9b2e-d1529b7bbb9e.png)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680022695316/ba97ac97-eff1-4246-9b2b-ffc136a523f2.png)

### POST endpoint

```

use Hanami::Middleware::BodyParser, :json
class App < Hanami::API
    list_tasks = [
        {"id": 1, "title": "Buy almonds"},
        {"id": 2, "title": "Buy Nuts"}
    ]
...

    post "/task" do
        list_tasks.push(params)
        json params
    end   
end

```

Here, we define a POST endpoint with the URI `/task.`

To extract the payload from a POST request, we have to put `Hanami::Middleware::BodyParser, :json` on top of our file, to parse the payload of the incoming request.

The `Hanami::Middleware::BodyParser` is shipped by `hanami-router` which is a dependency of `hanami-API`. So we don't need to install an additional gem.

We extract the payload with `params` and push it to the array.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680022898956/e9654006-b5b5-494a-b942-1a0eda67c0bf.png)

### GET endpoint

```
class App < Hanami::API
    ....
    get "/task/:id" do
        id = params[:id]
        task = list_tasks.find{|x| x[:id] == id.to_i}

        if task == nil
            json ({status: status(404),  
                    message: "Entry #{params[:id]} not found"
                 })

        else
            json task

        end  
    end   
end

```

This GET endpoint can return an item by its ID.

We extract the parameter from the URI with `params[:id]`. Then we look in the array and Hashmap with the ID that matches and send it as JSON. If there is no hashmap with the ID that matches, we return the message "Entry #{params[:id]} not found" and the status code 404.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680023048478/cca33e1d-6c5c-4080-93b0-502fc9f8f2dc.png)

### PUT endpoint

```
put "/task/:id" do
        id = params[:id]
        task = list_tasks.find{|x| x[:id] == id.to_i}

        if task == nil
            json ({status: status(404), error: "not_found", message: "Entry #{params[:id]} not found"})

        else
            json list_tasks[list_tasks.rindex(task)] = params

        end  
    end

```

Here we define a PUT endpoint to update an element in our array.

We extract the parameter from the URI with `params[:id]`. Then we look in the array and Hashmap with the ID that matches. Then, we the `rindex()` method to have the index of the hashmap and update it with the payload.

If there is no hashmap with the ID that matches, we return the message "Entry #{params[:id]} not found" and the status code 404.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680027188531/11ce982c-6124-401a-bc25-df28681197ea.png)

### DELETE endpoint

```
delete "/task/:id" do
        id = params[:id]
        task = list_tasks.find{|x| x[:id] == id.to_i}

        if task == nil
            json ({status: status(404), error: "not_found", message: "Entry #{params[:id]} not found"})

        else

            list_tasks.delete_at(list_tasks.rindex(task))
            json(message: "Task deleted")
        end
    end

```

For the DELETE endpoint, we repeat the same operation of looking in the array for the hashmap with the ID that matches the `:id` parameter.

Then, we use the `delete_at()` method to delete the item by its index.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680027351745/8c3155a6-8c63-4ec1-ba13-2be1a0aadf24.png)

## Conclusion

In conclusion, Hanami-API is a lightweight, fast Ruby framework for building HTTP APIs. It's made up of smaller, single-purpose libraries that can be used independently or together in a Hanami application. With Hanami-API, it's easy to create endpoints with different HTTP methods, extract parameters from the URI, and parse the payload of incoming requests. Hanami-API provides a simple and effective way to build and deploy HTTP APIs in Ruby.

Thank you for taking the time to read this article.

If you have any recommendations about other packages, architectures, how to improve my code, my English, or anything; please leave a comment or contact me through [**Twitter**](https://twitter.com/Carlos_marcv), or [**LinkedIn**](https://www.linkedin.com/in/carlos-marcano-a2135a134/).

The source code is [here](https://github.com/carlosm27/hanami-api-demo).

## References

- [Introducing Hanami::API](https://hanamirb.org/blog/2020/02/26/introducing-hanami-api/).

- [Hanami::API documentation.](https://github.com/hanami/api/blob/main/README.md)

- [Hanami documentation.](https://hanamirb.org/)

- [Hanami README.](https://github.com/hanami/hanami)

- [try-hanami-api repository](https://github.com/makevoid/try-hanami-api).