After the last few months of seemingly slow progress (and some corresponding malaise), September was a real watershed for my OSS work! It featured seven gem releases and one giant PR being made ready for merge. Let’s take a look.
I started the month resolved to finish the work on dry-configurable 0.13.0 that I detailed in the last episode.
I started my updating and merging any of the pending changes across dry-configurable’s dependent dry-rb gems: dry-container, dry-monitor, dry-schema, and dry-validation. Fortunately, thanks to the extra compatibility work I’d done in dry-configurable, all of these changes were straightforward.
By this time, there was nothing left to do but release! So on the evening of the 12th of September, I decided I get this done. At 9:55pm, I shipped dry-configurable 0.13.0, at long last!
And then I shipped the following:
By 11:30pm, this was all done and I happily sent out the announcement tweet.
In the time since, we haven’t seen or heard of any issues with the changes, so I think I can consider this change a success!
Despite it taking as long as it did, I’m glad we made this change to move dry-configurable to a clearer API. A lesson I’m taking away from this is to think again before mixing optional positional parameters with keyword args splats in Ruby methods; though this is largely a non-issue for Ruby 3.0, moving away from this while retaining backwards compatibility did cause some grief for Ruby 2.7, and on top of that, I value the extra clarity that keyword arguments bring for anything but an immediately-obvious and required singular positional argument.
With the dry-configurable taken care of, it was time to do the same for the saga of dry-system namespaces.
Before I committed to polishing off the implementation in dry-system, I wanted to double check that it’d do the job we needed in Hanami: to elide the redundant lib directory in e.g.
slices/main/lib/main/, turning it into
slices/main/lib/ only, with all the classes defined therein still retaining their
Main Ruby constant namespace. As hoped, it did exactly that! As I shared with the other Hanami contributors:
Like all of my favourite PRs, it was 3 months of dry-system work, followed by a 3-line change in Hanami 😄
A fun quip, but I think this is an important aspect of the work we’re doing in Hanami 2. We’re not putting in this amount of effort just to arrive at a toughly coupled framework that can deliver only for a small subset of users. Rather, we’re trying to establish powerful, flexible, well-factored building blocks that deliver not only the default Hanami experience, but also serve as useful tools unto themselves. The idea with this approach is that it should allow an Hanami user to “eject” themselves from any particular aspect of the framework’s defaults whenever their needs require it: they can dive deeper and use/configure constituent parts directly, while still using the rest of the framework for the value it provides.
Confident about the use case in Hanami, I used the rest of the month (and a little bit of October, shh!) to finish off the dry-system namespaces. Here’s how they look:
class AdminContainer < Dry::System::Container configure do |config| config.root = __dir__ config.component_dirs.add "lib" do |dir| dir.namespaces.add "admin", key: nil end end end
This example configures a single namespace for
lib/admin/ that ensures the components have top-level identifiers (e.g.
"foo.bar" rather than
Namespaces take care of more than just container keys. If you wanted to mimic what we’re doing in Hanami and expect all classes in
lib/ to use the
Admin const namespace, you could do the following:
config.component_dirs.add "lib" do |dir| dir.namespaces.root const: "admin" end
You’re not limited to just a single namespace, either:
config.component_dirs.add "lib" do |dir| dir.namespaces.add "admin/system_adapters", key: nil, const: nil dir.namespaces.add "admin", key: nil dir.namespaces.add "elsewhere", key: "stuff.and.things" end
If you want to learn more, go read the overview in the PR: there’s around 3,000 words explaining the history, rationale, and full details of feature, as well as a whole bunch of implementation notes.
Getting this ready to merge took around three weeks of really concerted work (almost every night!), but I’m super glad to finally have it done. Component dir namespaces represent another huge leap for dry-system. With namespaces, dry-system can load and manage code in almost any conceivable structure. With this change giving us support for “friendlier” source directory structures like the one we’ll use in Hanami, I hope it means that dry-system will also become as approachable as it already is powerful.
A final highlight of the month was getting together for another in-person chat with Luca! (Can you believe we’ve only done this four or five times at most?) Among other things, we figured out a strategy for the next and subsequent Hanami 2.0.0.alpha releases.
Here’s the plan:
So this means you should here about a new Hanami release by the time I’m writing my next set of notes here!
My work in Ruby OSS is kindly supported by my GitHub sponsors.
Thank you in particular to Jason Charnes for your unwavering support as my sole level 3 sponsor (it was great to chat to you this month as well!). Thanks also to Sebastian Wilgosz of HanamiMastery for upgrading his sponsorship!
If you’d like to support my work in bringing Hanami 2 to life, I’d love for you to join my sponsors too.
See you all next month!