hanami 2.3.0.beta1 → 2.3.0

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -1
  3. data/README.md +1 -3
  4. data/hanami.gemspec +8 -8
  5. data/lib/hanami/config/actions/content_security_policy.rb +2 -2
  6. data/lib/hanami/config/actions.rb +3 -2
  7. data/lib/hanami/config/router.rb +1 -0
  8. data/lib/hanami/config.rb +11 -19
  9. data/lib/hanami/extensions/action.rb +1 -0
  10. data/lib/hanami/extensions/operation/slice_configured_db_operation.rb +88 -0
  11. data/lib/hanami/extensions/operation.rb +8 -23
  12. data/lib/hanami/extensions/view/context.rb +2 -11
  13. data/lib/hanami/extensions/view/part.rb +3 -0
  14. data/lib/hanami/extensions/view/scope.rb +3 -0
  15. data/lib/hanami/extensions/view/slice_configured_context.rb +0 -7
  16. data/lib/hanami/extensions/view.rb +1 -0
  17. data/lib/hanami/helpers/assets_helper.rb +2 -2
  18. data/lib/hanami/middleware/content_security_policy_nonce.rb +3 -3
  19. data/lib/hanami/routes.rb +4 -3
  20. data/lib/hanami/slice/router.rb +201 -12
  21. data/lib/hanami/slice.rb +13 -0
  22. data/lib/hanami/slice_configurable.rb +1 -3
  23. data/lib/hanami/version.rb +1 -1
  24. data/lib/hanami/web/rack_logger.rb +25 -8
  25. data/lib/hanami.rb +15 -1
  26. data/spec/integration/action/format_config_spec.rb +2 -67
  27. data/spec/integration/action/slice_configuration_spec.rb +36 -36
  28. data/spec/integration/logging/request_logging_spec.rb +16 -0
  29. data/spec/integration/operations/extension_spec.rb +63 -0
  30. data/spec/integration/rack_app/body_parser_spec.rb +3 -3
  31. data/spec/integration/rack_app/rack_app_spec.rb +2 -2
  32. data/spec/integration/router/resource_routes_spec.rb +281 -0
  33. data/spec/unit/hanami/config/actions_spec.rb +2 -2
  34. metadata +19 -20
  35. data/spec/integration/view/context/settings_spec.rb +0 -46
  36. data/spec/unit/hanami/version_spec.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8faef478dec45e673c25c67704b0fd7a363e784061412c64e96735040f2d07f
4
- data.tar.gz: b88eac54b8ba6241645b616ba9eafd20d54edb888e7fca8abc9e310f414dabe5
3
+ metadata.gz: 38d55453c1d105a2082e3fb7b6f3ae75318261b02cf496db56832f7223fbb5d2
4
+ data.tar.gz: fe85b8b2cb513066219d58556d981e9afbad8c824415ef303d56134de19c1754
5
5
  SHA512:
6
- metadata.gz: 8233b2e453669ae1528c3cadd8032cbff3a7337c590bb0962d307ddd71bb8b18e28f56cc19a5644225efaf0ad0bfa2f5a008dd8fbae2615a9bc819906e47e1cc
7
- data.tar.gz: 07551dada781667f44be90593599a0f505e9580d82d98c70df4e18e4288651e68fb26130d3504bf228dd2b7d2237af7494d7cfac86cd06ece733920657adfa83
6
+ metadata.gz: 363fb71d90a7c35bc55a8eb45ab050314be92e3ef0eb074a5da75d57b8f034e653a3e640c2e49548f0e3dcdf7adaa8cb013fda940befbaf33066e71fd4deded4
7
+ data.tar.gz: 8de0ec686d58238d32397950322e90411158dc9089cbf134d32983a03d0ba5518b3a0338097ee0e8a46a35bc12688c348a498ada16cfa41201ce3824b7892ed9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Hanami
2
2
 
