Open source status update, November 2021

One of the things I find hardest about writing these open source status updates is my opening sentence. So I’m just going to leave this one in here and get on with journalling another month of steady progress!

We shipped the first of our monthly Hanami alphas!

After our last alpha release and our promise to ship monthly, we delivered the next alpha right on time, with Hanami 2.0.0.alpha4 going out the door on the 7th of December.

The release was a very orderly process this time around, especially compared to my late night marathons of the last two. Luca was our release manager (we’re alternating duties), and a few days before the release, we already had the gems lined up and release announcement prepared. I’ve a feeling this will make for a really helpful cadence for us. Anyway, go check out the announcement post for the changes, a few of which I’ll cover in detail below.

Access to routes helpers inside all actions

Way back in July, Marc Busqué prepared a class to provide access to helper methods returning URLs for all of the named routes in an application. This languished for a while, but we got it merged in preparation for the alpha3 release. This made the routes helpers accessible via a component registered with the "routes" container key. This is all fine if you want to inject this object explicitly, but we want to make it easier still in the common usage contexts, like action and view classes.

For alpha4 we’ve made it automatically available in both those places!

Making it available in the actions was a fairly straightforward extension of the existing set of dependencies we automatically provide. There was a little wrinkle here, however: the “resolver” that we have the Hanami application provide to the router (for resolving action objects from string container keys) was resolving those objects eagerly, i.e. directly fetching them from the container for every declared route. This led to an infinite loop, since the first action would auto-inject the router helper, which in turn required the router, which then tried to load each again again, and so on. After a small change to make the router resolver lazy, we were back in business and the routes helper was available. The lazy router resolver is something we would have wanted to build before 2.0.0 final anyway (a big principle behind 2.0.0 is to make it easy to load only subsets of your application), so I’m glad we had this as a prompt to do it now.

The end result is that you can now have routes like this:

module TestApp
  class Routes < Hanami::Application::Routes
    define do
      slice :main, at: "/" do
        get "test", to: "test"
        get "examples", to: "examples.index", as: :examples
      end
    end
  end
end

And then access your named routes inside an action with no extra work:

module Main
  module Actions
    class Test < Hanami::Action
      def handle(req, res)
        res.redirect routes.path(:examples)
      end
    end
  end
end

Thanks to Marc’s ongoing work in this space, we’ll have the same arrangement set up for views by this time next month, too.

Improvements to the Hanami console

I’ve been preparing another Hanami app at work lately, and noticed we’d experienced some regressions in the console experience compared to the arrangement we had in place back for our original Hanami 2 application template. Notably, slice helpers weren’t available, nor was there a shortcut to access the application class. I fixed these here, and now this wonderful experience is available again:

$ ./bin/hanami console

test_app[development]> app
=> RecognitionService::Application

test_app[development]> main
=> #<Hanami::Slice:0x00007fdc97ab47a0
 @application=RecognitionService::Application,
 @container=Main::Container,
 @name=:main,
 @namespace=Main,
 @namespace_path="main",
 @root=#<Pathname:/Users/tim/Source/cultureamp/recognition-service/slices/main>>

Having such quick and easy access to the application and its slices is a big part of what makes the Hanami console experience so pleasurable! And this is in addition to its constant start time, no matter how large your app (remember my note above about having the framework support loading subsets of the application?), because it only loads the most minimal subset of the app, and then brings in the rest of your components lazily, only as you require them.

While I was in CLI land, I also decided to finally figure out why our IRB-based console wasn’t offering a custom prompt, and managed to get that one fixed too. IRB shows its age in this regard: Pry offers a much nicer setup and customisation experience.

Preparing for flexible source dir configuration

In the remainder of my OSS time this month, I was slowly moving towards the next evolution of the configurable Hanami component dirs I shipped last month. The plan here is to make it support “source dir” configuration in general, not just for component dirs. This should allow a user to configure component dirs when they want source dirs to be auto-registered (along with full access to the dry-system component dir configuration), as well as ordinary source dirs, when they want a directory to be autoloaded by Zeitwerk, but not populate the container.

The beginning of my work on the Hanami side is available here, and the approach I’m taking is to leverage dry-system’s own Config::ComponentDirs class for most of the component dir heavy lifting. This means we’ll need to add a range of new behaviours to that class, which is in progress here.

I’m hoping to have this one ready by the end of the year. More on this in next month’s update.

© 2008-2021 Tim Riley. All rights reserved.