We are very pleased to announce the release of dry-system 0.19.0! This release marks a huge step forward for dry-system, bringing support for Zeitwerk and other autoloaders, plus clearer configuration and improved consistency around component resolution for both finalized and lazy loading containers.
These changes will also pave the way for a seamless integration of Zeitwerk and dry-system into the new Hanami 2.0 application core. Until then, thanks to dry-rb serving as an independent foundation layer for Hanami, you can already try out these new features!
A dry-system container as of 0.19.0, configured for Zeitwerk, now looks like this:
require "dry/system/container"
require "dry/system/loader/autoloading"
require "zeitwerk"
class MyApp::Container < Dry::System::Container
configure do |config|
config.root = __dir__
config.component_dirs.loader = Dry::System::Loader::Autoloading
config.component_dirs.add_to_load_path = false
config.component_dirs.add "lib"
end
end
loader = Zeitwerk::Loader.new
loader.push_dir MyApp::Container.config.root.join("lib").realpath
loader.setup
Unlike the default loader, the new Dry::System::Loader::Autoloading
does not require
files itself when loading components. Instead, it references their class constants directly, allowing the missing constant resolution to trigger the autoloading behaviour of Zeitwerk and other autoloaders. This is all that's required to bring Zeitwerk and dry-system together! Combined with dry-system's auto-injector, you now have the best of both worlds: the convenience of auto-loading classes combined with all the loose-coupling benefits of injected dependencies.
The new component_dirs
setting also allows multiple component dirs to be added (these are where dry-system looks when loading a container's components) and configured independently:
class MyApp::Container < Dry::System::Container
configure do |config|
config.root = __dir__
# Defaults for all component dirs can be configured
config.component_dirs.default_namespace = "my_app"
# As well as settings for individual dirs
config.component_dirs.add "lib" do |dir|
dir.auto_register = proc do |component|
!component.identifier.start_with?('entities')
end
end
# Multiple component dirs can be added
config.component_dirs.add "app"
end
end
The auto_register
and memoize
component dir settings have been improved as part of this release, now accepting either simple truthy or falsey values, or a proc accepting a Dry::System::Component
and returning a truthy or falsey value. Using a proc makes it easy to configure fine-grained behavior on a component-per-component basis. Check out also the new Dry::System::Identifier
class as used above via component.identifier
: this is a new class that provides namespace-aware methods for querying container component identifiers, which is particularly useful in cases like the above.
Finally, we've given a lot of attention to making sure dry-system containers work consistently regardless of whether they're finalized or lazy loading their components. For example, # auto_register: false
magic comments are not respected in both cases, where previously they were ignored for a lazy loading container.
There's plenty more to learn about this release, including several breaking changes, so check out the changelog for all the details. And if you want to understand more of the thinking that went into these changes, also check out Tim’s open source status updates for this last November, December, January, and February (Yes, this release has been long in the making!).
With many internal improvements also in place for this release, we now see a clear picture of what's left before 1.0, and have filled out the dry-system 1.0 milestone with issues representing the remaining work. Please take a look and get in touch if you can help.
In the meantime, we hope you enjoy dry-system 0.19.0 and please let us know how you go with all the new features!