H a n a m i

Ruby apps that grow with you

Hanami is a Ruby framework that helps you keep your code organised and maintainable.

Separated concerns, explicit business logic, and modular architecture give you the foundation to build apps that remain a pleasure to work on even as they grow large.

View the Hanami docs

Database

Hanami gives you a dedicated database layer, so you have one place for all your queries. It keeps simple queries easy, while allowing you to build complex queries from all the same tools.

Relations define your data access patterns, repos compose them for your business logic, and structs give you value objects you can use throughout your app.

This means that as your app grows, your database layer stays focused and maintainable.

View database guide
# app/relations/articles.rb
class Articles < Hanami::DB::Relation
  schema :articles, infer: true

  def published
    where(published: true).order { created_at.desc }
  end
end
# app/repos/article_repo.rb
class ArticleRepo < MyApp::Repo
  def update(id, attributes)
    articles.by_pk(id).changeset(:update, attributes).commit
  end

  def find(id)
    articles.published.by_pk(id).one!
  end

  def latest
    articles.published.limit(10).to_a
  end
end
# app/structs/article.rb
class Article < MyApp::DB::Struct
  def summary
    "#{title} (#{author_name}, #{published_at.year})"
  end
end

Business logic

Operations let you compose your workflows with explicit success and failure paths.

Each operation focuses on a single job, pulls in the dependencies it needs, and makes your business logic obvious and testable.

Dive into operations
# app/articles/update.rb
class Update < MyApp::Operation
  include Deps["repos.article_repo"]

  def call(article_id, attributes)
    validation = step validate(attributes)
    article = article_repo.update(article_id, validation.to_h)
    Success(article)
  end

  private

  def validate(attributes)
    # returns a Success or Failure
  end
end

Routes

Hanami routes work like you expect, giving you a clear overview of your URLs. You can use resource routes to keep your routes understandable as your app grows.

Find your way around routing
# config/routes.rb
module MyApp
  class Routes < Hanami::Routes
    root to: "home.show"

    resources "articles"
  end
end

Actions

Hanami handles HTTP requests via actions. You have one action class per endpoint. Inside, you can focus on HTTP only, using dependencies to call into your business logic.

Typical actions will render a view or call an operation, helping them stay lean and easy to follow.

Learn about actions
# app/actions/articles/update.rb
class Update < MyApp::Action
  include Deps[update_article: "articles.update"]

  def handle(request, response)
    result = update_article.call(
      request.params[:id],
      request.params[:article]
    )

    case result
    in Success(article)
      response.redirect_to routes.path(:article, article.id)
    in Failure(validation)
      response.render view, validation:
    end
  end
end

Views

Your views are also dedicated classes. Load your data, decorate it with view-specific logic, and expose it to the template for rendering.

Views are easy to render from actions, but because they're also regular objects, you can test them directly, and use them wherever else you need.

Explore views
# app/views/articles/show.rb
class Show < MyApp::View
  include Deps["repos.article_repo"]

  expose :article do |id:|
    article_repo.get(id)
  end
end
<%# app/templates/articles/show.html.erb %>
<h1><%= article.title %></h1>
<%= article.body_html %>

…and more!

We’ve just scratched the surface with Hanami. There’s a lot more to love:

  • Hanami is designed for modularity. Using slices, you can create clear boundaries between your subdomains or subsystems. Each slice is self-contained, and you can decide if or how they depend on each other.
  • You can choose how much framework you want. Remove or swap out whatever you like, it’s all there in your Gemfile. With Hanami, you can build full-stack web apps, lean APIs, stream processors, or whatever shape of app you need.
  • Your development interactions stay fast. Thanks to Hanami’s smart code loading, your console, tests, and app server load quickly no matter how big your app grows.
Explore the Hanami docs

Built on community

For people who bring kindness, curiosity, and care

Photograph of cute people being cute

The Hanakai community is a place where people of all backgrounds and experience levels can feel respected, and can share and grow. A place for people to be proud of, and feel safe within.

We do not tolerate nazis, transphobes, racists, or any kind of bigotry. See our Code of Conduct for more.

Supported by

Hanakai is made possible by our wonderful sponsors

We’re also supported by our many community patrons.

Become a Hanakai sponsor or patron today, and help us build a diverse future for Ruby.

Support the Hanakai project