This is the first minor release after the project rebranding that happened a few months ago.

We waited so long to release this version in order to have the largest possible feedback cycle. (Actually, the longest gap in releases since this project was started four years ago!) We've had a lot of new contributions: new features, bug fixes, and real world experiences. At this point we're really close to 1.0.

In the meantime, we've started tech alliances with dry-rb and ROM. We're working closely with these two amazing projects (and communities) to make the Ruby ecosystem stronger.

As result of this collaboration, today we can ship a new, powerful validation syntax based on dry-validation.


New Validations Syntax

This new powerful syntax overcomes the limitations that we have reached with the old design: no control on the order of execution and lack of extensibility. We realized that complex validation rules are hard to describe with DSL options, so we made it possible to express these rules with Ruby macros.

The results are astonishing: besides being more expressive, we can now guarantee type safety and we've seen performance improvements.

# apps/web/controllers/books/create.rb
module Web::Controllers::Books
  class Create
    include Web::Action

    params do
      required(:book).schema do
        required(:price).filled(:float?, gt?: 0.0)

    def call(params)
      if params.valid?
        # persist
        self.status = 422
# apps/web/views/books/create.rb
module Web::Views::Books
  class Create
    include Web::View
    template 'books/new'
# apps/web/templates/books/new.html.erb
<% unless params.valid? %>
    <p>There was a problem</p>
      <% params.error_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
<% end %>

Subresource Integrity

A CDN can dramatically improve page speed, but it can potentially open a security breach. If the CDN that we're using is compromised and serves evil javascript or stylesheet files, we're exposing our users to security attacks like Cross Site Scripting (XSS).

To solve this problem, browsers vendors introduced a defense called Subresource Integrity.

When enabled, the browser verifies that the checksum of the downloaded file, matches with the declared one.

From A CDN

If we're using jQuery from their CDN, we should find the checksum of the .js file on their website and write:

<%= javascript '', integrity: 'sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=' %>

The output will be:

<script integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" src="" type="text/javascript" crossorigin="anonymous"></script>

Local Assets

The security problem described above doesn't concern only CDNs, but local files too. Imagine we have a compromised file system and someone was able to replace our javascripts with evil files: we would be vulnerable to the same kind of attack.

As a defense against this security problem, Hanami enables Subresource Integrity by default in production. When we precompile assets at deploy time, Hanami calculates the checksum of all our assets and it adds a special HTML attribute integrity to our asset tags like <script>.

<%= javascript 'application' %>
<script src="/assets/application-92cab02f6d2d51253880cd98d91f1d0e.js" type="text/javascript" integrity="sha256-WB2pRuy8LdgAZ0aiFxLN8DdfRjKJTc4P4xuEw31iilM=" crossorigin="anonymous"></script>

Security Updates

We've updated our default security settings to support Content Security Policy 1.1 and 2.0 (1.0 is still supported).

Along with this improvement, we have now turned on two extra security HTTP headers: X-Content-Type-Options and X-XSS-Protection.


  • New settings for logging: Hanami now supports per-environment stream (standard output, file, etc..), level and formatter. Because of JSON parseability, for the production environment, there is now a JSON formatter for the logger.

  • Hanami no longer supports Ruby 2.0 and 2.1

  • params can now be accessed only with :symbols, not 'strings'. That is, we have removed indifferent access.

Upgrade Notes

Please have a look at the upgrade notes for v0.8.0.


We're grateful for each person who contributed to this release. These lovely people are:

Thank you all!