hanami 2.1.0.beta2.1 → 2.1.0.rc2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/hanami.gemspec +3 -3
- data/lib/hanami/config/actions.rb +16 -3
- data/lib/hanami/config/assets.rb +1 -1
- data/lib/hanami/config/views.rb +10 -2
- data/lib/hanami/config.rb +21 -12
- data/lib/hanami/extensions/action/slice_configured_action.rb +5 -5
- data/lib/hanami/extensions/action.rb +4 -4
- data/lib/hanami/extensions/view/context.rb +111 -19
- data/lib/hanami/extensions/view/part.rb +64 -3
- data/lib/hanami/extensions/view/scope.rb +7 -0
- data/lib/hanami/extensions/view/slice_configured_context.rb +12 -8
- data/lib/hanami/extensions/view/slice_configured_helpers.rb +12 -1
- data/lib/hanami/extensions/view/slice_configured_part.rb +71 -0
- data/lib/hanami/extensions/view/slice_configured_view.rb +14 -6
- data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
- data/lib/hanami/extensions/view.rb +5 -3
- data/lib/hanami/helpers/assets_helper.rb +47 -79
- data/lib/hanami/routes.rb +33 -2
- data/lib/hanami/slice.rb +12 -2
- data/lib/hanami/slice_registrar.rb +48 -23
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +70 -2
- data/lib/hanami/web/welcome.html.erb +203 -0
- data/lib/hanami/web/welcome.rb +46 -0
- data/spec/integration/assets/assets_spec.rb +14 -3
- data/spec/integration/logging/request_logging_spec.rb +65 -7
- data/spec/integration/rack_app/method_override_spec.rb +97 -0
- data/spec/integration/slices_spec.rb +275 -5
- data/spec/integration/view/context/assets_spec.rb +0 -8
- data/spec/integration/view/context/inflector_spec.rb +0 -8
- data/spec/integration/view/context/settings_spec.rb +0 -8
- data/spec/integration/view/helpers/part_helpers_spec.rb +2 -2
- data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +10 -10
- data/spec/integration/view/parts/default_rendering_spec.rb +138 -0
- data/spec/integration/web/welcome_view_spec.rb +84 -0
- data/spec/support/app_integration.rb +22 -4
- data/spec/unit/hanami/config/render_detailed_errors_spec.rb +1 -1
- data/spec/unit/hanami/helpers/assets_helper/{audio_spec.rb → audio_tag_spec.rb} +10 -14
- data/spec/unit/hanami/helpers/assets_helper/{favicon_spec.rb → favicon_tag_spec.rb} +7 -11
- data/spec/unit/hanami/helpers/assets_helper/{image_spec.rb → image_tag_spec.rb} +8 -12
- data/spec/unit/hanami/helpers/assets_helper/{javascript_spec.rb → javascript_tag_spec.rb} +14 -18
- data/spec/unit/hanami/helpers/assets_helper/{stylesheet_spec.rb → stylesheet_tag_spec.rb} +12 -16
- data/spec/unit/hanami/helpers/assets_helper/{video_spec.rb → video_tag_spec.rb} +11 -11
- data/spec/unit/hanami/version_spec.rb +1 -1
- metadata +28 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a6835d72654251d1461ea2ad61c9fe56ad9b37b0ff333d23dc444e205b32ab1
|
4
|
+
data.tar.gz: 3daf6e28931aa6abf0c3579d95c8e403c1ba12bbcb5879549825e03ae8e81556
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b79171920231066598260223766e9abaee75806c751bcf83ca9ddaa93ef2eabef1fabc3077674cb81f25e435fa8659a04f9c272200a4ed27fa02c271ac03531
|
7
|
+
data.tar.gz: 04072a74f320abda02874ace16c616db0f3db9bb63de4d3b00746f3c1898c1dc58a143abd47915c9ef0a32b0a5eda860bd9264bccd375779d87bb101e4686dc1
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,36 @@
|
|
2
2
|
|
3
3
|
The web, with simplicity.
|
4
4
|
|
5
|
+
## Changed
|
6
|
+
|
7
|
+
- [Tim Riley] Enable `config.render_detailed_errors` in development mode only by default. (#1365)
|
8
|
+
- [Tim Riley] Remove current_path from context (#1362)
|
9
|
+
|
10
|
+
## v2.1.0.rc1 - 2023-11-01
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- [Aaron Moodie & Tim Riley] Render a welcome page when no routes are defined (#1353)
|
15
|
+
- [Luca Guidi] Allow _Method Override_ by default, by mounting `Rack::MethodOverride` middleware. (#1344)
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
- [Luca Guidi] Ensure compatibility with Ruby Logger from stdlib (#1352)
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
|
23
|
+
- [Philip Arndt] Add support for a slice's class definition file to exist inside either `config/slices/[slice_name].rb` or `slices/[slice_name]/config/slice.rb`, in that order of precedence, so that a slice can provide its own definition which the app, or the slice's parent slice if that exists, can override if needed.
|
24
|
+
- [Tim Riley] Use `helpers` prefix to access helper methods from view parts (e.g. `helpers.format_number`)
|
25
|
+
- [Tim Riley] Make it possible to directly initialize view parts to ease their unit tests (#1357)
|
26
|
+
- [Tim Riley] Remove short names for assets helpers (#1356):
|
27
|
+
- Keep `javascript_tag` (remove `javascript` and `js` aliases)
|
28
|
+
- Keep `stylesheet_tag` (renamed from `stylesheet_link_tag`; remove `stylesheet` and `css` aliases)
|
29
|
+
- Keep `favicon_tag` (renamed from `favicon_link_tag`; remove `favicon` alias)
|
30
|
+
- Keep `image_tag` (remove `image` alias)
|
31
|
+
- Keep `video_tag` (remove `video` alias)
|
32
|
+
- Keep `audio_tag` (remove `audio` alias)
|
33
|
+
|
34
|
+
|
5
35
|
## v2.1.0.beta2.1 - 2023-10-04
|
6
36
|
|
7
37
|
### Added
|
data/hanami.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
lib = File.expand_path("../lib", __FILE__)
|
4
|
-
$LOAD_PATH.
|
4
|
+
$LOAD_PATH.prepend(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require "hanami/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
@@ -38,8 +38,8 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_dependency "dry-monitor", "~> 1.0", ">= 1.0.1", "< 2"
|
39
39
|
spec.add_dependency "dry-system", "~> 1.0", "< 2"
|
40
40
|
spec.add_dependency "dry-logger", "~> 1.0", "< 2"
|
41
|
-
spec.add_dependency "hanami-cli", "~> 2.1.
|
42
|
-
spec.add_dependency "hanami-utils", "~> 2.1.
|
41
|
+
spec.add_dependency "hanami-cli", "~> 2.1.rc"
|
42
|
+
spec.add_dependency "hanami-utils", "~> 2.1.rc"
|
43
43
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
44
44
|
|
45
45
|
spec.add_development_dependency "rspec", "~> 3.8"
|
@@ -74,20 +74,33 @@ module Hanami
|
|
74
74
|
# @since 2.0.0
|
75
75
|
attr_accessor :content_security_policy
|
76
76
|
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
77
|
+
# @!attribute [rw] method_override
|
78
|
+
# Sets or returns whether HTTP method override should be enabled for action classes.
|
79
|
+
#
|
80
|
+
# Defaults to true. You can override this by explicitly setting a
|
81
|
+
# true or false value.
|
82
|
+
#
|
83
|
+
# When true, this will mount `Rack::MethodOverride` in the Rack middleware stack of the App.
|
84
|
+
#
|
85
|
+
# @return [Boolean]
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
# @since 2.1.0
|
89
|
+
setting :method_override, default: true
|
80
90
|
|
81
91
|
# @!attribute [rw] name_inference_base
|
82
92
|
# @api private
|
93
|
+
# @since 2.1.0
|
83
94
|
setting :name_inference_base, default: "actions"
|
84
95
|
|
85
96
|
# @!attribute [rw] view_name_inferrer
|
86
97
|
# @api private
|
98
|
+
# @since 2.1.0
|
87
99
|
setting :view_name_inferrer, default: Slice::ViewNameInferrer
|
88
100
|
|
89
101
|
# @!attribute [rw] view_name_inference_base
|
90
102
|
# @api private
|
103
|
+
# @since 2.1.0
|
91
104
|
setting :view_name_inference_base, default: "views"
|
92
105
|
|
93
106
|
# @api private
|
data/lib/hanami/config/assets.rb
CHANGED
@@ -9,7 +9,7 @@ module Hanami
|
|
9
9
|
#
|
10
10
|
# This exposes all the settings from the standalone `Hanami::Assets` class, pre-configured with
|
11
11
|
# sensible defaults for actions within a full Hanami app. It also provides additional settings
|
12
|
-
# for further integration of
|
12
|
+
# for further integration of assets with other full stack app components.
|
13
13
|
#
|
14
14
|
# @since 2.1.0
|
15
15
|
# @api public
|
data/lib/hanami/config/views.rb
CHANGED
@@ -7,16 +7,22 @@ module Hanami
|
|
7
7
|
class Config
|
8
8
|
# Hanami views config
|
9
9
|
#
|
10
|
-
# This
|
10
|
+
# This exposes all the settings from the standalone `Hanami::View` class, pre-configured with
|
11
|
+
# sensible defaults for actions within a full Hanami app. It also provides additional settings
|
12
|
+
# for further integration of views with other full stack app components.
|
11
13
|
#
|
12
|
-
# @
|
14
|
+
# @since 2.1.0
|
15
|
+
# @api public
|
13
16
|
class Views
|
14
17
|
include Dry::Configurable
|
15
18
|
|
19
|
+
# @api private
|
20
|
+
# @since 2.1.0
|
16
21
|
attr_reader :base_config
|
17
22
|
protected :base_config
|
18
23
|
|
19
24
|
# @api private
|
25
|
+
# @since 2.1.0
|
20
26
|
def initialize(*)
|
21
27
|
super
|
22
28
|
|
@@ -26,6 +32,7 @@ module Hanami
|
|
26
32
|
end
|
27
33
|
|
28
34
|
# @api private
|
35
|
+
# @since 2.1.0
|
29
36
|
def initialize_copy(source)
|
30
37
|
super
|
31
38
|
@base_config = source.base_config.dup
|
@@ -33,6 +40,7 @@ module Hanami
|
|
33
40
|
private :initialize_copy
|
34
41
|
|
35
42
|
# @api private
|
43
|
+
# @since 2.1.0
|
36
44
|
def finalize!
|
37
45
|
return self if frozen?
|
38
46
|
|
data/lib/hanami/config.rb
CHANGED
@@ -251,16 +251,30 @@ module Hanami
|
|
251
251
|
|
252
252
|
# Returns the app's views config, or a null config if hanami-view is not bundled.
|
253
253
|
#
|
254
|
-
#
|
254
|
+
# @example When hanami-view is bundled
|
255
|
+
# config.views.paths # => [...]
|
255
256
|
#
|
256
|
-
# @
|
257
|
+
# @example When hanami-view is not bundled
|
258
|
+
# config.views.paths # => NoMethodError
|
259
|
+
#
|
260
|
+
# @return [Hanami::Config::Views, Hanami::Config::NullConfig]
|
261
|
+
#
|
262
|
+
# @api public
|
263
|
+
# @since 2.1.0
|
257
264
|
attr_reader :views
|
258
265
|
|
259
|
-
# Returns the app's
|
266
|
+
# Returns the app's views config, or a null config if hanami-view is not bundled.
|
260
267
|
#
|
261
|
-
#
|
268
|
+
# @example When hanami-view is bundled
|
269
|
+
# config.views.paths # => [...]
|
262
270
|
#
|
263
|
-
# @
|
271
|
+
# @example When hanami-view is not bundled
|
272
|
+
# config.views.paths # => NoMethodError
|
273
|
+
#
|
274
|
+
# @return [Hanami::Config::Assets, Hanami::Config::NullConfig]
|
275
|
+
#
|
276
|
+
# @api public
|
277
|
+
# @since 2.1.0
|
264
278
|
attr_reader :assets
|
265
279
|
|
266
280
|
# @api private
|
@@ -272,7 +286,7 @@ module Hanami
|
|
272
286
|
# Apply default values that are only knowable at initialize-time (vs require-time)
|
273
287
|
self.root = Dir.pwd
|
274
288
|
self.render_errors = (env == :production)
|
275
|
-
self.render_detailed_errors = (env
|
289
|
+
self.render_detailed_errors = (env == :development)
|
276
290
|
load_from_env
|
277
291
|
|
278
292
|
@logger = Config::Logger.new(env: env, app_name: app_name)
|
@@ -296,13 +310,8 @@ module Hanami
|
|
296
310
|
@assets = load_dependent_config("hanami-assets") {
|
297
311
|
require_relative "config/assets"
|
298
312
|
|
299
|
-
public_dir = root.join("public")
|
300
|
-
|
301
313
|
Hanami::Config::Assets.new(
|
302
|
-
|
303
|
-
sources: root.join("app", "assets"),
|
304
|
-
destination: public_dir.join("assets"),
|
305
|
-
manifest_path: public_dir.join("assets.json")
|
314
|
+
manifest_path: root.join("public", "assets.json")
|
306
315
|
)
|
307
316
|
}
|
308
317
|
|
@@ -31,14 +31,14 @@ module Hanami
|
|
31
31
|
# @see Hanami::Extensions::Action::InstanceMethods#initialize
|
32
32
|
def define_new
|
33
33
|
resolve_view = method(:resolve_paired_view)
|
34
|
-
|
34
|
+
view_context_class = method(:view_context_class)
|
35
35
|
resolve_routes = method(:resolve_routes)
|
36
36
|
resolve_rack_monitor = method(:resolve_rack_monitor)
|
37
37
|
|
38
38
|
define_method(:new) do |**kwargs|
|
39
39
|
super(
|
40
40
|
view: kwargs.fetch(:view) { resolve_view.(self) },
|
41
|
-
|
41
|
+
view_context_class: kwargs.fetch(:view_context_class) { view_context_class.() },
|
42
42
|
routes: kwargs.fetch(:routes) { resolve_routes.() },
|
43
43
|
rack_monitor: kwargs.fetch(:rack_monitor) { resolve_rack_monitor.() },
|
44
44
|
**kwargs,
|
@@ -128,9 +128,9 @@ module Hanami
|
|
128
128
|
nil
|
129
129
|
end
|
130
130
|
|
131
|
-
def
|
131
|
+
def view_context_class
|
132
132
|
if Hanami.bundled?("hanami-view")
|
133
|
-
return Extensions::View::Context.context_class(slice)
|
133
|
+
return Extensions::View::Context.context_class(slice)
|
134
134
|
end
|
135
135
|
|
136
136
|
# If hanami-view isn't bundled, try and find a possible third party context class with the
|
@@ -139,7 +139,7 @@ module Hanami
|
|
139
139
|
views_namespace = slice.namespace.const_get(:Views)
|
140
140
|
|
141
141
|
if views_namespace.const_defined?(:Context)
|
142
|
-
views_namespace.const_get(:Context)
|
142
|
+
views_namespace.const_get(:Context)
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
@@ -40,7 +40,7 @@ module Hanami
|
|
40
40
|
attr_reader :view
|
41
41
|
|
42
42
|
# @api private
|
43
|
-
attr_reader :
|
43
|
+
attr_reader :view_context_class
|
44
44
|
|
45
45
|
# Returns the app or slice's {Hanami::Slice::RoutesHelper RoutesHelper} for use within
|
46
46
|
# action instance methods.
|
@@ -70,9 +70,9 @@ module Hanami
|
|
70
70
|
#
|
71
71
|
# @api public
|
72
72
|
# @since 2.0.0
|
73
|
-
def initialize(view: nil,
|
73
|
+
def initialize(view: nil, view_context_class: nil, rack_monitor: nil, routes: nil, **kwargs)
|
74
74
|
@view = view
|
75
|
-
@
|
75
|
+
@view_context_class = view_context_class
|
76
76
|
@routes = routes
|
77
77
|
@rack_monitor = rack_monitor
|
78
78
|
|
@@ -104,7 +104,7 @@ module Hanami
|
|
104
104
|
|
105
105
|
# @api private
|
106
106
|
def view_options(request, response)
|
107
|
-
{context:
|
107
|
+
{context: view_context_class&.new(**view_context_options(request, response))}.compact
|
108
108
|
end
|
109
109
|
|
110
110
|
# @api private
|
@@ -7,15 +7,15 @@ module Hanami
|
|
7
7
|
module View
|
8
8
|
# View context for views in Hanami apps.
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# @api private
|
10
|
+
# @api public
|
11
|
+
# @since 2.1.0
|
13
12
|
module Context
|
14
13
|
class << self
|
15
14
|
# Returns a context class for the given slice. If a context class is not defined, defines
|
16
15
|
# a class named `Views::Context` within the slice's namespace.
|
17
16
|
#
|
18
17
|
# @api private
|
18
|
+
# @since 2.1.0
|
19
19
|
def context_class(slice)
|
20
20
|
views_namespace = views_namespace(slice)
|
21
21
|
|
@@ -30,6 +30,8 @@ module Hanami
|
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
+
# @api private
|
34
|
+
# @since 2.1.0
|
33
35
|
def context_superclass(slice)
|
34
36
|
return Hanami::View::Context if Hanami.app.equal?(slice)
|
35
37
|
|
@@ -44,8 +46,10 @@ module Hanami
|
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
|
-
#
|
49
|
+
# @api private
|
50
|
+
# @since 2.1.0
|
48
51
|
def views_namespace(slice)
|
52
|
+
# TODO: this could be moved into the top-level Extensions::View
|
49
53
|
if slice.namespace.const_defined?(:Views)
|
50
54
|
slice.namespace.const_get(:Views)
|
51
55
|
else
|
@@ -54,6 +58,8 @@ module Hanami
|
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
61
|
+
# @api private
|
62
|
+
# @since 2.1.0
|
57
63
|
module ClassExtension
|
58
64
|
def self.included(context_class)
|
59
65
|
super
|
@@ -63,18 +69,39 @@ module Hanami
|
|
63
69
|
context_class.prepend(InstanceMethods)
|
64
70
|
end
|
65
71
|
|
72
|
+
# @api private
|
73
|
+
# @since 2.1.0
|
66
74
|
module ClassMethods
|
75
|
+
# @api private
|
76
|
+
# @since 2.1.0
|
67
77
|
def configure_for_slice(slice)
|
68
78
|
extend SliceConfiguredContext.new(slice)
|
69
79
|
end
|
70
80
|
end
|
71
81
|
|
82
|
+
# @api public
|
83
|
+
# @since 2.1.0
|
72
84
|
module InstanceMethods
|
85
|
+
# Returns the app's inflector.
|
86
|
+
#
|
87
|
+
# @return [Dry::Inflector] the inflector
|
88
|
+
#
|
89
|
+
# @api public
|
90
|
+
# @since 2.1.0
|
73
91
|
attr_reader :inflector
|
74
92
|
|
93
|
+
# Returns the app's settings.
|
94
|
+
#
|
95
|
+
# @return [Hanami::Settings] the settings
|
96
|
+
#
|
97
|
+
# @api public
|
98
|
+
# @since 2.1.0
|
75
99
|
attr_reader :settings
|
76
100
|
|
77
101
|
# @see SliceConfiguredContext#define_new
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
# @since 2.1.0
|
78
105
|
def initialize( # rubocop:disable Metrics/ParameterLists
|
79
106
|
inflector: nil,
|
80
107
|
settings: nil,
|
@@ -94,6 +121,8 @@ module Hanami
|
|
94
121
|
super(**args)
|
95
122
|
end
|
96
123
|
|
124
|
+
# @api private
|
125
|
+
# @since 2.1.0
|
97
126
|
def initialize_copy(source)
|
98
127
|
# The standard implementation of initialize_copy will make shallow copies of all
|
99
128
|
# instance variables from the source. This is fine for most of our ivars.
|
@@ -104,17 +133,14 @@ module Hanami
|
|
104
133
|
@content_for = source.instance_variable_get(:@content_for).dup
|
105
134
|
end
|
106
135
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
)
|
116
|
-
end
|
117
|
-
|
136
|
+
# Returns the app's assets.
|
137
|
+
#
|
138
|
+
# @return [Hanami::Assets] the assets
|
139
|
+
#
|
140
|
+
# @raise [Hanami::ComponentLoadError] if the hanami-assets gem is not bundled
|
141
|
+
#
|
142
|
+
# @api public
|
143
|
+
# @since 2.1.0
|
118
144
|
def assets
|
119
145
|
unless @assets
|
120
146
|
raise Hanami::ComponentLoadError, "the hanami-assets gem is required to access assets"
|
@@ -123,6 +149,14 @@ module Hanami
|
|
123
149
|
@assets
|
124
150
|
end
|
125
151
|
|
152
|
+
# Returns the current request, if the view is rendered from within an action.
|
153
|
+
#
|
154
|
+
# @return [Hanami::Action::Request] the request
|
155
|
+
#
|
156
|
+
# @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
|
157
|
+
#
|
158
|
+
# @api public
|
159
|
+
# @since 2.1.0
|
126
160
|
def request
|
127
161
|
unless @request
|
128
162
|
raise Hanami::ComponentLoadError, "only views rendered from Hanami::Action instances have a request"
|
@@ -131,6 +165,15 @@ module Hanami
|
|
131
165
|
@request
|
132
166
|
end
|
133
167
|
|
168
|
+
# Returns the app's routes helper.
|
169
|
+
#
|
170
|
+
# @return [Hanami::Slice::RoutesHelper] the routes helper
|
171
|
+
#
|
172
|
+
# @raise [Hanami::ComponentLoadError] if the hanami-router gem is not bundled or routes
|
173
|
+
# are not defined
|
174
|
+
#
|
175
|
+
# @api public
|
176
|
+
# @since 2.1.0
|
134
177
|
def routes
|
135
178
|
unless @routes
|
136
179
|
raise Hanami::ComponentLoadError, "the hanami-router gem is required to access routes"
|
@@ -139,6 +182,32 @@ module Hanami
|
|
139
182
|
@routes
|
140
183
|
end
|
141
184
|
|
185
|
+
# @overload content_for(key, value = nil, &block)
|
186
|
+
# Stores a string or block of template markup for later use.
|
187
|
+
#
|
188
|
+
# @param key [Symbol] the content key, for later retrieval
|
189
|
+
# @param value [String, nil] the content, if no block is given
|
190
|
+
#
|
191
|
+
# @return [String] the content
|
192
|
+
#
|
193
|
+
# @example
|
194
|
+
# content_for(:page_title, "Hello world")
|
195
|
+
#
|
196
|
+
# @example In a template
|
197
|
+
# <% content_for :page_title do %>
|
198
|
+
# <h1>Hello world</h1>
|
199
|
+
# <% end %>
|
200
|
+
#
|
201
|
+
# @overload content_for(key)
|
202
|
+
# Returns the previously stored content for the given key.
|
203
|
+
#
|
204
|
+
# @param key [Symbol] the content key
|
205
|
+
#
|
206
|
+
# @return [String, nil] the content, or nil if no content previously stored with the
|
207
|
+
# key
|
208
|
+
#
|
209
|
+
# @api public
|
210
|
+
# @since 2.1.0
|
142
211
|
def content_for(key, value = nil)
|
143
212
|
if block_given?
|
144
213
|
@content_for[key] = yield
|
@@ -149,18 +218,41 @@ module Hanami
|
|
149
218
|
end
|
150
219
|
end
|
151
220
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
221
|
+
# Returns the current request's CSRF token.
|
222
|
+
#
|
223
|
+
# @return [String] the token
|
224
|
+
#
|
225
|
+
# @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
|
226
|
+
# @raise [Hanami::Action::MissingSessionError] if sessions are not enabled
|
227
|
+
#
|
228
|
+
# @api public
|
229
|
+
# @since 2.1.0
|
156
230
|
def csrf_token
|
157
231
|
request.session[Hanami::Action::CSRFProtection::CSRF_TOKEN]
|
158
232
|
end
|
159
233
|
|
234
|
+
# Returns the session for the current request.
|
235
|
+
#
|
236
|
+
# @return [Rack::Session::Abstract::SessionHash] the session hash
|
237
|
+
#
|
238
|
+
# @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
|
239
|
+
# @raise [Hanami::Action::MissingSessionError] if sessions are not enabled
|
240
|
+
#
|
241
|
+
# @api public
|
242
|
+
# @since 2.1.0
|
160
243
|
def session
|
161
244
|
request.session
|
162
245
|
end
|
163
246
|
|
247
|
+
# Returns the flash hash for the current request.
|
248
|
+
#
|
249
|
+
# @return []
|
250
|
+
#
|
251
|
+
# @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
|
252
|
+
# @raise [Hanami::Action::MissingSessionError] if sessions are not enabled
|
253
|
+
#
|
254
|
+
# @api public
|
255
|
+
# @since 2.1.0
|
164
256
|
def flash
|
165
257
|
request.flash
|
166
258
|
end
|
@@ -3,21 +3,82 @@
|
|
3
3
|
module Hanami
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
|
-
# @api
|
6
|
+
# @api public
|
7
|
+
# @since 2.1.0
|
7
8
|
module Part
|
9
|
+
# @api private
|
10
|
+
# @since 2.1.0
|
8
11
|
def self.included(part_class)
|
9
12
|
super
|
10
13
|
|
11
14
|
part_class.extend(Hanami::SliceConfigurable)
|
12
|
-
part_class.include(StandardHelpers)
|
13
15
|
part_class.extend(ClassMethods)
|
14
16
|
end
|
15
17
|
|
18
|
+
# @api private
|
19
|
+
# @since 2.1.0
|
16
20
|
module ClassMethods
|
21
|
+
# @api private
|
22
|
+
# @since 2.1.0
|
17
23
|
def configure_for_slice(slice)
|
18
|
-
extend
|
24
|
+
extend SliceConfiguredPart.new(slice)
|
25
|
+
|
26
|
+
const_set :PartHelpers, Class.new(PartHelpers) { |klass|
|
27
|
+
klass.configure_for_slice(slice)
|
28
|
+
}
|
19
29
|
end
|
20
30
|
end
|
31
|
+
|
32
|
+
# Returns an object including the default Hanami helpers as well as the user-defined helpers
|
33
|
+
# for the part's slice.
|
34
|
+
#
|
35
|
+
# Use this when you need to access helpers inside your part classes.
|
36
|
+
#
|
37
|
+
# @return [Object] the helpers object
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
# @since 2.1.0
|
41
|
+
def helpers
|
42
|
+
@helpers ||= self.class.const_get(:PartHelpers).new(context: _context)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Standalone helpers class including both {StandardHelpers} as well as the user-defined
|
47
|
+
# helpers for the slice.
|
48
|
+
#
|
49
|
+
# Used used where helpers should be addressed via an intermediary object (i.e. in parts),
|
50
|
+
# rather than mixed into a class directly.
|
51
|
+
#
|
52
|
+
# @api private
|
53
|
+
# @since 2.1.0
|
54
|
+
class PartHelpers
|
55
|
+
extend Hanami::SliceConfigurable
|
56
|
+
|
57
|
+
include StandardHelpers
|
58
|
+
|
59
|
+
# @api private
|
60
|
+
# @since 2.1.0
|
61
|
+
def self.configure_for_slice(slice)
|
62
|
+
extend SliceConfiguredHelpers.new(slice)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the context for the current view rendering.
|
66
|
+
#
|
67
|
+
# @return [Hanami::View::Context] the context
|
68
|
+
#
|
69
|
+
# @api public
|
70
|
+
# @since 2.1.0
|
71
|
+
attr_reader :_context
|
72
|
+
|
73
|
+
# @api public
|
74
|
+
# @since 2.1.0
|
75
|
+
alias_method :context, :_context
|
76
|
+
|
77
|
+
# @api private
|
78
|
+
# @since 2.1.0
|
79
|
+
def initialize(context:)
|
80
|
+
@_context = context
|
81
|
+
end
|
21
82
|
end
|
22
83
|
end
|
23
84
|
end
|
@@ -4,7 +4,10 @@ module Hanami
|
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
6
|
# @api private
|
7
|
+
# @since 2.1.0
|
7
8
|
module Scope
|
9
|
+
# @api private
|
10
|
+
# @since 2.1.0
|
8
11
|
def self.included(scope_class)
|
9
12
|
super
|
10
13
|
|
@@ -13,7 +16,11 @@ module Hanami
|
|
13
16
|
scope_class.extend(ClassMethods)
|
14
17
|
end
|
15
18
|
|
19
|
+
# @api private
|
20
|
+
# @since 2.1.0
|
16
21
|
module ClassMethods
|
22
|
+
# @api private
|
23
|
+
# @since 2.1.0
|
17
24
|
def configure_for_slice(slice)
|
18
25
|
extend SliceConfiguredHelpers.new(slice)
|
19
26
|
end
|
@@ -3,35 +3,39 @@
|
|
3
3
|
module Hanami
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
|
-
# Provides slice-specific configuration and behavior for any view context class
|
7
|
-
#
|
6
|
+
# Provides slice-specific configuration and behavior for any view context class defined within
|
7
|
+
# a slice's module namespace.
|
8
8
|
#
|
9
|
-
# @api
|
10
|
-
# @since 2.
|
9
|
+
# @api public
|
10
|
+
# @since 2.1.0
|
11
11
|
class SliceConfiguredContext < Module
|
12
12
|
attr_reader :slice
|
13
13
|
|
14
|
+
# @api private
|
15
|
+
# @since 2.1.0
|
14
16
|
def initialize(slice)
|
15
17
|
super()
|
16
18
|
@slice = slice
|
17
19
|
end
|
18
20
|
|
21
|
+
# @api private
|
22
|
+
# @since 2.1.0
|
19
23
|
def extended(_context_class)
|
20
24
|
define_new
|
21
25
|
end
|
22
26
|
|
27
|
+
# @api public
|
28
|
+
# @since 2.1.0
|
23
29
|
def inspect
|
24
30
|
"#<#{self.class.name}[#{slice.name}]>"
|
25
31
|
end
|
26
32
|
|
27
33
|
private
|
28
34
|
|
29
|
-
# Defines a {.new} method on the context class that resolves key components from
|
30
|
-
#
|
31
|
-
# dependencies.
|
35
|
+
# Defines a {.new} method on the context class that resolves key components from the app
|
36
|
+
# container and provides them to {#initialize} as injected dependencies.
|
32
37
|
#
|
33
38
|
# This includes the following app components:
|
34
|
-
#
|
35
39
|
# - the configured inflector as `inflector`
|
36
40
|
# - "settings" from the app container as `settings`
|
37
41
|
# - "routes" from the app container as `routes`
|