Happy new year, Hanami community! To get 2022 started, we're excited to announce the release of Hanami 2.0.0.alpha5!
This release brings the last month of our work on Hanami 2.0 (with an extra week added for good measure, while we all returned from our end of year breaks). It includes:
- Sensible default configuration for the application logger
- Comprehensive source dirs configuration (for advanced users)
- Lazy router and Rack app initialization
- Access to the application route helpers from the view context
- RSS support in our default MIME type list
Default application logger configuration
In our ongoing effort to strip boilerplate from our application template, we now ship a sensible default configuration for the application logger.
The defaults are:
- In production, log for level
info
, send logs to$stdout
in JSON format without colors - In development, log for level
debug
, send logs to$stdout
in single-line format with colors - In test, log for level
debug
, send logs tolog/test.log
in single-line format without colors
These defaults mean we've now achieved sensible behavior for a zero-configuration Hanami application class:
# config/application.rb
require "hanami"
module MyApp
class Application < Hanami::Application
end
end
You can customize the logger config as much as you need:
module MyApp
class Application < Hanami::Application
config.logger.level = :info
config.logger.stream = $stdout
config.logger.stream = "/path/to/file"
config.logger.stream = StringIO.new
config.logger.format = :json
config.logger.format = MyCustomFormatter.new
config.logger.color = false # disable coloring
config.logger.color = MyCustomColorizer.new
config.logger.filters << "secret" # add
config.logger.filters += ["yet", "another"] # add
config.logger.filters = ["foo"] # replace
# See https://ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html
config.logger.options = ["daily"] # time based log rotation
config.logger.options = [0, 1048576] # size based log rotation
end
end
You can also customize the config specifically for given environments:
module MyApp
class Application < Hanami::Application
config.environment(:staging) do
config.logger.level = :info
end
end
end
And finally, you can assign a completely custom logger object:
module MyApp
class Application < Hanami::Application
config.logger = MyCustomLogger.new
end
end
Comprehensive source dirs configuration (for advanced users)
In the 2.0.0.alpha3 release, we introduced streamlined source directories for the Ruby source files within each slice. Just like we’re doing with our application logger, we ship a sensible default configuration out of the box. Now with alpha5, we’re introducing a new config.source_dirs
setting that you can use to fully customize this configuration.
This will allow you to add and configure your own additional component dirs (which are the directories used to auto-register application components):
module MyApp
class Application < Hanami::Application
# Adding a simple component dir
config.source_dirs.component_dirs.add "serializers"
# Adding a component dir with custom configuration
config.source_dirs.component_dirs.add "serializers" do |dir|
dir.auto_register = proc { |component|
!component.identifier.start_with?("structs")
}
end
end
end
You can also customize the configuration of the default component dirs ("lib", "actions", "repositories", "views"):
module MyApp
class Application < Hanami::Application
# Customising a default component dir
config.source_dirs.component_dirs.dir("lib").auto_register = proc { |component|
!component.identifier.start_with?("structs")
}
# Setting default config to apply to all component dirs
config.source_dirs.component_dirs.auto_register = proc { |component|
!component.identifier.start_with?("entities")
}
# Removing a default component dir
config.source_dirs.component_dirs.delete("views")
end
end
The config.source_dirs.component_dirs
setting is provided by dry-system’s own Dry::System::Config::ComponentDirs
, so you can use this to configure any aspect of component loading as you require.
In addition to component dirs, you can also configure your own autoload paths, for source files you don’t want registered as components, but whose classes you still want to access inside your application. These directories are helpful for any classes that you will directly instantiate with their own data rather than dependencies, such as entities, structs, or any other kind of value class.
Out of the box, our autoload_paths
is ["entities"]
. You can configure this as required:
module MyApp
class Application < Hanami::Application
# Adding your own autoload paths
config.source_dirs.autoload_paths << "structs"
# Or providing a full replacement
config.source_dirs.autoload_paths = ["structs"]
end
end
Lazy router and Rack app initialization
One of the most powerful features of Hanami 2 is your ability to partially boot the application, loading only the specific components you need to complete a particular task. This makes testing considerably faster, but it also opens up flexible deployment opportunities, such as optimising the performance of certain production workloads by only loading particular subsets of your application.
With this release, this flexibility has been extended to the application router and its Rack interface, which are now initialized lazily, allowing you to access the router and rack app even if your application has not fully booted. The rack app is now available as .rack_app
on your application class, and can be accessed at any time after the application’s initial "init" step:
# Example config.ru
# Loads the Hanami app at config/application.rb and runs Hanami.init
#
# n.b. this does _not_ fully boot the application, so most components are not
# loaded, but routes are still accessible and their supporting components will
# also be lazily loaded when required
require "hanami/init"
run Hanami.rack_app
Access to the Rack app in this way opens up the possibility of a slimline deployment of a your application configured to serve only a small subset of its overall routes. In this case, only the minimal subset of components will be loaded to serve the given routes. This may be helpful for fine-grained deployment to resource-constrained targets like serverless functions.
Closer to home, this is also the first step towards faster code reloading when running the application in development mode. We’ll be working on this in future releases.
Route helpers via the view context
Last month we made the route helpers available in actions, and now we’re making them available in views too, via our default view context. This means you can access routes
inside any template:
/ slices/main/web/templates/books/index.html.slim
- books.each do |book|
p
a href=routes.url(:book, id: book.id) = book.title
Given the context is exposed to view parts and scopes, you can access routes
there as well.
RSS support in our default MIME type list
You can now configure your Hanami actions to work with RSS formatted requests and responses via the new rss
entry in our default MIME types list.
What’s included?
Today we’re releasing the following gems:
hanami v2.0.0.alpha5
hanami-controller v2.0.0.alpha5
hanami-view v2.0.0.alpha5
Contributors
Thank you to these fine people for contributing to this release!
How can I try it?
You can check out our Hanami 2 application template, which is up to date for this release and ready for you to try as the starting point for your own app.
What’s coming next?
We’ll be back in February for alpha6, bringing our next month of development direct to you.