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
Streamlined application directories
tl;dr we simplified the source directory structures, slices/main/lib/main/my_class.rb
will now be slices/main/lib/my_class.rb
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 Main::Slice["my_class"]
.
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 actions/
, repositories/
, and views/
. With this, you can define an action like Main::Actions::Posts::Index
in slices/main/actions/posts/index.rb
, with the component accessible from the slice as Main::Slice["actions.posts.index"]
.
Together, these changes should make surveying and navigating both your slice’s business logic and its top-level entry points much easier.
Application no longer auto-registers components from lib/
As of this release, classes inside lib/
(unlike 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.
Reworked application settings
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 config/settings.rb
:
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
Reworked application routes
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.
Actions enhancements
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#handle
method, which is the where we expect you to put your own custom logic. With this change, you’ll no longer need to callsuper
if 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)
Framework settings ported to dry-configurable
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.
What’s included?
Today we’re releasing the following gems:
hanami
v2.0.0.alpha3hanami-cli
v2.0.0.alpha3hanami-view
v2.0.0.alpha3hanami-controller
v2.0.0.alpha3hanami-utils
v2.0.0.alpha3
How can I try it?
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!
What’s coming next?
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. 🙇🏻♂️🌸