3
+ A flexible framework for maintainable Ruby apps.
4
+
5
+ A complete Hanami app is composed of multiple gems. For a complete overview of changes, see also these CHANGELOGs:
6
+
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
24
+
3
25
  ## [Unreleased]
4
26
 
5
27
  ### Added
@@ -14,6 +36,57 @@
14
36
 
15
37
  ### Security
16
38
 
39
+ ## [v2.3.0] - 2025-11-12
40
+
41
+ ### Added
42
+
43
+ - Add `resources` and `resource` methods to the routes DSL. (@afomera and @timriley in #1542 and #1548)
44
+
45
+ ```ruby
46
+ resources :users
47
+ # Generates:
48
+ # GET /users users.index
49
+ # GET /users/new users.new
50
+ # POST /users users.create
51
+ # GET /users/:id users.show
52
+ # GET /users/:id/edit users.edit
53
+ # PATCH /users/:id users.update
54
+ # DELETE /users/:id users.destroy
55
+
56
+ resource :profile
57
+ # Generates (singular, no index):
58
+ # GET /profile/new profile.new
59
+ # POST /profile profile.create
60
+ # GET /profile profile.show
61
+ # GET /profile/edit profile.edit
62
+ # PATCH /profile profile.update
63
+ # DELETE /profile profile.destroy
64
+ ```
65
+
66
+ ### Changed
67
+
68
+ - Enable body parsing middleware by default. (@timriley in #1549)
69
+
70
+ This will parse multipart form upload bodies in requests with content type of `multipart/form-data`, and JSON bodies in requests with content types of `application/json` or `application/vnd.api+json`.
71
+ - For standard logging, use block-based API to provide log payloads, so that log payloads are not generated if the log severity is less than the configured log level. (@p8 in #1550)
72
+
73
+ ### Fixed
74
+
75
+ - Avoid errors when eagerloading Zeitwerk (or when running `bin/rails zeitwerk:check` if your Hanami app is embedded within Rails) by skipping autoloading for extension files that may depend on non-installed gems. (@timriley in #1498)
76
+ - Only extend `Dry::Operation` for Hanami’s database layer when the hanami-db gem is bundled. (@timriley in #1490)
77
+ - Address deprecation warnings from previous usage of `JSON.fast_generate`. (@krzykamil in #1546)
78
+
79
+ ## [v2.3.0.beta1] - 2025-10-17
80
+
81
+ ### Changed
82
+
83
+ - Use updated API for `config.actions.formats`. (@timriley in #1544)
84
+ - Show relative paths in `MissingActionError`. (@kyleplump and @timriley in #1445)
85
+
86
+ ### Removed
87
+
88
+ - View context `settings` has been removed and is no longer accessible from templates. (@baweaver in #1536)
89
+
17
90
  ## [v2.3.0.beta1] - 2025-10-03
18
91
 
19
92
  ### Added
@@ -1512,5 +1585,7 @@ end
1512
1585
  - [Luca Guidi] Official support for MRI 2.0
1513
1586
 
1514
1587
 
1515
- [unreleased]: https://github.com/hanami/hanami/compare/v2.3.0.beta1...HEAD
1588
+ [unreleased]: https://github.com/hanami/hanami/compare/v2.3.0...HEAD
1589
+ [v2.3.0] https://github.com/hanami/hanami/compare/v2.3.0.beta2...v2.3.0
1590
+ [v2.3.0.beta2] https://github.com/hanami/hanami/compare/v2.3.0.beta1...v2.3.0.beta2
1516
1591
  [v2.3.0.beta1] https://github.com/hanami/hanami/compare/v2.2.1...v2.3.0.beta1
data/README.md CHANGED
@@ -21,8 +21,6 @@ These components are designed to be used independently or together in a Hanami a
21
21
 
22
22
  ## Installation
23
23
 
24
- Hanami supports Ruby (MRI) 3.1+.
25
-
26
24
  ```shell
27
25
  gem install hanami
28
26
  ```
@@ -95,7 +93,7 @@ $ bundle exec rspec path/to/spec.rb
95
93
 
96
94
  ### Development Requirements
97
95
 
98
- * Ruby >= 3.1
96
+ * Ruby >= 3.2
99
97
  * Bundler
100
98
  * Node.js
101
99
 
data/hanami.gemspec CHANGED
@@ -7,10 +7,10 @@ require "hanami/version"
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = "hanami"
9
9
  spec.version = Hanami::VERSION
10
- spec.authors = ["Luca Guidi"]
11
- spec.email = ["me@lucaguidi.com"]
12
- spec.summary = "The web, with simplicity"
13
- spec.description = "Hanami is a web framework for Ruby"
10
+ spec.authors = ["Hanakai team"]
11
+ spec.email = ["info@hanakai.org"]
12
+ spec.summary = "A flexible framework for maintainable Ruby apps"
13
+ spec.description = spec.summary
14
14
  spec.homepage = "http://hanamirb.org"
15
15
  spec.license = "MIT"
16
16
 
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.test_files = Dir["spec/**/*"]
28
28
  spec.require_paths = ["lib"]
29
29
  spec.metadata["rubygems_mfa_required"] = "true"
30
- spec.required_ruby_version = ">= 3.1"
30
+ spec.required_ruby_version = ">= 3.2"
31
31
 
32
32
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
33
33
 
@@ -37,9 +37,9 @@ Gem::Specification.new do |spec|
37
37
  spec.add_dependency "dry-inflector", "~> 1.0", ">= 1.1.0", "< 2"
38
38
  spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
39
39
  spec.add_dependency "dry-system", "~> 1.1"
40
- spec.add_dependency "dry-logger", "~> 1.0", "< 2"
41
- spec.add_dependency "hanami-cli", "~> 2.3.0.beta1"
42
- spec.add_dependency "hanami-utils", "~> 2.2"
40
+ spec.add_dependency "dry-logger", "~> 1.2", "< 2"
41
+ spec.add_dependency "hanami-cli", ">= 2.3.0"
42
+ spec.add_dependency "hanami-utils", ">= 2.3.0"
43
43
  spec.add_dependency "json", ">= 2.7.2"
44
44
  spec.add_dependency "zeitwerk", "~> 2.6"
45
45
  spec.add_dependency "rack-session"
@@ -101,7 +101,7 @@ module Hanami
101
101
  # @return [Boolean]
102
102
  #
103
103
  # @api public
104
- # @since x.x.x
104
+ # @since 2.3.0
105
105
  def nonce?
106
106
  @policy.any? { _2.match?(/'nonce'/) }
107
107
  end
@@ -112,7 +112,7 @@ module Hanami
112
112
  # @return [Array<(Symbol, Array)>]
113
113
  #
114
114
  # @api public
115
- # @since x.x.x
115
+ # @since 2.3.0
116
116
  def middleware
117
117
  return [] unless nonce?
118
118
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/configurable"
4
+ require "hanami/action"
4
5
 
5
6
  module Hanami
6
7
  class Config
@@ -88,7 +89,7 @@ module Hanami
88
89
  # @return [Proc]
89
90
  #
90
91
  # @api public
91
- # @since x.x.x
92
+ # @since 2.3.0
92
93
  setting :content_security_policy_nonce_generator, default: -> { SecureRandom.urlsafe_base64(16) }
93
94
 
94
95
  # @!attribute [rw] method_override
@@ -156,7 +157,7 @@ module Hanami
156
157
  end
157
158
 
158
159
  # @api public
159
- # @since x.x.x
160
+ # @since 2.3.0
160
161
  def content_security_policy? = !!@content_security_policy
161
162
 
162
163
  private
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/configurable"
4
+ require_relative "../slice/routing/resolver"
4
5
 
5
6
  module Hanami
6
7
  class Config
data/lib/hanami/config.rb CHANGED
@@ -187,12 +187,12 @@ module Hanami
187
187
 
188
188
  # @!attribute [rw] console
189
189
  # Returns the app's console config
190
- #
190
+ #
191
191
  # @example
192
192
  # config.console.engine # => :irb
193
- #
193
+ #
194
194
  # @return [Hanami::Config::Console]
195
- #
195
+ #
196
196
  # @api public
197
197
  # @since 2.3.0
198
198
  setting :console, default: Hanami::Config::Console.new
@@ -320,7 +320,6 @@ module Hanami
320
320
  self.render_detailed_errors = (env == :development)
321
321
  load_from_env
322
322
 
323
-
324
323
  @actions = load_dependent_config("hanami-controller") {
325
324
  require_relative "config/actions"
326
325
  Actions.new
@@ -336,6 +335,7 @@ module Hanami
336
335
  @logger = Config::Logger.new(env: env, app_name: app_name)
337
336
 
338
337
  @middleware = load_dependent_config("hanami-router") {
338
+ require_relative "slice/routing/middleware/stack"
339
339
  Slice::Routing::Middleware::Stack.new
340
340
  }
341
341
 
@@ -484,24 +484,16 @@ module Hanami
484
484
  self.slices = ENV["HANAMI_SLICES"]&.split(",")&.map(&:strip)
485
485
  end
486
486
 
487
- SUPPORTED_MIDDLEWARE_PARSERS = %i[json].freeze
488
- private_constant :SUPPORTED_MIDDLEWARE_PARSERS
487
+ DEFAULT_MIDDLEWARE_PARSERS = {
488
+ form: ["multipart/form-data"],
489
+ json: ["application/json", "application/vnd.api+json"]
490
+ }.freeze
491
+ private_constant :DEFAULT_MIDDLEWARE_PARSERS
489
492
 
490
493
  def use_body_parser_middleware
491
- return unless Hanami.bundled?("hanami-controller")
492
-
493
- return if actions.formats.empty?
494
- return if middleware.stack["/"].map(&:first).any? { |klass| klass == "Hanami::Middleware::BodyParser" }
495
-
496
- parsers = SUPPORTED_MIDDLEWARE_PARSERS & actions.formats.values
497
- return if parsers.empty?
494
+ return unless Hanami.bundled?("hanami-router") && Hanami.bundled?("hanami-controller")
498
495
 
499
- middleware.use(
500
- :body_parser,
501
- [parsers.to_h { |parser_format|
502
- [parser_format, actions.formats.mime_types_for(parser_format)]
503
- }]
504
- )
496
+ middleware.use(:body_parser, [DEFAULT_MIDDLEWARE_PARSERS])
505
497
  end
506
498
 
507
499
  def load_dependent_config(gem_name)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "hanami/action"
4
+ require_relative "action/slice_configured_action"
4
5
 
5
6
  module Hanami
6
7
  # @api private
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module Extensions
5
+ module Operation
6
+ # Extends operations to support the database.
7
+ #
8
+ # Add an initializer accepting a `rom:` dependency, which is supplied automatically from the
9
+ # `"db.rom"` component in the operation's slice.
10
+ #
11
+ # @api private
12
+ class SliceConfiguredDBOperation < Module
13
+ attr_reader :slice
14
+
15
+ def initialize(slice)
16
+ super()
17
+ @slice = slice
18
+ end
19
+
20
+ def extended(operation_class)
21
+ require "dry/operation/extensions/rom"
22
+ operation_class.include Dry::Operation::Extensions::ROM
23
+
24
+ operation_class.include InstanceMethods
25
+ operation_class.include SliceInstanceMethods.new(slice)
26
+ define_new
27
+ end
28
+
29
+ def inspect
30
+ "#<#{self.class.name}[#{slice.name}>"
31
+ end
32
+
33
+ private
34
+
35
+ def define_new
36
+ resolve_rom = method(:resolve_rom)
37
+
38
+ define_method(:new) do |**kwargs|
39
+ super(
40
+ **kwargs,
41
+ rom: kwargs.fetch(:rom) { resolve_rom.() },
42
+ )
43
+ end
44
+ end
45
+
46
+ def resolve_rom
47
+ slice["db.rom"] if slice.key?("db.rom")
48
+ end
49
+
50
+ module InstanceMethods
51
+ attr_reader :rom
52
+
53
+ def initialize(rom:, **)
54
+ @rom = rom
55
+ end
56
+ end
57
+
58
+ class SliceInstanceMethods < Module
59
+ attr_reader :slice
60
+
61
+ def initialize(slice)
62
+ @slice = slice
63
+ end
64
+
65
+ def included(operation_class)
66
+ define_transaction
67
+ end
68
+
69
+ private
70
+
71
+ def define_transaction
72
+ slice = self.slice
73
+ define_method(:transaction) do |**kwargs, &block|
74
+ unless rom
75
+ msg = <<~TEXT.strip
76
+ A configured db for #{slice} is required to run transactions.
77
+ TEXT
78
+ raise Hanami::ComponentLoadError, msg
79
+ end
80
+
81
+ super(**kwargs, &block)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -11,38 +11,23 @@ module Hanami
11
11
  # @api public
12
12
  # @since 2.2.0
13
13
  module Operation
14
+ require_relative "operation/slice_configured_db_operation"
15
+
14
16
  # @api private
15
- # @since 2.2.0
16
- def self.included(operation_class)
17
+ def self.extended(operation_class)
17
18
  super
18
19
 
19
20
  operation_class.extend(Hanami::SliceConfigurable)
20
- operation_class.extend(ClassMethods)
21
21
  end
22
22
 
23
- # @api private
24
- # @since 2.2.0
25
- module ClassMethods
26
- # @api private
27
- # @since 2.2.0
28
- def configure_for_slice(slice)
29
- include slice.namespace::Deps["db.rom"]
30
- end
31
-
32
- # @api private
33
- # @since 2.2.0
34
- def inherited(subclass)
35
- super
23
+ # private
36
24
 
37
- return unless subclass.superclass == self
38
- return unless Hanami.bundled?("hanami-db")
39
-
40
- require "dry/operation/extensions/rom"
41
- subclass.include Dry::Operation::Extensions::ROM
42
- end
25
+ # @api private
26
+ def configure_for_slice(slice)
27
+ extend SliceConfiguredDBOperation.new(slice) if Hanami.bundled?("hanami-db")
43
28
  end
44
29
  end
45
30
  end
46
31
  end
47
32
 
48
- Dry::Operation.include(Hanami::Extensions::Operation)
33
+ Dry::Operation.extend(Hanami::Extensions::Operation)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../../errors"
4
+ require_relative "slice_configured_context"
4
5
 
5
6
  module Hanami
6
7
  module Extensions
@@ -90,28 +91,18 @@ module Hanami
90
91
  # @since 2.1.0
91
92
  attr_reader :inflector
92
93
 
93
- # Returns the app's settings.
94
- #
95
- # @return [Hanami::Settings] the settings
96
- #
97
- # @api public
98
- # @since 2.1.0
99
- attr_reader :settings
100
-
101
94
  # @see SliceConfiguredContext#define_new
102
95
  #
103
96
  # @api private
104
97
  # @since 2.1.0
105
98
  def initialize( # rubocop:disable Metrics/ParameterLists
106
99
  inflector: nil,
107
- settings: nil,
108
100
  routes: nil,
109
101
  assets: nil,
110
102
  request: nil,
111
103
  **args
112
104
  )
113
105
  @inflector = inflector
114
- @settings = settings
115
106
  @routes = routes
116
107
  @assets = assets
117
108
  @request = request
@@ -177,7 +168,7 @@ module Hanami
177
168
  # @return [Boolean]
178
169
  #
179
170
  # @api public
180
- # @since x.x.x
171
+ # @since 2.3.0
181
172
  def request?
182
173
  !!@request
183
174
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "standard_helpers"
4
+ require_relative "slice_configured_part"
5
+
3
6
  module Hanami
4
7
  module Extensions
5
8
  module View
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "slice_configured_helpers"
4
+ require_relative "standard_helpers"
5
+
3
6
  module Hanami
4
7
  module Extensions
5
8
  module View
@@ -37,18 +37,15 @@ module Hanami
37
37
  #
38
38
  # This includes the following app components:
39
39
  # - the configured inflector as `inflector`
40
- # - "settings" from the app container as `settings`
41
40
  # - "routes" from the app container as `routes`
42
41
  # - "assets" from the app container as `assets`
43
42
  def define_new
44
43
  inflector = slice.inflector
45
- resolve_settings = method(:resolve_settings)
46
44
  resolve_routes = method(:resolve_routes)
47
45
  resolve_assets = method(:resolve_assets)
48
46
 
49
47
  define_method :new do |**kwargs|
50
48
  kwargs[:inflector] ||= inflector
51
- kwargs[:settings] ||= resolve_settings.()
52
49
  kwargs[:routes] ||= resolve_routes.()
53
50
  kwargs[:assets] ||= resolve_assets.()
54
51
 
@@ -56,10 +53,6 @@ module Hanami
56
53
  end
57
54
  end
58
55
 
59
- def resolve_settings
60
- slice["settings"] if slice.key?("settings")
61
- end
62
-
63
56
  def resolve_routes
64
57
  slice["routes"] if slice.key?("routes")
65
58
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "hanami/view"
4
+ require_relative "view/slice_configured_view"
4
5
 
5
6
  module Hanami
6
7
  # @api private
@@ -710,7 +710,7 @@ module Hanami
710
710
  #
711
711
  # @return [String, nil] nonce value of the current request
712
712
  #
713
- # @since x.x.x
713
+ # @since 2.3.0
714
714
  #
715
715
  # @example App configuration
716
716
  #
@@ -766,7 +766,7 @@ module Hanami
766
766
  _context.assets.crossorigin?(source)
767
767
  end
768
768
 
769
- # @since x.x.x
769
+ # @since 2.3.0
770
770
  # @api private
771
771
  def _nonce(source, nonce_option)
772
772
  if nonce_option == false
@@ -14,16 +14,16 @@ module Hanami
14
14
  # @see Hanami::Middleware::ContentSecurityPolicyNonce
15
15
  #
16
16
  # @api private
17
- # @since x.x.x
17
+ # @since 2.3.0
18
18
  class ContentSecurityPolicyNonce
19
19
  # @api private
20
- # @since x.x.x
20
+ # @since 2.3.0
21
21
  def initialize(app)
22
22
  @app = app
23
23
  end
24
24
 
25
25
  # @api private
26
- # @since x.x.x
26
+ # @since 2.3.0
27
27
  def call(env)
28
28
  return @app.call(env) unless Hanami.app.config.actions.content_security_policy?
29
29
 
data/lib/hanami/routes.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "constants"
4
4
  require_relative "errors"
5
+ require_relative "slice/router"
5
6
 
6
7
  module Hanami
7
8
  # App routes
@@ -36,14 +37,14 @@ module Hanami
36
37
  def initialize(action_key, slice)
37
38
  action_path = action_key.gsub(CONTAINER_KEY_DELIMITER, PATH_DELIMITER)
38
39
  action_constant = slice.inflector.camelize(
39
- "#{slice.inflector.underscore(slice.namespace.to_s)}#{PATH_DELIMITER}#{action_path}"
40
+ slice.inflector.underscore(slice.namespace.to_s) + PATH_DELIMITER + action_path
40
41
  )
41
- action_file = slice.root.join("#{action_path}#{RB_EXT}")
42
+ action_file_path = slice.relative_source_path.join(action_path).to_s.concat(RB_EXT)
42
43
 
43
44
  super(<<~MSG)
44
45
  Could not find action with key #{action_key.inspect} in #{slice}
45
46
 
46
- To fix this, define the action class #{action_constant} in #{action_file}
47
+ To fix this, define the action class #{action_constant} in #{action_file_path}
47
48
  MSG
48
49
  end
49
50
  end