hanami 2.3.2 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -19
  3. data/LICENSE +20 -0
  4. data/README.md +18 -35
  5. data/hanami.gemspec +36 -37
  6. data/lib/hanami/config/db.rb +2 -0
  7. data/lib/hanami/config/i18n.rb +138 -0
  8. data/lib/hanami/config/logger.rb +15 -7
  9. data/lib/hanami/config/null_config.rb +1 -1
  10. data/lib/hanami/config/views.rb +17 -0
  11. data/lib/hanami/config.rb +66 -22
  12. data/lib/hanami/errors.rb +6 -0
  13. data/lib/hanami/extensions/action/slice_configured_action.rb +1 -1
  14. data/lib/hanami/extensions/action.rb +2 -2
  15. data/lib/hanami/extensions/mailer/slice_configured_mailer.rb +120 -0
  16. data/lib/hanami/extensions/mailer.rb +28 -0
  17. data/lib/hanami/extensions/operation/slice_configured_db_operation.rb +2 -0
  18. data/lib/hanami/extensions/view/context.rb +26 -4
  19. data/lib/hanami/extensions/view/part.rb +2 -0
  20. data/lib/hanami/extensions/view/slice_configured_context.rb +7 -0
  21. data/lib/hanami/extensions/view/slice_configured_part.rb +2 -0
  22. data/lib/hanami/extensions/view/slice_configured_view.rb +8 -8
  23. data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
  24. data/lib/hanami/extensions.rb +6 -1
  25. data/lib/hanami/helpers/assets_helper.rb +0 -4
  26. data/lib/hanami/helpers/form_helper.rb +1 -1
  27. data/lib/hanami/helpers/i18n_helper.rb +176 -0
  28. data/lib/hanami/logger/rack_formatter.rb +73 -0
  29. data/lib/hanami/logger/sql_formatter.rb +80 -0
  30. data/lib/hanami/logger/sql_logger.rb +48 -0
  31. data/lib/hanami/middleware/render_errors.rb +2 -2
  32. data/lib/hanami/providers/db.rb +7 -2
  33. data/lib/hanami/providers/db_logging.rb +4 -7
  34. data/lib/hanami/providers/i18n/backend.rb +369 -0
  35. data/lib/hanami/providers/i18n/locale/en.yml +57 -0
  36. data/lib/hanami/providers/i18n.rb +114 -0
  37. data/lib/hanami/providers/mailers.rb +101 -0
  38. data/lib/hanami/routes.rb +1 -0
  39. data/lib/hanami/settings/composite_store.rb +53 -0
  40. data/lib/hanami/settings.rb +4 -4
  41. data/lib/hanami/slice/router.rb +15 -10
  42. data/lib/hanami/slice.rb +71 -11
  43. data/lib/hanami/slice_registrar.rb +2 -2
  44. data/lib/hanami/universal_logger.rb +250 -0
  45. data/lib/hanami/version.rb +1 -1
  46. data/lib/hanami/web/rack_logger.rb +2 -80
  47. data/lib/hanami/web/welcome.html.erb +443 -58
  48. data/lib/hanami.rb +4 -2
  49. metadata +28 -276
  50. data/CODE_OF_CONDUCT.md +0 -74
  51. data/FEATURES.md +0 -269
  52. data/LICENSE.md +0 -22
  53. data/spec/integration/action/cookies_spec.rb +0 -58
  54. data/spec/integration/action/csrf_protection_spec.rb +0 -54
  55. data/spec/integration/action/format_config_spec.rb +0 -129
  56. data/spec/integration/action/routes_spec.rb +0 -71
  57. data/spec/integration/action/sessions_spec.rb +0 -50
  58. data/spec/integration/action/slice_configuration_spec.rb +0 -284
  59. data/spec/integration/action/view_rendering/automatic_rendering_spec.rb +0 -247
  60. data/spec/integration/action/view_rendering/paired_view_inference_spec.rb +0 -115
  61. data/spec/integration/action/view_rendering/view_context_spec.rb +0 -221
  62. data/spec/integration/action/view_rendering_spec.rb +0 -89
  63. data/spec/integration/assets/assets_spec.rb +0 -155
  64. data/spec/integration/assets/cross_slice_assets_helpers_spec.rb +0 -129
  65. data/spec/integration/assets/serve_static_assets_spec.rb +0 -152
  66. data/spec/integration/code_loading/loading_from_app_spec.rb +0 -152
  67. data/spec/integration/code_loading/loading_from_lib_spec.rb +0 -242
  68. data/spec/integration/code_loading/loading_from_slice_spec.rb +0 -165
  69. data/spec/integration/container/application_routes_helper_spec.rb +0 -48
  70. data/spec/integration/container/auto_injection_spec.rb +0 -53
  71. data/spec/integration/container/auto_registration_spec.rb +0 -86
  72. data/spec/integration/container/autoloader_spec.rb +0 -82
  73. data/spec/integration/container/imports_spec.rb +0 -253
  74. data/spec/integration/container/prepare_container_spec.rb +0 -125
  75. data/spec/integration/container/provider_environment_spec.rb +0 -52
  76. data/spec/integration/container/provider_lifecycle_spec.rb +0 -61
  77. data/spec/integration/container/shutdown_spec.rb +0 -91
  78. data/spec/integration/container/standard_providers/rack_provider_spec.rb +0 -44
  79. data/spec/integration/container/standard_providers_spec.rb +0 -124
  80. data/spec/integration/db/auto_registration_spec.rb +0 -39
  81. data/spec/integration/db/commands_spec.rb +0 -80
  82. data/spec/integration/db/db_inflector_spec.rb +0 -57
  83. data/spec/integration/db/db_slices_spec.rb +0 -398
  84. data/spec/integration/db/db_spec.rb +0 -245
  85. data/spec/integration/db/gateways_spec.rb +0 -361
  86. data/spec/integration/db/logging_spec.rb +0 -301
  87. data/spec/integration/db/mappers_spec.rb +0 -84
  88. data/spec/integration/db/provider_config_spec.rb +0 -88
  89. data/spec/integration/db/provider_spec.rb +0 -35
  90. data/spec/integration/db/relations_spec.rb +0 -60
  91. data/spec/integration/db/repo_spec.rb +0 -300
  92. data/spec/integration/db/slices_importing_from_parent.rb +0 -130
  93. data/spec/integration/dotenv_loading_spec.rb +0 -138
  94. data/spec/integration/logging/exception_logging_spec.rb +0 -120
  95. data/spec/integration/logging/notifications_spec.rb +0 -68
  96. data/spec/integration/logging/request_logging_spec.rb +0 -202
  97. data/spec/integration/operations/extension_spec.rb +0 -122
  98. data/spec/integration/rack_app/body_parser_spec.rb +0 -108
  99. data/spec/integration/rack_app/method_override_spec.rb +0 -97
  100. data/spec/integration/rack_app/middleware_spec.rb +0 -720
  101. data/spec/integration/rack_app/non_booted_rack_app_spec.rb +0 -104
  102. data/spec/integration/rack_app/rack_app_spec.rb +0 -442
  103. data/spec/integration/rake_tasks_spec.rb +0 -107
  104. data/spec/integration/router/resource_routes_spec.rb +0 -281
  105. data/spec/integration/settings/access_in_slice_class_body_spec.rb +0 -83
  106. data/spec/integration/settings/access_to_constants_spec.rb +0 -46
  107. data/spec/integration/settings/loading_from_env_spec.rb +0 -188
  108. data/spec/integration/settings/settings_component_loading_spec.rb +0 -113
  109. data/spec/integration/settings/slice_registration_spec.rb +0 -145
  110. data/spec/integration/settings/using_types_spec.rb +0 -80
  111. data/spec/integration/setup_spec.rb +0 -165
  112. data/spec/integration/slices/external_slice_spec.rb +0 -91
  113. data/spec/integration/slices/slice_configuration_spec.rb +0 -42
  114. data/spec/integration/slices/slice_loading_spec.rb +0 -171
  115. data/spec/integration/slices/slice_registrations_spec.rb +0 -80
  116. data/spec/integration/slices/slice_routing_spec.rb +0 -219
  117. data/spec/integration/slices_spec.rb +0 -471
  118. data/spec/integration/view/config/default_context_spec.rb +0 -149
  119. data/spec/integration/view/config/inflector_spec.rb +0 -57
  120. data/spec/integration/view/config/part_class_spec.rb +0 -147
  121. data/spec/integration/view/config/part_namespace_spec.rb +0 -103
  122. data/spec/integration/view/config/paths_spec.rb +0 -119
  123. data/spec/integration/view/config/scope_class_spec.rb +0 -147
  124. data/spec/integration/view/config/scope_namespace_spec.rb +0 -103
  125. data/spec/integration/view/config/template_spec.rb +0 -38
  126. data/spec/integration/view/context/assets_spec.rb +0 -79
  127. data/spec/integration/view/context/inflector_spec.rb +0 -40
  128. data/spec/integration/view/context/request_spec.rb +0 -57
  129. data/spec/integration/view/context/routes_spec.rb +0 -84
  130. data/spec/integration/view/helpers/form_helper_spec.rb +0 -174
  131. data/spec/integration/view/helpers/part_helpers_spec.rb +0 -124
  132. data/spec/integration/view/helpers/scope_helpers_spec.rb +0 -84
  133. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +0 -162
  134. data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +0 -119
  135. data/spec/integration/view/parts/default_rendering_spec.rb +0 -138
  136. data/spec/integration/view/slice_configuration_spec.rb +0 -289
  137. data/spec/integration/view/views_spec.rb +0 -103
  138. data/spec/integration/web/content_security_policy_nonce_spec.rb +0 -251
  139. data/spec/integration/web/render_detailed_errors_spec.rb +0 -107
  140. data/spec/integration/web/render_errors_spec.rb +0 -242
  141. data/spec/integration/web/welcome_view_spec.rb +0 -84
  142. data/spec/spec_helper.rb +0 -28
  143. data/spec/support/app_integration.rb +0 -157
  144. data/spec/support/coverage.rb +0 -1
  145. data/spec/support/matchers.rb +0 -32
  146. data/spec/support/rspec.rb +0 -27
  147. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +0 -96
  148. data/spec/unit/hanami/config/actions/cookies_spec.rb +0 -46
  149. data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +0 -58
  150. data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -43
  151. data/spec/unit/hanami/config/actions/sessions_spec.rb +0 -48
  152. data/spec/unit/hanami/config/actions_spec.rb +0 -52
  153. data/spec/unit/hanami/config/base_url_spec.rb +0 -25
  154. data/spec/unit/hanami/config/console_spec.rb +0 -22
  155. data/spec/unit/hanami/config/db_spec.rb +0 -38
  156. data/spec/unit/hanami/config/inflector_spec.rb +0 -35
  157. data/spec/unit/hanami/config/logger_spec.rb +0 -195
  158. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +0 -25
  159. data/spec/unit/hanami/config/render_errors_spec.rb +0 -25
  160. data/spec/unit/hanami/config/router_spec.rb +0 -44
  161. data/spec/unit/hanami/config/slices_spec.rb +0 -34
  162. data/spec/unit/hanami/config/views_spec.rb +0 -80
  163. data/spec/unit/hanami/env_spec.rb +0 -37
  164. data/spec/unit/hanami/extensions/view/context_spec.rb +0 -59
  165. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +0 -120
  166. data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +0 -132
  167. data/spec/unit/hanami/helpers/assets_helper/favicon_tag_spec.rb +0 -87
  168. data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +0 -92
  169. data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +0 -143
  170. data/spec/unit/hanami/helpers/assets_helper/stylesheet_tag_spec.rb +0 -126
  171. data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +0 -136
  172. data/spec/unit/hanami/helpers/form_helper_spec.rb +0 -2857
  173. data/spec/unit/hanami/port_spec.rb +0 -117
  174. data/spec/unit/hanami/providers/db/config/default_config_spec.rb +0 -100
  175. data/spec/unit/hanami/providers/db/config/gateway_spec.rb +0 -73
  176. data/spec/unit/hanami/providers/db/config_spec.rb +0 -143
  177. data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +0 -27
  178. data/spec/unit/hanami/router/errors/not_found_error_spec.rb +0 -22
  179. data/spec/unit/hanami/settings/env_store_spec.rb +0 -52
  180. data/spec/unit/hanami/settings_spec.rb +0 -111
  181. data/spec/unit/hanami/slice_configurable_spec.rb +0 -141
  182. data/spec/unit/hanami/slice_name_spec.rb +0 -47
  183. data/spec/unit/hanami/slice_spec.rb +0 -99
  184. data/spec/unit/hanami/web/rack_logger_spec.rb +0 -99
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83aa8539603f6f36097cafc14e3808b5ccc9c6797b8ba1e84e43c180f4f09b3b
4
- data.tar.gz: 4b739af805d108359042c2c87529f7f258aaf4f05567efe4ebf457cf60175687
3
+ metadata.gz: c0629b02399ba598bc3d4cbcd3c421b6312e06bee5f6e1f41a5608b2cac18ec0
4
+ data.tar.gz: fde643ae7b04a53c3047ff88f27856177bc16905e1bbe65ee577142ae1cdb35f
5
5
  SHA512:
