Hello Hanami community! It’s Tim here again, and I’m delighted to announce the release of Hanami 2.0.0.alpha3!
This release represents months of work on several foundational aspects of the framework, and brings:
- Shallow application source directories
- Reworked application settings
- Reworked application routes
- Actions enhancements
- Framework settings are now powered by dry-configurable
tl;dr we simplified the source directory structures,
slices/main/lib/main/my_class.rb will now be
In our previous alpha release, we required you to structure your source files in a way that matched the typical Ruby conventions for loading from the
$LOAD_PATH. So if you had a
main slice, and a
Main::MyClass component, it would need to be located at
slices/main/lib/main/my_class.rb. This worked well enough, but it presented awkwardly deep directory trees with redundant names, especially given we expect all components defined within each slice to live within its own singular namespace anyway. This latter aspect was already made clear by the fact that we removed that redundant leading "main" from the component’s key, with it available from the slice as
So for this release, we made a major overhaul to our code loading to support our ideal source directory structure. Now in your
main slice, your
Main::MyClass component can be defined directly within it’s
lib/ directory, at
slices/main/lib/my_class.rb, while still available from the slice as
Main::Slice["my_class"]. This means one fewer directory to hop through, one less name to say when you’re communicating your source paths, and a much stronger signal that each slice should fully inhabit its own namespace.
Along with this, you can now keep certain categories of components in their own top-level directories, including
views/. With this, you can define an action like
slices/main/actions/posts/index.rb, with the component accessible from the slice as
Together, these changes should make surveying and navigating both your slice’s business logic and its top-level entry points much easier.
As of this release, classes inside
slices/) no longer auto-register as application components.
If you wish to register a component with the application, you should create a file in
config/boot/ like this example in our current application template.
The idea with this change is to help minimize the coupling across the application overall. Components within the application are automatically imported into all slices (e.g. with the
Hanami.application["logger"] also available as
Main::Slice["application.logger"]), so the fewer application-wide components you carry, the better. In addition, Hanami gives you another option for more intentional sharing of behavior: more slices! If there’s a distinct subset of related components that you want to make accessible to numerous other slices, you should define them within their own slice, and import that wherever needed. You can currently achieve this like so (and we’ll be working to make it more ergonomic in future releases):
module MyApp class Application < Hanami::Application config.slice :main do # Importing a common "search" slice into the main slice; all components from the search # slice will be accessible with keys prefixed by "search." import :search end end end
While we’re encouraging you to look to additional slices for sharing components, we still want to make it straightforward to share and access other aspects of common behavior across your application. To this end, we’ve clarified the autoloading rules for
lib/: now, every file under the application’s namespace (such as
lib/my_app/my_class.rb) will be autoloaded and available without explicit requires, to ensure the experience is consistent across both the application and slice namespaces.
All files in
lib/ outside the application namespace (such as
lib/some/other/class.rb) will not be autoloaded, and will need a
require just like working with regular Ruby gems. This gives you a place to build out non-core, complementary code in your application without it being interfered with by the autoloader.
As of this release, your application settings are now no longer defined within an anonymous block, and are instead delivered as a concrete class, still defined in
require "hanami/application/settings" module MyApp class Settings < Hanami::Application::Settings setting :my_secret end end
The benefit these living within a class is that it gives us a place to hang all sorts of regular Ruby code to enhance the settings loading and delivery. For instance, it’s now possible to define an inline types module with dry-types, to provide an expressive types library for validating and coercing your settings:
require "dry/types" require "hanami/application/settings" module MyApp class Settings < Hanami::Application::Settings Types = Dry.Types() setting :my_secret, constructor: Types::String.constrained(min_size: 20) end end
And since the settings are based on dry-configurable, you can now easily provide default values, too:
setting :my_bool, constructor: Types::Params::Bool, default: false
And finally, with a class at your disposal, you can also add your own methods to provide the best and most fit for purpose interface to your application settings:
require "dry/types" require "hanami/application/settings" module MyApp class Settings < Hanami::Application::Settings Types = Dry.Types() setting :some_account_key, constructor: Types::String.optional def some_account_enabled? !!some_account_key end end end
We’ve also reworked the application routes to match the approach we’ve taken for the settings. As of this release, your
config/routes.rb will no look something like this:
require "hanami/application/routes" module MyApp class Routes < Hanami::Application::Routes define do slice :main, at: "/" do root to: "home.show" end end end end
For now, switching from the anonymous block to the concrete class is the extent of the change, but we expect this will provide a useful hook for your own custom behavior in the future, too. Watch this space.
We have a assortment of small quality of life improvements to actions for this release:
- Session behavior within actions is now automatically included whenever sessions are enabled via your application-level settings.
- Automatic view rendering how now been moved out of the default implementation of
Hanami::Action#handlemethod, which is the where we expect you to put your own custom logic. With this change, you’ll no longer need to call
superif you want to keep the automatic view rendering behavior.
- All action exposures are now automatically passed to the view for rendering (and will be passed onto your template if you provide a same-named exposure in your view class)
This is a mostly internal change, but the framework settings defined in
Hanami::Configuration and exposed as
Hanami.application.config are now largely provided by dry-configurable, which will has made them significantly easier to maintain, and will provide us with some better building blocks for more extensible settings in future.
Today we’re releasing the following gems:
You can check out our Hanami 2 application template, which is up to date for this latest release and ready for you to use out as the starting point for your own app.
We’d really love for you to give the tires a good kick for this release in this particular: the more real-world testing we can have of our code loading changes, the better!
As of this alpha release, we believe we’ve now jumped the biggest hurdles in preparing the overall Hanami 2 structure.
From this point forward, we’ll be making monthly alpha releases, bringing together all the work from the month and making it easily accessible to you, along with high-level release announcements like this one. We’re excited to pick up the pace of development from here, and to round out the Hanami 2 vision with you along for the ride!
Thank you as ever for your support of Hanami! We can’t wait to hear from you about this release, and we’re looking forward to checking in with you again next month. 🙇🏻♂️🌸