October was the month! I finally got through the remaining tasks standing between me and an Hanami 2.0.0.alpha2 release. Let’s work through the list now!
Now when you subclass
Hanami::View inside an Hanami app, it will now use the application’s configured inflector automatically. This is important because hanami-view uses the inflector to determine the class names for your view parts, and it’s just plain table stakes for an framework to apply inflections consistently (especially if you’ve configured custom inflection rules).
The implementation within hanami-view was quite interesting, because it was the first time I had to adjust an
ApplicationConfiguration (this one being exposed as
config.views on the
Hanami::Application subclass) to hide one of its base settings. In this case, it hides the
inflector setting because we know it will be configured with the application’s inflector as part of the
ApplicationView behaviour (to refresh your memory,
ApplicationView is a module that’s mixed in whenever
Hanami::View is subclassed within a namespace managed by a full Hanami application).
Ordinarily, I’m all in favour of exposing as many settings as possible, but in this case, it didn’t make sense for a view-specific inflector to be independently configurable right alongside the application inflector itself.
Rest assured, you don’t lose access to this setting entirely, so if you ever have reason to give your views a different inflector, you can go right ahead and directly assign it in a view class:
module Main class View < Hanami::View # By default, the application inflector is configured # But you can also override it: config.inflector = MyCustomInflector end end
There was a counterpart hanami PR for this change, and I was quite happy to see it all done, because it means we now have consistent handling of both action and view settings: each gem provides their own
ApplicationConfiguration class, which is made accessible via
config.views respectively. This consistency should make it easier to maintain both of these imported configurations going forward (and, one day, to devise a system for any third party gem to register application-level settings).
One aspect of the
ApplicationView behaviour is to automatically configure a template name on each view class. For example, a
Main::Views::Articles::Index would have its template configured as
This is great, but there was an missing piece from the implementation. It assumed that your view hierarchy would always include an abstract base class defined within the application:
module Main # Abstract base view class View < Hanami::View end module Views module Articles # Concrete view class Index < View end end end end
Under this assumption, the base view would never have its template automatically configured. That makes sense in the above arrangement, but if you ever wanted to directly inherit from
Hanami::View for a single concrete view (and I can imagine cases where this would make sense), you’d lose the nice template name inference!
With this PR, this limitation is no more: every
ApplicationView has a template configured in all circumstances.
Keeping with the theme of improving hanami-view integration, another gap I’d noticed was that application views are not automatically configured with a part namespace. This meant another wart if you wanted to use this feature:
require "main/views/parts" module Main class View < Hanami::View # Ugh, I have to _type_ all of this out, _by hand?_ config.part_namespace = Views::Parts end end
Not any more! As of this PR, we now have a
config.views.parts_path application-level setting, with a default value of
"views/parts". When an
ApplicationView is activated, it will take this value, convert it into a module (relative to the view’s application or slice namespace), and assign it as the view’s
part_namespace. This would see any view defined in
Main::Views::Parts automatically set as its part namespace. Slick!
Sticking with configuration, but moving over to hanami-controller,
Hanami::Action subclasses within an Hanami app (that is, any
ApplicationAction) now have these security-related headers configured out of the box:
X-XSS-Protection: 1; mode=block
Content-Security-Policy:it’s long, just go check the code
These are set on the
config.actions.default_headers application-level setting, which you can also tweak to suit your requirements.
Previously, these were part of a bespoke one-setting-per-header arrangement in the
config.security application-level setting namespace, but I think this new arrangement is both easier to understand and much more maintainable, so I was happy to drop that whole class from hanami as part of rounding this out this work.
The last change I made to hanami-controller was to move the
config.cookies application-level setting, which was defined in the hanami gem, directly into the
config.actions namespace, which is defined inside hamami-controller, much closer to the related behaviour.
We now also automatically include the
Hanami::Action::Cookies module into any
ApplicationAction if cookies are enabled. This removes yet another implmentation detail and piece of boilerplace that users would otherwise need to consider when building their actions. I’m really happy with how the
ApplicationAction idea is enabling this kind of integration in such a clean way.
It’s been a while now since I released my original Hanami 2 application template, which still serves as a helpful base for traditional all-in-one web applications.
But this isn’t the only good use for Hanami 2! I think it can serve as a helpful base for any kind of application. When I had a colleague ask me on the viability of Hanami to manage a long-running system service, I wanted to demonstrate how it could look, so I’ve now released an Hanami 2 minimal application template. This one is fully stripped back: nothing webby at all, just a good old
lib/ and a
bin/app to demonstrate an entry point. I think it really underscores the kind of versatility I want to achieve with Hanami 2. Go check it out!
Last but not least, one evening I was investigating just how many files were required as one of my applications booted. I noticed an unusually high number of concurrent-ruby files being required. Turns out this was an unintended consequence of requiring dry-types. One single-line PR later and now a
require "dry/types" will load 242 fewer files!
It’s taken quite some doing to get to this moment, where an Hanami 2.0.0.alpha2 release finally feels feasible. As you’d detect from my previous posts, it’s felt tantalisingly close for every one of the last few months. As you’d also detect from this post, the final stretch has involed a lot of focused, fiddly, and let’s face it, not all that exciting work. But these are just the kind of details we need to get right for an excellent framework experience, and I’m glad I could continue for long enough to get these done.
I’m keenly aware that there’ll be much, much more of this kind of work ahead of us, but for the time being, I’m savouring this interstice.
In fact, I’ve even given myself a treat: I’ve already started some early explorations of how we could adapt dry-system to fit with zeitwerk so that we can reliable autoloading a part of the core Hanami 2 experience. But more on that later ;)
As for the next month, new horizons await: I’ll start working out some alpha2 release notes (can you believe it’s been nearly 2 years of work?), as well as continuing on the zeitwerk experiment.
See you all again, same place, same time!