6
- metadata.gz: 6199e57e74e60b8b2206511a7ac86ec1f853e7c5103cbdf425b79cb085c32f297658e2f5d5c36346945fa3c4218070f9e88b2b8e42c4ddb9328241c426b846a5
7
- data.tar.gz: 2b94c7d2829d04580602f14637210316e7b24488ccfb343254c7b6cbc77b870f5cdeb3c5482e3eb41c160097e413248e4269a1a1b7ce1fbda38d267874c25999
6
+ metadata.gz: 1a27833e74d730e9ba84222cf739a6e503d5ae733846ba0abf0ecc21d527fbb3e0f416902f37d82064d773b18456fe803f85fd7085a5367ba9a6744efaac49be
7
+ data.tar.gz: ac8e58a76c42b02a967c2d2c86769b019dc5f4321408d877250c446ddb851c4199a781e7594e4c0bca54f3211bcdd86093af6a5393127e380cc59227aa7af883
data/CHANGELOG.md CHANGED
@@ -1,26 +1,27 @@
1
1
  # Hanami
2
2
 
3
- A flexible framework for maintainable Ruby apps.
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Break Versioning](https://www.taoensso.com/break-versioning).
4
6
 
5
7
  A complete Hanami app is composed of multiple gems. For a complete overview of changes, see also these CHANGELOGs:
6
8
 
7
- [Assets][assets], [Assets JS][assets-js], [CLI][cli],
8
- [Controller][controller], [DB][db], [RSpec][rspec],
9
- [Reloader][reloader], [Router][router], [Utils][utils],
10
- [Validations][validations], [View][view], [Webconsole][webconsole]
11
-
12
- [assets]: https://github.com/hanami/hanami-assets/blob/main/CHANGELOG.md
13
- [assets-js]: https://github.com/hanami/hanami-assets-js/blob/main/CHANGELOG.md
14
- [cli]: https://github.com/hanami/hanami-cli/blob/main/CHANGELOG.md
15
- [controller]: https://github.com/hanami/hanami-controller/blob/main/CHANGELOG.md
16
- [db]: https://github.com/hanami/hanami-db/blob/main/CHANGELOG.md
17
- [rspec]: https://github.com/hanami/hanami-rspec/blob/main/CHANGELOG.md
18
- [reloader]: https://github.com/hanami/hanami-reloader/blob/main/CHANGELOG.md
19
- [router]: https://github.com/hanami/hanami-router/blob/main/CHANGELOG.md
20
- [utils]: https://github.com/hanami/hanami-utils/blob/main/CHANGELOG.md
21
- [validations]: https://github.com/hanami/hanami-validations/blob/main/CHANGELOG.md
22
- [view]: https://github.com/hanami/hanami-view/blob/main/CHANGELOG.md
23
- [webconsole]: https://github.com/hanami/hanami-webconsole/blob/main/CHANGELOG.md
9
+ [Assets], [Assets JS], [CLI], [Action], [DB], [Mailer], [Minitest],
10
+ [RSpec], [Reloader], [Router], [Utils], [View], [Webconsole]
11
+
12
+ [Assets]: https://github.com/hanami/hanami-assets/blob/main/CHANGELOG.md
13
+ [Assets JS]: https://github.com/hanami/hanami-assets-js/blob/main/CHANGELOG.md
14
+ [CLI]: https://github.com/hanami/hanami-cli/blob/main/CHANGELOG.md
15
+ [Action]: https://github.com/hanami/hanami-action/blob/main/CHANGELOG.md
16
+ [DB]: https://github.com/hanami/hanami-db/blob/main/CHANGELOG.md
17
+ [Mailer]: https://github.com/hanami/hanami-mailer/blob/main/CHANGELOG.md
18
+ [Minitest]: https://github.com/hanami/hanami-minitest/blob/main/CHANGELOG.md
19
+ [RSpec]: https://github.com/hanami/hanami-rspec/blob/main/CHANGELOG.md
20
+ [Reloader]: https://github.com/hanami/hanami-reloader/blob/main/CHANGELOG.md
21
+ [Router]: https://github.com/hanami/hanami-router/blob/main/CHANGELOG.md
22
+ [Utils]: https://github.com/hanami/hanami-utils/blob/main/CHANGELOG.md
23
+ [View]: https://github.com/hanami/hanami-view/blob/main/CHANGELOG.md
24
+ [Webconsole]: https://github.com/hanami/hanami-webconsole/blob/main/CHANGELOG.md
24
25
 
25
26
  ## [Unreleased]
26
27
 
@@ -36,7 +37,42 @@ A complete Hanami app is composed of multiple gems. For a complete overview of c
36
37
 
37
38
  ### Security
38
39
 
39
- [unreleased]: https://github.com/hanami/hanami/compare/v2.3.2...HEAD
40
+ [unreleased]: https://github.com/hanami/hanami/compare/v3.0.0.rc1...HEAD
41
+
42
+ ## [3.0.0.rc1] - 2026-06-16
43
+
44
+ ### Added
45
+
46
+ - Integrate hanami-mailer gem when bundled. (@timriley in #1597, #1600)
47
+
48
+ Load templates from `templates/mailers/`. Register a `"mailers.delivery_method"`, which is either an SMTP mailer when `SMTP_ADDRESS`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_AUTHENTICATION` env vars are present. These can also be prefixed with a slice name. Register a test delivery always in the test env, and also in other envs when the env vars are absent.
49
+ - Integrate i18n gem when bundled. (@timriley in #1562, #1589, #1590, #1591, #1592)
50
+
51
+ Register an `"i18n"` component in each slice, which may be configured via `config.i18n` or a dedicated `:i18n` provider. Load translations from `config/i18n/` within each slice. Load shared translations from `config/i18n/shared/` at the app-level only. Bundle default English translations for `#localize`. Make helpers available in views and actions, which also prefix relative keys (with a leading ".") with their own dot-delimited template or action names.
52
+ - Wrap the configured app logger with `Hanami::UniversalLogger`, to provide a consistent logging interface regardless of the underlying logger. The app can now be depended upon to support (1) structured logging via keyword args passed to log methods, and (2) tagged logging via `#tagged`. (@timriley in #1567, #1568)
53
+ - Support `HANAMI_LOG_LEVEL` env var to set the log level (e.g. `HANAMI_LOG_LEVEL=warn bundle exec hanami server`). Takes precedence over `config.logger.level` set in `config/app.rb`. (@cllns in #1580)
54
+ - Add `config.db.log_level` setting, for changing the log level for SQL logs. (@katafrakt in #1587)
55
+ - New setting `:default_template_engine` that sets which template engine should be used by default when doing `hanami generate`. (@katafrakt in #1564)
56
+ - Add `Hanami::Settings::CompositeStore`, which can be used to chain setting lookups from multiple stores. (@aaronmallen in #1572)
57
+
58
+ ### Changed
59
+
60
+ - Default to memoizing all components, except in test env. Opt out for some or all components via `config.no_memoize`. (@timriley in #1573, #1599)
61
+ - Colorize logs by default in development env. (@timriley in #1566)
62
+ - Emit structured log entries for SQL queries, formatted consistently with request logs. (@timriley in #1569)
63
+ - Syntax highlight SQL in logs when the rouge gem is bundled. (@timriley in #1570)
64
+ - Colorize web request logs. (@timriley in #1571)
65
+ - Change default log level for SQL (and other database) statements from `:info` to `:debug`. (@katafrakt in #1595)
66
+ - Raise a helpful error message when the `Slice.call` Rack entrypoint is called and no routes are available. (@sandbergja in #1586)
67
+ - Apply extensions to hanami-action gem rather than hanami-controller (which is now retired). (@cllns in #1582)
68
+ - Redesign the new app welcome screen to match our new Hanakai visuals. (@makenosound in #1598)
69
+ - Require Ruby 3.3 or newer.
70
+
71
+ ### Removed
72
+
73
+ - Remove default body parsing middleware. This functionality has moved into Hanami Action. (@timriley in #1575)
74
+
75
+ [3.0.0.rc1]: https://github.com/hanami/hanami/compare/v2.3.2...v3.0.0.rc1
40
76
 
41
77
  ## [v2.3.2] - 2025-12-04
42
78
 
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015-2026 Hanakai team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,4 +1,14 @@
1
- # Hanami :cherry_blossom:
1
+ <!--- This file is synced from hanakai-rb/repo-sync -->
2
+
3
+ [actions]: https://github.com/hanami/hanami/actions
4
+ [chat]: https://discord.gg/naQApPAsZB
5
+ [forum]: https://discourse.hanamirb.org
6
+ [rubygem]: https://rubygems.org/gems/hanami
7
+
8
+ # Hanami [![Gem Version](https://badge.fury.io/rb/hanami.svg)][rubygem] [![CI Status](https://github.com/hanami/hanami/workflows/CI/badge.svg)][actions]
9
+
10
+ [![Forum](https://img.shields.io/badge/Forum-dc360f?logo=discourse&logoColor=white)][forum]
11
+ [![Chat](https://img.shields.io/badge/Chat-717cf8?logo=discord&logoColor=white)][chat]
2
12
 
3
13
  **A flexible framework for maintainable Ruby apps.**
4
14
 
@@ -7,18 +17,13 @@ Hanami is a **full-stack** Ruby web framework. It's made up of smaller, single-p
7
17
  This repository is for the full-stack framework, which provides the glue that ties all the parts together:
8
18
 
9
19
  * [**Hanami::Router**](https://github.com/hanami/router) - Rack compatible HTTP router for Ruby
10
- * [**Hanami::Controller**](https://github.com/hanami/controller) - Full featured, fast and testable actions for Rack
20
+ * [**Hanami::Action**](https://github.com/hanami/hanami-action) - Full featured, fast and testable actions for Rack
11
21
  * [**Hanami::View**](https://github.com/hanami/view) - Presentation with a separation between views and templates
12
22
  * [**Hanami::DB**](https://github.com/hanami/db) - Database integration, complete with migrations, repositories, relations, and structs
13
23
  * [**Hanami::Assets**](https://github.com/hanami/assets) - Assets management for Ruby
14
24
 
15
25
  These components are designed to be used independently or together in a Hanami application.
16
26
 
17
- ## Status
18
-
19
- [![Gem Version](https://badge.fury.io/rb/hanami.svg)](https://badge.fury.io/rb/hanami)
20
- [![CI](https://github.com/hanami/hanami/actions/workflows/ci.yml/badge.svg)](https://github.com/hanami/hanami/actions?query=workflow%3Aci+branch%3Amain)
21
-
22
27
  ## Installation
23
28
 
24
29
  ```shell
@@ -36,28 +41,9 @@ bundle exec hanami dev
36
41
 
37
42
  Please follow along with the [Getting Started guide](https://guides.hanamirb.org/getting-started/).
38
43
 
39
- ## Donations
40
-
41
- You can give back to Open Source, by supporting Hanami development via [GitHub Sponsors](https://github.com/sponsors/hanami).
42
-
43
- ## Contact
44
-
45
- * [Home page](http://hanamirb.org)
46
- * [Community](http://hanamirb.org/community)
47
- * [Guides](https://guides.hanamirb.org)
48
- * [Issues](https://github.com/hanami/hanami/issues)
49
- * [Forum](https://discourse.hanamirb.org)
50
- * [Chat](https://discord.gg/KFCxDmk3JQ)
51
-
52
- ## Community
53
-
54
- We care about building a friendly, inclusive and helpful community. We welcome people of all backgrounds, genders and experience levels, and respect you all equally.
55
-
56
- We do not tolerate nazis, transphobes, racists, or any kind of bigotry. See our [code of conduct](http://hanamirb.org/community/#code-of-conduct) for more.
57
-
58
44
  ## Contributing
59
45
 
60
- 1. Fork it ( https://github.com/hanami/hanami/fork )
46
+ 1. Fork it (https://github.com/hanami/hanami/fork)
61
47
  2. Create your feature branch (`git checkout -b my-new-feature`)
62
48
  3. Commit your changes (`git commit -am 'Add some feature'`)
63
49
  4. Push to the branch (`git push origin my-new-feature`)
@@ -91,16 +77,13 @@ To run a single test:
91
77
  $ bundle exec rspec path/to/spec.rb
92
78
  ```
93
79
 
94
- ### Development Requirements
80
+ ## Links
95
81
 
96
- * Ruby >= 3.2
97
- * Bundler
98
- * Node.js
82
+ - [User documentation](https://hanamirb.org)
83
+ - [API documentation](http://rubydoc.info/gems/hanami)
99
84
 
100
- ## Versioning
101
85
 
102
- Hanami uses [Semantic Versioning 2.0.0](http://semver.org).
86
+ ## License
103
87
 
104
- ## Copyright
88
+ See `LICENSE` file.
105
89
 
106
- Copyright © 2014–2025 Hanami Team – Released under MIT License.
data/hanami.gemspec CHANGED
@@ -1,50 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path("../lib", __FILE__)
4
- $LOAD_PATH.prepend(lib) unless $LOAD_PATH.include?(lib)
3
+ # This file is synced from hanakai-rb/repo-sync. To update it, edit repo-sync.yml.
4
+
5
+ lib = File.expand_path("lib", __dir__)
6
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
7
  require "hanami/version"
6
8
 
7
9
  Gem::Specification.new do |spec|
8
10
  spec.name = "hanami"
9
- spec.version = Hanami::VERSION
10
11
  spec.authors = ["Hanakai team"]
11
12
  spec.email = ["info@hanakai.org"]
12
- spec.summary = "A flexible framework for maintainable Ruby apps"
13
- spec.description = spec.summary
14
- spec.homepage = "http://hanamirb.org"
15
13
  spec.license = "MIT"
14
+ spec.version = Hanami::VERSION.dup
16
15
 
17
- spec.files = Dir[
18
- "CODE_OF_CONDUCT.md",
19
- "CHANGELOG.md",
20
- "FEATURES.md",
21
- "LICENSE.md",
22
- "README.md",
23
- "hanami.gemspec",
24
- "lib/**/*"
25
- ]
26
-
27
- spec.test_files = Dir["spec/**/*"]
16
+ spec.summary = "A flexible framework for maintainable Ruby apps"
17
+ spec.description = spec.summary
18
+ spec.homepage = "https://hanamirb.org"
19
+ spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "hanami.gemspec", "lib/**/*"]
20
+ spec.bindir = "exe"
21
+ spec.executables = Dir["exe/*"].map { |f| File.basename(f) }
28
22
  spec.require_paths = ["lib"]
29
- spec.metadata["rubygems_mfa_required"] = "true"
30
- spec.required_ruby_version = ">= 3.2"
31
-
32
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
33
-
34
- spec.add_dependency "bundler", ">= 2.0"
35
- spec.add_dependency "dry-configurable", "~> 1.0", ">= 1.2.0", "< 2"
36
- spec.add_dependency "dry-core", "~> 1.0", "< 2"
37
- spec.add_dependency "dry-inflector", "~> 1.0", ">= 1.1.0", "< 2"
38
- spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
39
- spec.add_dependency "dry-system", "~> 1.1"
40
- spec.add_dependency "dry-logger", "~> 1.2", "< 2"
41
- spec.add_dependency "hanami-cli", ">= 2.3.1"
42
- spec.add_dependency "hanami-utils", ">= 2.3.0"
43
- spec.add_dependency "json", ">= 2.7.2"
44
- spec.add_dependency "zeitwerk", "~> 2.6"
45
- spec.add_dependency "rack-session"
46
-
47
- spec.add_development_dependency "rspec", "~> 3.8"
23
+
24
+ spec.extra_rdoc_files = ["README.md", "CHANGELOG.md", "LICENSE"]
25
+
26
+ spec.metadata["changelog_uri"] = "https://github.com/hanami/hanami/blob/main/CHANGELOG.md"
27
+ spec.metadata["source_code_uri"] = "https://github.com/hanami/hanami"
28
+ spec.metadata["bug_tracker_uri"] = "https://github.com/hanami/hanami/issues"
29
+ spec.metadata["funding_uri"] = "https://github.com/sponsors/hanami"
30
+
31
+ spec.required_ruby_version = ">= 3.3"
32
+
33
+ spec.add_runtime_dependency "bundler", ">= 2.0"
34
+ spec.add_runtime_dependency "dry-configurable", "~> 1.0", ">= 1.2.0", "< 2"
35
+ spec.add_runtime_dependency "dry-core", "~> 1.0", "< 2"
36
+ spec.add_runtime_dependency "dry-inflector", "~> 1.0", ">= 1.1.0", "< 2"
37
+ spec.add_runtime_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
38
+ spec.add_runtime_dependency "dry-system", "~> 1.1"
39
+ spec.add_runtime_dependency "dry-logger", "~> 1.2", "< 2"
40
+ spec.add_runtime_dependency "hanami-cli", ">= 2.3.1"
41
+ spec.add_runtime_dependency "hanami-utils", ">= 2.3.0"
42
+ spec.add_runtime_dependency "json", ">= 2.7.2"
43
+ spec.add_runtime_dependency "zeitwerk", "~> 2.6"
44
+ spec.add_runtime_dependency "rack-session"
45
+ spec.add_development_dependency "rspec", "~> 3.8"
48
46
  spec.add_development_dependency "rack-test", "~> 2.0"
49
- spec.add_development_dependency "rake", "~> 13.0"
47
+ spec.add_development_dependency "rake", "~> 13.0"
50
48
  end
49
+
@@ -15,6 +15,8 @@ module Hanami
15
15
 
16
16
  setting :import_from_parent, default: false
17
17
 
18
+ setting :log_level, default: :debug
19
+
18
20
  private
19
21
 
20
22
  def method_missing(name, *args, &block)
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/configurable"
4
+ require_relative "../providers/i18n"
5
+
6
+ module Hanami
7
+ class Config
8
+ # Hanami I18n config
9
+ #
10
+ # @api public
11
+ # @since x.x.x
12
+ class I18n
13
+ include Dry::Configurable
14
+
15
+ # @!attribute [rw] default_locale
16
+ # Sets or returns the default locale to use for translations.
17
+ #
18
+ # Defaults to `:en`.
19
+ #
20
+ # @return [Symbol]
21
+ #
22
+ # @example
23
+ # config.i18n.default_locale = :fr
24
+ #
25
+ # @api public
26
+ # @since x.x.x
27
+ setting :default_locale, default: Providers::I18n::DEFAULT_LOCALE
28
+
29
+ # @!attribute [rw] available_locales
30
+ # Sets or returns the array of available locales for the application.
31
+ #
32
+ # When set, only these locales will be considered available, even if translation files exist
33
+ # for other locales. When empty or not set, all locales from loaded translation files are
34
+ # available.
35
+ #
36
+ # Defaults to `[]` (all loaded locales are available).
37
+ #
38
+ # @return [Array<Symbol>]
39
+ #
40
+ # @example Restrict to specific locales
41
+ # config.i18n.available_locales = [:en, :fr, :de]
42
+ #
43
+ # @api public
44
+ # @since x.x.x
45
+ setting :available_locales, default: Providers::I18n::DEFAULT_AVAILABLE_LOCALES
46
+
47
+ # @!attribute [rw] load_path
48
+ # Sets or returns the array of file path patterns for loading per-slice translation files.
49
+ #
50
+ # Patterns can be:
51
+ #
52
+ # - Relative paths/globs (resolved against the slice's own root)
53
+ # - Absolute paths (used as-is)
54
+ #
55
+ # Defaults to `["config/i18n/**/*.{yml,yaml,json,rb}"]`.
56
+ #
57
+ # See {#shared_load_path} for common translations that should be loaded into every slice.
58
+ #
59
+ # @return [Array<String>]
60
+ #
61
+ # @example Append custom paths
62
+ # config.i18n.load_path += ["config/custom_translations/**/*.yml"]
63
+ #
64
+ # @example Replace default paths
65
+ # config.i18n.load_path = ["translations/**/*.yml"]
66
+ #
67
+ # @api public
68
+ # @since x.x.x
69
+ setting :load_path, default: Providers::I18n::DEFAULT_LOAD_PATH
70
+
71
+ # @!attribute [rw] shared_load_path
72
+ # Sets or returns the array of file path patterns for loading translation files that
73
+ # should be shared across every slice in the app.
74
+ #
75
+ # Relative patterns are resolved against the **app root**, regardless of which slice is
76
+ # being loaded. Absolute paths are used as-is. Files matched by these patterns are loaded
77
+ # into every slice's i18n backend before that slice's own {#load_path} files, so
78
+ # slice-specific translations override shared ones on key conflicts.
79
+ #
80
+ # This is the recommended place for foundational translation data needed by every slice,
81
+ # such as the `date.*` and `time.*` keys used by `localize`.
82
+ #
83
+ # Defaults to `["config/i18n/shared/**/*.{yml,yaml,json,rb}"]`.
84
+ #
85
+ # @return [Array<String>]
86
+ #
87
+ # @example Disable shared translations
88
+ # config.i18n.shared_load_path = []
89
+ #
90
+ # @example Add another shared source
91
+ # config.i18n.shared_load_path += ["vendor/translations/**/*.yml"]
92
+ #
93
+ # @api public
94
+ # @since x.x.x
95
+ setting :shared_load_path, default: Providers::I18n::DEFAULT_SHARED_LOAD_PATH
96
+
97
+ # @!attribute [rw] fallbacks
98
+ # Sets or returns the locale fallbacks configuration for missing translations.
99
+ #
100
+ # When enabled, the i18n backend will fall back to other locales when a translation is
101
+ # missing in the requested locale.
102
+ #
103
+ # This can be set to `true` to enable default fallbacks, a hash to configure explicit
104
+ # fallback chains per locale, or an array to set a default fallback locale for all locales.
105
+ #
106
+ # Defaults to `nil` (fallbacks disabled).
107
+ #
108
+ # @return [Boolean, Hash, Array, nil]
109
+ #
110
+ # @example Enable default fallbacks
111
+ # config.i18n.fallbacks = true
112
+ #
113
+ # @example Configure fallbacks with a hash
114
+ # config.i18n.fallbacks = {de: [:de, :en], fr: [:fr, :en]}
115
+ #
116
+ # @example Configure a default fallback locale
117
+ # config.i18n.fallbacks = [:en]
118
+ #
119
+ # @api public
120
+ # @since x.x.x
121
+ setting :fallbacks
122
+
123
+ private
124
+
125
+ def method_missing(name, *args, &block)
126
+ if config.respond_to?(name)
127
+ config.public_send(name, *args, &block)
128
+ else
129
+ super
130
+ end
131
+ end
132
+
133
+ def respond_to_missing?(name, _include_all = false)
134
+ config.respond_to?(name) || super
135
+ end
136
+ end
137
+ end
138
+ end
@@ -28,6 +28,7 @@ module Hanami
28
28
  # Sets or returns the logger's level.
29
29
  #
30
30
  # Defaults to `:info` for the production environment and `:debug` for all others.
31
+ # Can be set via the `HANAMI_LOG_LEVEL` environment variable.
31
32
  #
32
33
  # @return [Symbol]
33
34
  #
@@ -122,9 +123,13 @@ module Hanami
122
123
  @env = env
123
124
 
124
125
  case env
125
- when :development, :test
126
+ when :development
126
127
  config.level = :debug
127
- config.stream = File.join("log", "#{env}.log") if env == :test
128
+ config.options = {colorize: true}
129
+ config.logger_constructor = method(:development_logger)
130
+ when :test
131
+ config.level = :debug
132
+ config.stream = File.join("log", "#{env}.log")
128
133
  config.logger_constructor = method(:development_logger)
129
134
  else
130
135
  config.level = :info
@@ -153,8 +158,9 @@ module Hanami
153
158
  def development_logger(_env, app_name, **options)
154
159
  Dry.Logger(app_name, **options) do |setup|
155
160
  setup
156
- .add_backend(log_if: -> entry { !entry.tag?(:rack) })
157
- .add_backend(formatter: :rack, log_if: -> entry { entry.tag?(:rack) })
161
+ .add_backend(log_if: -> entry { !entry.tag?(:rack) && !entry.tag?(:sql) })
162
+ .add_backend(log_if: -> entry { entry.tag?(:rack) }, formatter: Hanami::Logger::RackFormatter)
163
+ .add_backend(log_if: -> entry { entry.tag?(:sql) }, formatter: Hanami::Logger::SQLFormatter)
158
164
  end
159
165
  end
160
166
 
@@ -173,12 +179,14 @@ module Hanami
173
179
 
174
180
  # @api private
175
181
  def logger_constructor_options
176
- {stream: stream,
177
- level: level,
182
+ {
183
+ stream: stream,
184
+ level: ENV["HANAMI_LOG_LEVEL"]&.to_sym || level,
178
185
  formatter: formatter,
179
186
  filters: filters,
180
187
  template: template,
181
- **options}
188
+ **options
189
+ }
182
190
  end
183
191
 
184
192
  # @api private
@@ -5,7 +5,7 @@ require "dry/configurable"
5
5
  module Hanami
6
6
  class Config
7
7
  # NullConfig can serve as a fallback config object when out-of-gem config objects are not
8
- # available (specifically, when the hanami-controller, hanami-router or hanami-view gems are not
8
+ # available (specifically, when the hanami-action, hanami-router or hanami-view gems are not
9
9
  # loaded)
10
10
  class NullConfig
11
11
  include Dry::Configurable
@@ -16,6 +16,23 @@ module Hanami
16
16
  class Views
17
17
  include Dry::Configurable
18
18
 
19
+ # @!attribute [rw] default_template_engine
20
+ # Sets or returns the default template engine to use for generated views.
21
+ #
22
+ # Used by generators when no explicit template engine is specified.
23
+ # Supports `erb`, `haml`, and `slim`.
24
+ #
25
+ # Defaults to `"erb"`.
26
+ #
27
+ # @example
28
+ # config.views.default_template_engine = "slim"
29
+ #
30
+ # @return [String] the template engine name
31
+ #
32
+ # @api public
33
+ # @since 2.4.0
34
+ setting :default_template_engine, default: "erb"
35
+
19
36
  # @api private
20
37
  # @since 2.1.0
21
38
  attr_reader :base_config