Hello wonderful community, it's the hanami season! To celebrate, we're thrilled to release v1.2.0.

Features 🍒

So what this fresh spring 💐 has brought to you from the Hanami world?

HTTP/2 Early Hints

I experimented with HTTP/2 Push Promise in the summer of 2015, when Hanami was still called Lotus. I presented the results at the RubyDay of that year and build a demo app.

We didn't ship that feature because Rack and web servers didn't support Push Promise, so I had to write a toy HTTP/2 web server for Rack.

Given the adoption of HTTP/2 is slow, the IETF "backported" this feature to HTTP/1. This feature today is known as Early Hints (103) status code.

A web application can tell the browser which resources to fetch in advance in order to boost the page loading.

Given that now Rack and Puma support Early Hints (103) and we had already in place the code to support this kind of feature, we're excited to release it today!

Setup

In order to use it, you need to use Puma with Early Hints feature enabled.

# config/puma.rb
# ...
early_hints true

Inside the project configuration you can simply enable like this:

# config/environment.rb
Hanami.configure do
  # ...
  early_hints true
end

As last step, you need a web server that supports HTTP/2 and Early Hints like h2o. When you'll start the server and visit the page, javascripts and stylesheets will be pushed.

If you're looking for a full working example, please check this demo app.

Unobtrusive JavaScript (UJS)

Today we introduce a new gem in the Hanami family: hanami-ujs.

It provides JS features to submit forms and links via AJAX, disable buttons, confirm actions, only with pure JavaScript. hanami-ujs is based on the really good vanilla-ujs gem.

Usage

As first thing, you must add hanami-ujs to your Gemfile and run bundle install.

Then you have to add two lines to the application layout (eg. apps/web/templates/application.html.erb):

  1. <%= csrf_meta_tags %> inside <head>
  2. <%= javascript "hanami-ujs" %> the location is optional, but before </body> is a good spot.

Now we can use the new option for form_for: remote: true

<%=
  form_for :search, "/search", remote: true do
    # ...

    submit "Search"
  end
%>

When you will push "Search" the form will be sent via AJAX.

New Development Error Page

New Hanami projects will be generated with a new gem in Gemfile: hanami-webconsole.

It's is an improved development error page with a built-in REPL to debug Ruby code from the browser. This feature is based on better_errors gem, which historically didn't play well with Hanami.

So we packaged into a Hanami plugin to make the developer experience frictionless.

CLI hooks

Since v1.1.0 you can enhance the CLI experience of hanami by registering your own commands (eg. hanami generate webpack ). Starting from today you can register callbacks for existing commands to hook into their execution.

Imagine to build a gem hanami-database-analyzer to print the number of tables from the development database:

Hanami::CLI.after("db migrate") do
  puts "the database has 23 tables"
end

When a user will execute hanami db migrate, that callback will be called:

% bundle exec hanami db migrate
# migrations output ...
the database has 23 tables

Alternatively, you can use objects:

class DatabaseTableCounter
  def call(*)
    puts "the database has 23 tables"
  end
end

Hanami::CLI.after "db migrate", DatabaseTableCounter.new

Project Rack middleware

With this release we're introducing Rack middleware stack at the project level.

# config/environment.rb
Hanami.configure do
  middleware.use MyRackMiddleware
end

This is equivalent to use a middleware from config.ru, the main difference is that the new Rack middleware can be programmatically manipulated by third-party gems (aka plugins). (See the next feature).

Enhanced support for plugins

Third-party gems (aka plugins) can now manipulate the Hanami configuration of a project.

For instance from the hanami-webconsole gem, we mount a Rack middleware into the host project:

Hanami.plugin do
  middleware.use BetterErrors::Middleware
end

Custom repositories commands

Hanami::Repository interface exposes standard CRUD operations. If you need custom queries, you have a flexible querying API, but we were missing the same flexibility for writing operations (commands).

Let's say you want create records in bulk, here's how to define a command for that:

class TaskRepository < Hanami::Repository
  def create_many(data)
    command(create: :tasks, result: :many).call(data)
   end
end

Minor Changes

For the entire list of changes, please have a look at our CHANGELOG and features list.

Released Gems 💎

How to install

gem install hanami
hanami new bookshelf

Then follow our getting started guide.

How to upgrade

Update hanami and hanami-model in your Gemfile:

gem "hanami",       "~> 1.2"
gem "hanami-model", "~> 1.2"

Then run bundle update hanami hanami-model.

For a detailed explanation, check the upgrade guide.

What's next?

We're gonna join our forces with ROM & dry-rb teams to work together on Hanami 2.0, ROM 5.0, and dry 1.0! 🎉

We'll work to improve the integration between our three projects, to offer a rock solid, unified set of solutions for the Ruby ecosystem. 💎❤️

Starting from tomorrow we'll work in parallel on Hanami 2.0 and 1.3. If you want to follow along the progress, keep an eye on the branches in our GitHub repositories:

  • master targets 1.2 (bugfixes)
  • develop targets 1.3 (new features, deprecations for 2.0)
  • unstable targets 2.0 (new features, breaking changes)

While we don't have an ETA for 2.0, the first beta for 1.3 will be released on August 2018.

Happy coding! 🌸