hanami 2.0.0.beta3 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/hanami.gemspec +9 -8
- data/lib/hanami/app.rb +50 -39
- data/lib/hanami/assets/app_config.rb +61 -0
- data/lib/hanami/assets/{configuration.rb → config.rb} +9 -10
- data/lib/hanami/{configuration → config}/actions/content_security_policy.rb +3 -3
- data/lib/hanami/config/actions/cookies.rb +57 -0
- data/lib/hanami/config/actions/sessions.rb +83 -0
- data/lib/hanami/config/actions.rb +164 -0
- data/lib/hanami/config/logger.rb +176 -0
- data/lib/hanami/config/null_config.rb +14 -0
- data/lib/hanami/{configuration → config}/router.rb +8 -9
- data/lib/hanami/{configuration → config}/views.rb +16 -20
- data/lib/hanami/config.rb +396 -0
- data/lib/hanami/constants.rb +4 -0
- data/lib/hanami/errors.rb +20 -0
- data/lib/hanami/extensions/action/slice_configured_action.rb +10 -6
- data/lib/hanami/extensions/action.rb +59 -7
- data/lib/hanami/extensions/view/context.rb +3 -4
- data/lib/hanami/extensions/view/slice_configured_view.rb +4 -4
- data/lib/hanami/extensions/view.rb +7 -5
- data/lib/hanami/providers/inflector.rb +6 -2
- data/lib/hanami/providers/logger.rb +9 -3
- data/lib/hanami/providers/rack.rb +12 -2
- data/lib/hanami/providers/routes.rb +14 -6
- data/lib/hanami/routes.rb +36 -1
- data/lib/hanami/settings/env_store.rb +4 -4
- data/lib/hanami/settings.rb +169 -21
- data/lib/hanami/slice/router.rb +38 -16
- data/lib/hanami/slice/routing/middleware/stack.rb +108 -40
- data/lib/hanami/slice/routing/resolver.rb +10 -17
- data/lib/hanami/slice/view_name_inferrer.rb +1 -1
- data/lib/hanami/slice.rb +605 -51
- data/lib/hanami/slice_configurable.rb +1 -1
- data/lib/hanami/slice_registrar.rb +25 -14
- data/lib/hanami/version.rb +2 -3
- data/lib/hanami/web/rack_logger.rb +14 -4
- data/lib/hanami.rb +122 -24
- data/spec/integration/action/csrf_protection_spec.rb +1 -1
- data/spec/integration/container/application_routes_helper_spec.rb +3 -1
- data/spec/integration/container/prepare_container_spec.rb +2 -0
- data/spec/integration/container/provider_lifecycle_spec.rb +61 -0
- data/spec/integration/container/standard_providers/rack_provider_spec.rb +44 -0
- data/spec/integration/container/{standard_bootable_components_spec.rb → standard_providers_spec.rb} +3 -3
- data/spec/integration/rack_app/body_parser_spec.rb +111 -0
- data/spec/integration/rack_app/middleware_spec.rb +455 -3
- data/spec/integration/rack_app/non_booted_rack_app_spec.rb +2 -1
- data/spec/integration/rack_app/rack_app_spec.rb +39 -11
- data/spec/integration/settings/access_in_slice_class_body_spec.rb +82 -0
- data/spec/integration/settings/access_to_constants_spec.rb +23 -146
- data/spec/integration/{slices/slice_settings_spec.rb → settings/slice_registration_spec.rb} +5 -1
- data/spec/integration/settings/using_types_spec.rb +4 -11
- data/spec/integration/setup_spec.rb +4 -4
- data/spec/integration/slices/external_slice_spec.rb +2 -1
- data/spec/integration/slices/slice_configuration_spec.rb +3 -1
- data/spec/integration/slices/slice_loading_spec.rb +4 -4
- data/spec/integration/slices/slice_routing_spec.rb +4 -3
- data/spec/integration/slices_spec.rb +100 -0
- data/spec/isolation/hanami/boot/success_spec.rb +1 -1
- data/spec/support/app_integration.rb +10 -15
- data/spec/unit/hanami/{configuration → config}/actions/content_security_policy_spec.rb +16 -16
- data/spec/unit/hanami/{configuration → config}/actions/cookies_spec.rb +6 -6
- data/spec/unit/hanami/{configuration → config}/actions/csrf_protection_spec.rb +12 -12
- data/spec/unit/hanami/config/actions/default_values_spec.rb +54 -0
- data/spec/unit/hanami/{configuration → config}/actions/sessions_spec.rb +6 -8
- data/spec/unit/hanami/{configuration → config}/actions_spec.rb +8 -20
- data/spec/unit/hanami/{configuration → config}/base_url_spec.rb +2 -2
- data/spec/unit/hanami/{configuration → config}/inflector_spec.rb +2 -2
- data/spec/unit/hanami/{configuration → config}/logger_spec.rb +42 -59
- data/spec/unit/hanami/{configuration → config}/router_spec.rb +7 -8
- data/spec/unit/hanami/{configuration → config}/slices_spec.rb +2 -2
- data/spec/unit/hanami/{configuration → config}/views_spec.rb +13 -24
- data/spec/unit/hanami/settings_spec.rb +65 -10
- data/spec/unit/hanami/slice_configurable_spec.rb +21 -2
- data/spec/unit/hanami/slice_spec.rb +32 -0
- data/spec/unit/hanami/version_spec.rb +1 -1
- data/spec/unit/hanami/web/rack_logger_spec.rb +13 -2
- metadata +100 -76
- data/lib/hanami/assets/app_configuration.rb +0 -69
- data/lib/hanami/configuration/actions/cookies.rb +0 -29
- data/lib/hanami/configuration/actions/sessions.rb +0 -46
- data/lib/hanami/configuration/actions.rb +0 -101
- data/lib/hanami/configuration/logger.rb +0 -87
- data/lib/hanami/configuration/null_configuration.rb +0 -14
- data/lib/hanami/configuration/sessions.rb +0 -50
- data/lib/hanami/configuration.rb +0 -234
- data/lib/hanami/providers/settings.rb +0 -98
- data/spec/unit/hanami/configuration/actions/default_values_spec.rb +0 -52
- data/spec/unit/hanami/configuration_spec.rb +0 -43
data/lib/hanami/errors.rb
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Hanami
|
4
|
+
# Base class for all Hanami errors.
|
5
|
+
#
|
6
|
+
# @api public
|
4
7
|
# @since 2.0.0
|
5
8
|
Error = Class.new(StandardError)
|
6
9
|
|
10
|
+
# Error raised when {Hanami::App} fails to load.
|
11
|
+
#
|
12
|
+
# @api public
|
7
13
|
# @since 2.0.0
|
8
14
|
AppLoadError = Class.new(Error)
|
9
15
|
|
16
|
+
# Error raised when an {Hanami::Slice} fails to load.
|
17
|
+
#
|
18
|
+
# @api public
|
10
19
|
# @since 2.0.0
|
11
20
|
SliceLoadError = Class.new(Error)
|
12
21
|
|
22
|
+
# Error raised when an individual component fails to load.
|
23
|
+
#
|
24
|
+
# @api public
|
13
25
|
# @since 2.0.0
|
14
26
|
ComponentLoadError = Class.new(Error)
|
27
|
+
|
28
|
+
# Error raised when unsupported middleware configuration is given.
|
29
|
+
#
|
30
|
+
# @see Hanami::Slice::Routing::Middleware::Stack#use
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
# @since 2.0.0
|
34
|
+
UnsupportedMiddlewareSpecError = Class.new(Error)
|
15
35
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "hanami/action"
|
4
|
-
|
5
3
|
module Hanami
|
6
4
|
module Extensions
|
7
5
|
module Action
|
@@ -35,19 +33,21 @@ module Hanami
|
|
35
33
|
resolve_view = method(:resolve_paired_view)
|
36
34
|
resolve_view_context = method(:resolve_view_context)
|
37
35
|
resolve_routes = method(:resolve_routes)
|
36
|
+
resolve_rack_monitor = method(:resolve_rack_monitor)
|
38
37
|
|
39
38
|
define_method(:new) do |**kwargs|
|
40
39
|
super(
|
41
40
|
view: kwargs.fetch(:view) { resolve_view.(self) },
|
42
41
|
view_context: kwargs.fetch(:view_context) { resolve_view_context.() },
|
43
42
|
routes: kwargs.fetch(:routes) { resolve_routes.() },
|
43
|
+
rack_monitor: kwargs.fetch(:rack_monitor) { resolve_rack_monitor.() },
|
44
44
|
**kwargs,
|
45
45
|
)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
def configure_action(action_class)
|
50
|
-
action_class.
|
50
|
+
action_class.settings.each do |setting|
|
51
51
|
# Configure the action from config on the slice, _unless it has already been configured
|
52
52
|
# by a parent slice_, and re-configuring it for this slice would make no change.
|
53
53
|
#
|
@@ -86,12 +86,12 @@ module Hanami
|
|
86
86
|
# the `:json` value configured in its immediate superclass.
|
87
87
|
#
|
88
88
|
# This would be surprising behavior, and we want to avoid it.
|
89
|
-
slice_value = slice.config.actions.public_send(
|
90
|
-
parent_value = slice.parent.config.actions.public_send(
|
89
|
+
slice_value = slice.config.actions.public_send(setting.name)
|
90
|
+
parent_value = slice.parent.config.actions.public_send(setting.name) if slice.parent
|
91
91
|
|
92
92
|
next if slice.parent && slice_value == parent_value
|
93
93
|
|
94
|
-
action_class.config.public_send(:"#{setting}=", slice_value)
|
94
|
+
action_class.config.public_send(:"#{setting.name}=", slice_value)
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
@@ -137,6 +137,10 @@ module Hanami
|
|
137
137
|
slice.app["routes"] if slice.app.key?("routes")
|
138
138
|
end
|
139
139
|
|
140
|
+
def resolve_rack_monitor
|
141
|
+
slice.app["rack.monitor"] if slice.app.key?("rack.monitor")
|
142
|
+
end
|
143
|
+
|
140
144
|
def actions_config
|
141
145
|
slice.config.actions
|
142
146
|
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "hanami/action"
|
4
|
-
require_relative "../slice_configurable"
|
5
|
-
require_relative "action/slice_configured_action"
|
6
4
|
|
7
5
|
module Hanami
|
6
|
+
# @api private
|
8
7
|
module Extensions
|
9
|
-
#
|
8
|
+
# Integrated behavior for `Hanami::Action` classes within Hanami apps.
|
10
9
|
#
|
11
|
-
# @see
|
10
|
+
# @see InstanceMethods
|
11
|
+
# @see https://github.com/hanami/controller
|
12
12
|
#
|
13
13
|
# @api public
|
14
14
|
# @since 2.0.0
|
15
15
|
module Action
|
16
|
+
# @api private
|
16
17
|
def self.included(action_class)
|
17
18
|
super
|
18
19
|
|
@@ -21,46 +22,97 @@ module Hanami
|
|
21
22
|
action_class.prepend(InstanceMethods)
|
22
23
|
end
|
23
24
|
|
25
|
+
# Class methods for app-integrated actions.
|
26
|
+
#
|
27
|
+
# @since 2.0.0
|
24
28
|
module ClassMethods
|
29
|
+
# @api private
|
25
30
|
def configure_for_slice(slice)
|
26
31
|
extend SliceConfiguredAction.new(slice)
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
35
|
+
# Instance methods for app-integrated actions.
|
36
|
+
#
|
37
|
+
# @since 2.0.0
|
30
38
|
module InstanceMethods
|
31
|
-
|
39
|
+
# @api private
|
40
|
+
attr_reader :view
|
32
41
|
|
33
|
-
|
42
|
+
# @api private
|
43
|
+
attr_reader :view_context
|
44
|
+
|
45
|
+
# Returns the app or slice's {Hanami::Slice::RoutesHelper RoutesHelper} for use within
|
46
|
+
# action instance methods.
|
47
|
+
#
|
48
|
+
# @return [Hanami::Slice::RoutesHelper]
|
49
|
+
#
|
50
|
+
# @api public
|
51
|
+
# @since 2.0.0
|
52
|
+
attr_reader :routes
|
53
|
+
|
54
|
+
# Returns the app or slice's `Dry::Monitor::Rack::Middleware` for use within
|
55
|
+
# action instance methods.
|
56
|
+
#
|
57
|
+
# @return [Dry::Monitor::Rack::Middleware]
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
# @since 2.0.0
|
61
|
+
attr_reader :rack_monitor
|
62
|
+
|
63
|
+
# @overload def initialize(routes: nil, **kwargs)
|
64
|
+
# Returns a new `Hanami::Action` with app components injected as dependencies.
|
65
|
+
#
|
66
|
+
# These dependencies are injected automatically so that a call to `.new` (with no
|
67
|
+
# arguments) returns a fully integrated action.
|
68
|
+
#
|
69
|
+
# @param routes [Hanami::Slice::RoutesHelper]
|
70
|
+
#
|
71
|
+
# @api public
|
72
|
+
# @since 2.0.0
|
73
|
+
def initialize(view: nil, view_context: nil, rack_monitor: nil, routes: nil, **kwargs)
|
34
74
|
@view = view
|
35
75
|
@view_context = view_context
|
36
76
|
@routes = routes
|
77
|
+
@rack_monitor = rack_monitor
|
37
78
|
|
38
79
|
super(**kwargs)
|
39
80
|
end
|
40
81
|
|
41
82
|
private
|
42
83
|
|
84
|
+
# @api private
|
43
85
|
def build_response(**options)
|
44
86
|
options = options.merge(view_options: method(:view_options))
|
45
87
|
super(**options)
|
46
88
|
end
|
47
89
|
|
90
|
+
# @api private
|
48
91
|
def finish(req, res, halted)
|
49
92
|
res.render(view, **req.params) if !halted && auto_render?(res)
|
50
93
|
super
|
51
94
|
end
|
52
95
|
|
96
|
+
# @api private
|
97
|
+
def _handle_exception(request, _response, exception)
|
98
|
+
rack_monitor&.instrument(:error, exception: exception, env: request.env)
|
99
|
+
|
100
|
+
super
|
101
|
+
end
|
102
|
+
|
103
|
+
# @api private
|
53
104
|
def view_options(req, res)
|
54
105
|
{context: view_context&.with(**view_context_options(req, res))}.compact
|
55
106
|
end
|
56
107
|
|
108
|
+
# @api private
|
57
109
|
def view_context_options(req, res)
|
58
110
|
{request: req, response: res}
|
59
111
|
end
|
60
112
|
|
61
113
|
# Returns true if a view should automatically be rendered onto the response body.
|
62
114
|
#
|
63
|
-
# This may be overridden to enable
|
115
|
+
# This may be overridden to enable or disable automatic rendering.
|
64
116
|
#
|
65
117
|
# @param res [Hanami::Action::Response]
|
66
118
|
#
|
@@ -3,16 +3,15 @@
|
|
3
3
|
require "hanami/view"
|
4
4
|
require "hanami/view/context"
|
5
5
|
require_relative "../../errors"
|
6
|
-
require_relative "../../slice_configurable"
|
7
|
-
require_relative "slice_configured_context"
|
8
6
|
|
9
7
|
module Hanami
|
10
8
|
module Extensions
|
11
9
|
module View
|
12
10
|
# View context for views in Hanami apps.
|
13
11
|
#
|
14
|
-
#
|
15
|
-
#
|
12
|
+
# This is NOT RELEASED as of 2.0.0.
|
13
|
+
#
|
14
|
+
# @api private
|
16
15
|
module Context
|
17
16
|
def self.included(context_class)
|
18
17
|
super
|
@@ -32,7 +32,7 @@ module Hanami
|
|
32
32
|
# rubocop:disable Metrics/AbcSize
|
33
33
|
def configure_view(view_class)
|
34
34
|
view_class.settings.each do |setting|
|
35
|
-
next unless slice.config.views.respond_to?(
|
35
|
+
next unless slice.config.views.respond_to?(setting.name)
|
36
36
|
|
37
37
|
# Configure the view from config on the slice, _unless it has already been configured by
|
38
38
|
# a parent slice_, and re-configuring it for this slice would make no change.
|
@@ -72,12 +72,12 @@ module Hanami
|
|
72
72
|
# in its immediate superclass.
|
73
73
|
#
|
74
74
|
# This would be surprising behavior, and we want to avoid it.
|
75
|
-
slice_value = slice.config.views.public_send(
|
76
|
-
parent_value = slice.parent.config.views.public_send(
|
75
|
+
slice_value = slice.config.views.public_send(setting.name)
|
76
|
+
parent_value = slice.parent.config.views.public_send(setting.name) if slice.parent
|
77
77
|
|
78
78
|
next if slice.parent && slice_value == parent_value
|
79
79
|
|
80
|
-
view_class.config.public_send(:"#{setting}=", slice_value)
|
80
|
+
view_class.config.public_send(:"#{setting.name}=", slice_value)
|
81
81
|
end
|
82
82
|
|
83
83
|
view_class.config.inflector = inflector
|
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "hanami/view"
|
4
|
-
require_relative "../slice_configurable"
|
5
|
-
require_relative "view/slice_configured_view"
|
6
4
|
|
7
5
|
module Hanami
|
6
|
+
# @api private
|
8
7
|
module Extensions
|
9
|
-
#
|
8
|
+
# Integrated behavior for `Hanami::View` classes within Hanami apps.
|
9
|
+
#
|
10
|
+
# This is NOT RELEASED as of 2.0.0.
|
10
11
|
#
|
11
12
|
# @see Hanami::View
|
12
13
|
#
|
13
|
-
# @api
|
14
|
-
# @since 2.0.0
|
14
|
+
# @api private
|
15
15
|
module View
|
16
|
+
# @api private
|
16
17
|
def self.included(view_class)
|
17
18
|
super
|
18
19
|
|
@@ -20,6 +21,7 @@ module Hanami
|
|
20
21
|
view_class.extend(ClassMethods)
|
21
22
|
end
|
22
23
|
|
24
|
+
# @api private
|
23
25
|
module ClassMethods
|
24
26
|
# @api private
|
25
27
|
def configure_for_slice(slice)
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/system/provider/source"
|
4
|
-
|
5
3
|
module Hanami
|
4
|
+
# @api private
|
6
5
|
module Providers
|
6
|
+
# Provider source to register inflector component in Hanami slices.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 2.0.0
|
7
10
|
class Inflector < Dry::System::Provider::Source
|
11
|
+
# @api private
|
8
12
|
def start
|
9
13
|
register :inflector, Hanami.app.inflector
|
10
14
|
end
|
@@ -1,12 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/system/provider/source"
|
4
|
-
|
5
3
|
module Hanami
|
4
|
+
# @api private
|
6
5
|
module Providers
|
6
|
+
# Provider source to register logger component in Hanami slices.
|
7
|
+
#
|
8
|
+
# @see Hanami::Config#logger
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 2.0.0
|
7
12
|
class Logger < Dry::System::Provider::Source
|
13
|
+
# @api private
|
8
14
|
def start
|
9
|
-
register :logger, Hanami.app.
|
15
|
+
register :logger, Hanami.app.config.logger_instance
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|
@@ -1,10 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/system/provider/source"
|
4
|
-
|
5
3
|
module Hanami
|
4
|
+
# @api private
|
6
5
|
module Providers
|
6
|
+
# Provider source to register Rack integration components in Hanami slices.
|
7
|
+
#
|
8
|
+
# @see Hanami::Providers::Logger
|
9
|
+
# @see Hanami::Web::RackLogger
|
10
|
+
# @see https://github.com/rack/rack
|
11
|
+
# @see https://dry-rb.org/gems/dry-monitor/
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 2.0.0
|
7
15
|
class Rack < Dry::System::Provider::Source
|
16
|
+
# @api private
|
8
17
|
def prepare
|
9
18
|
require "dry/monitor"
|
10
19
|
require "hanami/web/rack_logger"
|
@@ -12,6 +21,7 @@ module Hanami
|
|
12
21
|
Dry::Monitor.load_extensions(:rack)
|
13
22
|
end
|
14
23
|
|
24
|
+
# @api private
|
15
25
|
def start
|
16
26
|
target.start :logger
|
17
27
|
|
@@ -1,29 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/system/provider/source"
|
4
|
-
|
5
3
|
module Hanami
|
4
|
+
# @api private
|
6
5
|
module Providers
|
6
|
+
# Provider source to register routes helper component in Hanami slices.
|
7
|
+
#
|
8
|
+
# @see Hanami::Slice::RoutesHelper
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 2.0.0
|
7
12
|
class Routes < Dry::System::Provider::Source
|
13
|
+
# @api private
|
8
14
|
def self.for_slice(slice)
|
9
15
|
Class.new(self) do |klass|
|
10
16
|
klass.instance_variable_set(:@slice, slice)
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
20
|
+
# @api private
|
14
21
|
def self.slice
|
15
22
|
@slice || Hanami.app
|
16
23
|
end
|
17
24
|
|
25
|
+
# @api private
|
18
26
|
def prepare
|
19
27
|
require "hanami/slice/routes_helper"
|
20
28
|
end
|
21
29
|
|
30
|
+
# @api private
|
22
31
|
def start
|
23
|
-
# Register a lazy instance of RoutesHelper to ensure we don't load prematurely
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# slice.
|
32
|
+
# Register a lazy instance of RoutesHelper to ensure we don't load prematurely load the
|
33
|
+
# router during the process of booting. This ensures the router's resolver can run strict
|
34
|
+
# action key checks once when it runs on a fully booted slice.
|
27
35
|
register :routes do
|
28
36
|
Hanami::Slice::RoutesHelper.new(self.class.slice.router)
|
29
37
|
end
|
data/lib/hanami/routes.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative "constants"
|
4
|
+
require_relative "errors"
|
4
5
|
|
5
6
|
module Hanami
|
6
7
|
# App routes
|
@@ -25,6 +26,40 @@ module Hanami
|
|
25
26
|
# @see Hanami::Slice::Router
|
26
27
|
# @since 2.0.0
|
27
28
|
class Routes
|
29
|
+
# Error raised when no action could be found in an app or slice container for the key given in a
|
30
|
+
# routes file.
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
# @since 2.0.0
|
34
|
+
class MissingActionError < Hanami::Error
|
35
|
+
# @api private
|
36
|
+
def initialize(action_key, slice)
|
37
|
+
action_path = action_key.gsub(CONTAINER_KEY_DELIMITER, PATH_DELIMITER)
|
38
|
+
action_constant = slice.inflector.camelize(
|
39
|
+
"#{slice.inflector.underscore(slice.namespace.to_s)}#{PATH_DELIMITER}#{action_path}"
|
40
|
+
)
|
41
|
+
action_file = slice.root.join("#{action_path}#{RB_EXT}")
|
42
|
+
|
43
|
+
super(<<~MSG)
|
44
|
+
Could not find action with key #{action_key.inspect} in #{slice}
|
45
|
+
|
46
|
+
To fix this, define the action class #{action_constant} in #{action_file}
|
47
|
+
MSG
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Error raised when a given routes endpoint does not implement the `#call` interface required
|
52
|
+
# for Rack.
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
# @since 2.0.0
|
56
|
+
class NotCallableEndpointError < Hanami::Error
|
57
|
+
# @api private
|
58
|
+
def initialize(endpoint)
|
59
|
+
super("#{endpoint.inspect} is not compatible with Rack. Please make sure it implements #call.")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
28
63
|
# @api private
|
29
64
|
def self.routes
|
30
65
|
@routes ||= build_routes
|
@@ -4,7 +4,7 @@ require "dry/core/constants"
|
|
4
4
|
|
5
5
|
module Hanami
|
6
6
|
class Settings
|
7
|
-
# The default store for {Hanami
|
7
|
+
# The default store for {Hanami::Settings}, loading setting values from `ENV`.
|
8
8
|
#
|
9
9
|
# If your app loads the dotenv gem, then `ENV` will also be populated from various `.env` files when
|
10
10
|
# you subclass `Hanami::App`.
|
@@ -12,7 +12,7 @@ module Hanami
|
|
12
12
|
# @since 2.0.0
|
13
13
|
# @api private
|
14
14
|
class EnvStore
|
15
|
-
|
15
|
+
NO_ARG = Object.new.freeze
|
16
16
|
|
17
17
|
attr_reader :store, :hanami_env
|
18
18
|
|
@@ -21,9 +21,9 @@ module Hanami
|
|
21
21
|
@hanami_env = hanami_env
|
22
22
|
end
|
23
23
|
|
24
|
-
def fetch(name, default_value =
|
24
|
+
def fetch(name, default_value = NO_ARG, &block)
|
25
25
|
name = name.to_s.upcase
|
26
|
-
args = default_value
|
26
|
+
args = default_value.eql?(NO_ARG) ? [name] : [name, default_value]
|
27
27
|
|
28
28
|
store.fetch(*args, &block)
|
29
29
|
end
|