hanami 2.0.3 → 2.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/LICENSE.md +1 -1
- data/README.md +25 -9
- data/hanami.gemspec +2 -2
- data/lib/hanami/config/actions.rb +0 -4
- data/lib/hanami/config/views.rb +0 -4
- data/lib/hanami/config.rb +54 -0
- data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
- data/lib/hanami/extensions/action.rb +4 -4
- data/lib/hanami/extensions/router/errors.rb +58 -0
- data/lib/hanami/extensions/view/context.rb +129 -60
- data/lib/hanami/extensions/view/part.rb +26 -0
- data/lib/hanami/extensions/view/scope.rb +26 -0
- data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
- data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
- data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
- data/lib/hanami/extensions/view/standard_helpers.rb +14 -0
- data/lib/hanami/extensions.rb +10 -3
- data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
- data/lib/hanami/helpers/form_helper/values.rb +75 -0
- data/lib/hanami/helpers/form_helper.rb +213 -0
- data/lib/hanami/middleware/public_errors_app.rb +75 -0
- data/lib/hanami/middleware/render_errors.rb +93 -0
- data/lib/hanami/slice.rb +27 -2
- data/lib/hanami/slice_configurable.rb +3 -2
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +1 -1
- data/lib/hanami.rb +1 -1
- data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
- data/spec/integration/action/view_rendering_spec.rb +0 -18
- data/spec/integration/rack_app/middleware_spec.rb +23 -23
- data/spec/integration/rack_app/rack_app_spec.rb +5 -1
- data/spec/integration/view/config/default_context_spec.rb +149 -0
- data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
- data/spec/integration/view/config/part_class_spec.rb +147 -0
- data/spec/integration/view/config/part_namespace_spec.rb +103 -0
- data/spec/integration/view/config/paths_spec.rb +119 -0
- data/spec/integration/view/config/scope_class_spec.rb +147 -0
- data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
- data/spec/integration/view/config/template_spec.rb +38 -0
- data/spec/integration/view/context/request_spec.rb +3 -7
- data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
- data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
- data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
- data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
- data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
- data/spec/integration/view/slice_configuration_spec.rb +9 -9
- data/spec/integration/web/render_detailed_errors_spec.rb +90 -0
- data/spec/integration/web/render_errors_spec.rb +240 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/matchers.rb +32 -0
- data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -4
- data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
- data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
- data/spec/unit/hanami/config/views_spec.rb +0 -18
- data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
- data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
- data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
- data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
- data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
- data/spec/unit/hanami/version_spec.rb +1 -1
- data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
- metadata +65 -33
- data/spec/integration/action/view_integration_spec.rb +0 -165
- data/spec/integration/view/part_namespace_spec.rb +0 -96
- data/spec/integration/view/path_spec.rb +0 -56
- data/spec/integration/view/template_spec.rb +0 -68
- data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
- data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
- data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
- data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
- data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
- data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
- data/spec/isolation/hanami/boot/success_spec.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b7770e05814c2c09affa6bb627a563f56f64601e2587c474f5139c42a17d25c
|
4
|
+
data.tar.gz: 67e7f5b426b6e50023f5c3baad3b91d422b1c82dcc25213f4d6fe4efab0ff681
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eeb3695b89718d12ca4d6376b997af52a21fe39e39e8b8e2e932422d291314a9b8bc1f11ade96279737847283234a783039e8e7e0364fc488def2ab18f8efaf5
|
7
|
+
data.tar.gz: 63cf7e291a0b6789eb16430ce0c1945ce945787fab250c8e804869276428045404d0f98205fdf481c9a80e48cf89b38a243bff00b52a900349fcffef5cc62254
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
The web, with simplicity.
|
4
4
|
|
5
|
+
## v2.1.0.beta1 - 2023-06-29
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- [Tim Riley] Introduce `Hanami::View` extensions to use alongside hanami-view v2.1.0.beta1 (#1292)
|
10
|
+
- [Tim Riley] Enable standard helpers (from hanami-view) for all view parts and scopes (#1303,
|
11
|
+
#1307)
|
12
|
+
- [Tim Riley] Add `Hanami::Helpers::FormHelper` and include in all view parts and scopes (#1305,
|
13
|
+
#1307)
|
14
|
+
- [Tim Riley] Include user defined helpers (at `MyApp::Views::Helpers` or `MySlice::Views::Helpers`)
|
15
|
+
in all view parts and scopes (#1307)
|
16
|
+
- [Tim Riley] Introduce `Hanami::Middleware::RenderErrors` middleware to render error responses (in HTML or JSON) when errors are raised. For HTML responses, the error pages are expected to be found in `public/{404,500}.html` (#1309)
|
17
|
+
- [Tim Riley] Use hanami-webconsole (if bundled) to render detailed error pages in development mode (#1311).
|
18
|
+
|
19
|
+
### Fixed
|
20
|
+
|
21
|
+
- [Tim Riley] Prevent matching incorrect slice names (due to partial matches) in `Hanami::SliceConfigurable`. This ensures appropriate config is applied to actions and views within their respective slices. (#1302)
|
22
|
+
- [Masanori Ohnishi] Ensure content-length properly appears in rack logs (#1306)
|
23
|
+
|
5
24
|
## v2.0.3 - 2023-02-01
|
6
25
|
|
7
26
|
### Added
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -82,26 +82,42 @@ We strive for an inclusive and helpful community. We have a [Code of Conduct](ht
|
|
82
82
|
|
83
83
|
In addition to contributing code, you can help to triage issues. This can include reproducing bug reports, or asking for vital information such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to hanami on CodeTriage](https://www.codetriage.com/hanami/hanami).
|
84
84
|
|
85
|
-
###
|
85
|
+
### Tests
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
To run all test suite:
|
88
|
+
|
89
|
+
```shell
|
90
|
+
$ bundle exec rake
|
91
|
+
```
|
90
92
|
|
91
|
-
|
93
|
+
To run all the unit tests:
|
92
94
|
|
93
|
-
|
95
|
+
```shell
|
96
|
+
$ bundle exec rspec spec/unit
|
97
|
+
```
|
94
98
|
|
95
|
-
|
99
|
+
To run all the integration tests:
|
96
100
|
|
97
101
|
```shell
|
98
|
-
bundle exec rspec spec/
|
102
|
+
$ bundle exec rspec spec/integration
|
99
103
|
```
|
100
104
|
|
105
|
+
To run a single test:
|
106
|
+
|
107
|
+
```shell
|
108
|
+
$ bundle exec rspec path/to/spec.rb
|
109
|
+
```
|
110
|
+
|
111
|
+
### Development Requirements
|
112
|
+
|
113
|
+
* Ruby >= 3.0
|
114
|
+
* Bundler
|
115
|
+
* Node.js (MacOS)
|
116
|
+
|
101
117
|
## Versioning
|
102
118
|
|
103
119
|
__Hanami__ uses [Semantic Versioning 2.0.0](http://semver.org)
|
104
120
|
|
105
121
|
## Copyright
|
106
122
|
|
107
|
-
Copyright © 2014
|
123
|
+
Copyright © 2014 Hanami Team – Released under MIT License.
|
data/hanami.gemspec
CHANGED
@@ -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.
|
42
|
-
spec.add_dependency "hanami-utils", "~> 2.
|
41
|
+
spec.add_dependency "hanami-cli", "~> 2.1.beta"
|
42
|
+
spec.add_dependency "hanami-utils", "~> 2.1.beta"
|
43
43
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
44
44
|
|
45
45
|
spec.add_development_dependency "rspec", "~> 3.8"
|
@@ -82,10 +82,6 @@ module Hanami
|
|
82
82
|
# @api private
|
83
83
|
setting :name_inference_base, default: "actions"
|
84
84
|
|
85
|
-
# @!attribute [rw] view_context_identifier
|
86
|
-
# @api private
|
87
|
-
setting :view_context_identifier, default: "views.context"
|
88
|
-
|
89
85
|
# @!attribute [rw] view_name_inferrer
|
90
86
|
# @api private
|
91
87
|
setting :view_name_inferrer, default: Slice::ViewNameInferrer
|
data/lib/hanami/config/views.rb
CHANGED
@@ -13,8 +13,6 @@ module Hanami
|
|
13
13
|
class Views
|
14
14
|
include Dry::Configurable
|
15
15
|
|
16
|
-
setting :parts_path, default: "views/parts"
|
17
|
-
|
18
16
|
attr_reader :base_config
|
19
17
|
protected :base_config
|
20
18
|
|
@@ -46,8 +44,6 @@ module Hanami
|
|
46
44
|
private
|
47
45
|
|
48
46
|
def configure_defaults
|
49
|
-
self.paths = ["templates"]
|
50
|
-
self.template_inference_base = "views"
|
51
47
|
self.layout = "app"
|
52
48
|
end
|
53
49
|
|
data/lib/hanami/config.rb
CHANGED
@@ -127,6 +127,58 @@ module Hanami
|
|
127
127
|
# @since 2.0.0
|
128
128
|
setting :base_url, default: "http://0.0.0.0:2300", constructor: ->(url) { URI(url) }
|
129
129
|
|
130
|
+
# @!attribute [rw] render_errors
|
131
|
+
# Sets whether to catch exceptions and render error pages.
|
132
|
+
#
|
133
|
+
# For HTML responses, these error pages are in `public/{404,500}.html`.
|
134
|
+
#
|
135
|
+
# Defaults to `true` in production mode, `false` in all others.
|
136
|
+
#
|
137
|
+
# @return [Boolean]
|
138
|
+
#
|
139
|
+
# @api public
|
140
|
+
# @since 2.1.0
|
141
|
+
setting :render_errors, default: false
|
142
|
+
|
143
|
+
# @!attribute [rw] render_detailed_errors
|
144
|
+
# Sets whether to catch exceptions and render detailed, interactive error pages.
|
145
|
+
#
|
146
|
+
# Requires the hanami-webconsole gem to be available.
|
147
|
+
#
|
148
|
+
# Defaults to `false` in production mode, `true` in all others.
|
149
|
+
#
|
150
|
+
# @return [Boolean]
|
151
|
+
#
|
152
|
+
# @api public
|
153
|
+
# @since 2.1.0
|
154
|
+
setting :render_detailed_errors, default: false
|
155
|
+
|
156
|
+
# @!attribute [rw] render_error_responses
|
157
|
+
# Sets a mapping of exception class names (as strings) to symbolic response status codes used
|
158
|
+
# for rendering error responses.
|
159
|
+
#
|
160
|
+
# The response status codes will be passed to `Rack::Utils.status_code`.
|
161
|
+
#
|
162
|
+
# In ordinary usage, you should not replace this hash. Instead, add keys and values for the
|
163
|
+
# errors you want handled.
|
164
|
+
#
|
165
|
+
# @example
|
166
|
+
# config.render_error_responses
|
167
|
+
# # => {"Hanami::Router::NotFoundError" => :not_found}
|
168
|
+
#
|
169
|
+
# config.render_error_responses["MyNotFoundError"] = :not_found
|
170
|
+
#
|
171
|
+
# @return [Hash{String => Symbol}]
|
172
|
+
#
|
173
|
+
# @see #render_errors
|
174
|
+
#
|
175
|
+
# @api public
|
176
|
+
# @since 2.1.0
|
177
|
+
setting :render_error_responses, default: Hash.new(:internal_server_error).merge!(
|
178
|
+
"Hanami::Router::NotAllowedError" => :not_found,
|
179
|
+
"Hanami::Router::NotFoundError" => :not_found,
|
180
|
+
)
|
181
|
+
|
130
182
|
# Returns the app or slice's {Hanami::SliceName slice_name}.
|
131
183
|
#
|
132
184
|
# This is useful for default config values that depend on this name.
|
@@ -217,6 +269,8 @@ module Hanami
|
|
217
269
|
|
218
270
|
# Apply default values that are only knowable at initialize-time (vs require-time)
|
219
271
|
self.root = Dir.pwd
|
272
|
+
self.render_errors = (env == :production)
|
273
|
+
self.render_detailed_errors = (env != :production)
|
220
274
|
load_from_env
|
221
275
|
|
222
276
|
@logger = Config::Logger.new(env: env, app_name: app_name)
|
@@ -121,18 +121,26 @@ module Hanami
|
|
121
121
|
slice: slice,
|
122
122
|
)
|
123
123
|
|
124
|
-
view_identifiers.
|
125
|
-
|
124
|
+
view_identifiers.each do |identifier|
|
125
|
+
return slice[identifier] if slice.key?(identifier)
|
126
126
|
end
|
127
|
+
|
128
|
+
nil
|
127
129
|
end
|
128
130
|
|
129
131
|
def resolve_view_context
|
130
|
-
|
132
|
+
if Hanami.bundled?("hanami-view")
|
133
|
+
return Extensions::View::Context.context_class(slice).new
|
134
|
+
end
|
135
|
+
|
136
|
+
# If hanami-view isn't bundled, try and find a possible third party context class with the
|
137
|
+
# same `Views::Context` name (but don't fall back to automatically defining one).
|
138
|
+
if slice.namespace.const_defined?(:Views)
|
139
|
+
views_namespace = slice.namespace.const_get(:Views)
|
131
140
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
slice.app[identifier]
|
141
|
+
if views_namespace.const_defined?(:Context)
|
142
|
+
views_namespace.const_get(:Context).new
|
143
|
+
end
|
136
144
|
end
|
137
145
|
end
|
138
146
|
|
@@ -101,13 +101,13 @@ module Hanami
|
|
101
101
|
end
|
102
102
|
|
103
103
|
# @api private
|
104
|
-
def view_options(
|
105
|
-
{context: view_context&.with(**view_context_options(
|
104
|
+
def view_options(request, response)
|
105
|
+
{context: view_context&.with(**view_context_options(request, response))}.compact
|
106
106
|
end
|
107
107
|
|
108
108
|
# @api private
|
109
|
-
def view_context_options(
|
110
|
-
{request:
|
109
|
+
def view_context_options(request, response) # rubocop:disable Lint:UnusedMethodArgument
|
110
|
+
{request: request}
|
111
111
|
end
|
112
112
|
|
113
113
|
# Returns true if a view should automatically be rendered onto the response body.
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hanami/router"
|
4
|
+
|
5
|
+
module Hanami
|
6
|
+
class Router
|
7
|
+
# Error raised when a request is made for a missing route.
|
8
|
+
#
|
9
|
+
# Raised only when using hanami-router as part of a full Hanami app. When using hanami-router
|
10
|
+
# standalone, the behavior for such requests is to return a "Not Found" response.
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
# @since 2.1.0
|
14
|
+
class NotFoundError < Hanami::Router::Error
|
15
|
+
# @return [Hash] the Rack environment for the request
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
# @since 2.1.0
|
19
|
+
attr_reader :env
|
20
|
+
|
21
|
+
def initialize(env)
|
22
|
+
@env = env
|
23
|
+
|
24
|
+
message = "No route found for #{env["REQUEST_METHOD"]} #{env["PATH_INFO"]}"
|
25
|
+
super(message)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Error raised when a request is made for a route using a HTTP method not allowed on the route.
|
30
|
+
#
|
31
|
+
# Raised only when using hanami-router as part of a full Hanami app. When using hanami-router
|
32
|
+
# standalone, the behavior for such requests is to return a "Method Not Allowed" response.
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
# @since 2.1.0
|
36
|
+
class NotAllowedError < Hanami::Router::Error
|
37
|
+
# @return [Hash] the Rack environment for the request
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
# @since 2.1.0
|
41
|
+
attr_reader :env
|
42
|
+
|
43
|
+
# @return [Array<String>] the allowed methods for the route
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
# @since 2.1.0
|
47
|
+
attr_reader :allowed_methods
|
48
|
+
|
49
|
+
def initialize(env, allowed_methods)
|
50
|
+
@env = env
|
51
|
+
@allowed_methods = allowed_methods
|
52
|
+
|
53
|
+
message = "Only #{allowed_methods.join(', ')} requests are allowed at #{env["PATH_INFO"]}"
|
54
|
+
super(message)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "hanami/view"
|
4
|
-
require "hanami/view/context"
|
5
3
|
require_relative "../../errors"
|
6
4
|
|
7
5
|
module Hanami
|
@@ -13,88 +11,159 @@ module Hanami
|
|
13
11
|
#
|
14
12
|
# @api private
|
15
13
|
module Context
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
context_class
|
22
|
-
|
14
|
+
class << self
|
15
|
+
# Returns a context class for the given slice. If a context class is not defined, defines
|
16
|
+
# a class named `Views::Context` within the slice's namespace.
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
def context_class(slice)
|
20
|
+
views_namespace = views_namespace(slice)
|
21
|
+
|
22
|
+
if views_namespace.const_defined?(:Context)
|
23
|
+
return views_namespace.const_get(:Context)
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
views_namespace.const_set(:Context, Class.new(context_superclass(slice)).tap { |klass|
|
27
|
+
klass.configure_for_slice(slice)
|
28
|
+
})
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
# @see SliceConfiguredContext#define_new
|
32
|
-
def initialize(**kwargs)
|
33
|
-
defaults = {content: {}}
|
31
|
+
private
|
34
32
|
|
35
|
-
|
33
|
+
def context_superclass(slice)
|
34
|
+
return Hanami::View::Context if Hanami.app.equal?(slice)
|
35
|
+
|
36
|
+
begin
|
37
|
+
slice.inflector.constantize(
|
38
|
+
slice.inflector.camelize("#{slice.app.slice_name.name}/views/context")
|
39
|
+
)
|
40
|
+
rescue NameError => e
|
41
|
+
raise e unless %i[Views Context].include?(e.name)
|
42
|
+
|
43
|
+
Hanami::View::Context
|
44
|
+
end
|
36
45
|
end
|
37
46
|
|
38
|
-
|
39
|
-
|
47
|
+
# TODO: this could be moved into the top-level Extensions::View
|
48
|
+
def views_namespace(slice)
|
49
|
+
if slice.namespace.const_defined?(:Views)
|
50
|
+
slice.namespace.const_get(:Views)
|
51
|
+
else
|
52
|
+
slice.namespace.const_set(:Views, Module.new)
|
53
|
+
end
|
40
54
|
end
|
55
|
+
end
|
41
56
|
|
42
|
-
|
43
|
-
|
57
|
+
module ClassExtension
|
58
|
+
def self.included(context_class)
|
59
|
+
super
|
60
|
+
|
61
|
+
context_class.extend(Hanami::SliceConfigurable)
|
62
|
+
context_class.extend(ClassMethods)
|
63
|
+
context_class.prepend(InstanceMethods)
|
44
64
|
end
|
45
65
|
|
46
|
-
|
47
|
-
|
66
|
+
module ClassMethods
|
67
|
+
def configure_for_slice(slice)
|
68
|
+
extend SliceConfiguredContext.new(slice)
|
69
|
+
end
|
48
70
|
end
|
49
71
|
|
50
|
-
|
51
|
-
|
52
|
-
|
72
|
+
module InstanceMethods
|
73
|
+
attr_reader :inflector
|
74
|
+
|
75
|
+
attr_reader :settings
|
76
|
+
|
77
|
+
# @see SliceConfiguredContext#define_new
|
78
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
79
|
+
inflector: nil,
|
80
|
+
settings: nil,
|
81
|
+
routes: nil,
|
82
|
+
assets: nil,
|
83
|
+
request: nil,
|
84
|
+
**args
|
85
|
+
)
|
86
|
+
@inflector = inflector
|
87
|
+
@settings = settings
|
88
|
+
@routes = routes
|
89
|
+
@assets = assets
|
90
|
+
@request = request
|
91
|
+
|
92
|
+
@content_for = {}
|
93
|
+
|
94
|
+
super(**args)
|
53
95
|
end
|
54
96
|
|
55
|
-
|
56
|
-
|
97
|
+
def initialize_copy(source)
|
98
|
+
# The standard implementation of initialize_copy will make shallow copies of all
|
99
|
+
# instance variables from the source. This is fine for most of our ivars.
|
100
|
+
super
|
57
101
|
|
58
|
-
|
59
|
-
|
60
|
-
|
102
|
+
# Dup any objects that will be mutated over a given rendering to ensure no leakage of
|
103
|
+
# state across distinct view renderings.
|
104
|
+
@content_for = source.instance_variable_get(:@content_for).dup
|
105
|
+
end
|
61
106
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
107
|
+
def with(**args)
|
108
|
+
self.class.new(
|
109
|
+
inflector: @inflector,
|
110
|
+
settings: @settings,
|
111
|
+
assets: @assets,
|
112
|
+
routes: @routes,
|
113
|
+
request: @request,
|
114
|
+
**args
|
115
|
+
)
|
68
116
|
end
|
69
117
|
|
70
|
-
|
71
|
-
|
118
|
+
def assets
|
119
|
+
unless @assets
|
120
|
+
raise Hanami::ComponentLoadError, "the hanami-assets gem is required to access assets"
|
121
|
+
end
|
72
122
|
|
73
|
-
|
74
|
-
|
75
|
-
end
|
123
|
+
@assets
|
124
|
+
end
|
76
125
|
|
77
|
-
|
78
|
-
|
79
|
-
|
126
|
+
def request
|
127
|
+
unless @request
|
128
|
+
raise Hanami::ComponentLoadError, "only views rendered from Hanami::Action instances have a request"
|
129
|
+
end
|
80
130
|
|
81
|
-
|
82
|
-
|
83
|
-
end
|
131
|
+
@request
|
132
|
+
end
|
84
133
|
|
85
|
-
|
86
|
-
|
87
|
-
|
134
|
+
def routes
|
135
|
+
unless @routes
|
136
|
+
raise Hanami::ComponentLoadError, "the hanami-router gem is required to access routes"
|
137
|
+
end
|
88
138
|
|
89
|
-
|
90
|
-
|
91
|
-
end
|
139
|
+
@routes
|
140
|
+
end
|
92
141
|
|
93
|
-
|
142
|
+
def content_for(key, value = nil)
|
143
|
+
if block_given?
|
144
|
+
@content_for[key] = yield
|
145
|
+
elsif value
|
146
|
+
@content_for[key] = value
|
147
|
+
else
|
148
|
+
@content_for[key]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def current_path
|
153
|
+
request.fullpath
|
154
|
+
end
|
155
|
+
|
156
|
+
def csrf_token
|
157
|
+
request.session[Hanami::Action::CSRFProtection::CSRF_TOKEN]
|
158
|
+
end
|
159
|
+
|
160
|
+
def session
|
161
|
+
request.session
|
162
|
+
end
|
94
163
|
|
95
|
-
|
96
|
-
|
97
|
-
|
164
|
+
def flash
|
165
|
+
request.flash
|
166
|
+
end
|
98
167
|
end
|
99
168
|
end
|
100
169
|
end
|
@@ -102,4 +171,4 @@ module Hanami
|
|
102
171
|
end
|
103
172
|
end
|
104
173
|
|
105
|
-
Hanami::View::Context.include(Hanami::Extensions::View::Context)
|
174
|
+
Hanami::View::Context.include(Hanami::Extensions::View::Context::ClassExtension)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Extensions
|
5
|
+
module View
|
6
|
+
# @api private
|
7
|
+
module Part
|
8
|
+
def self.included(part_class)
|
9
|
+
super
|
10
|
+
|
11
|
+
part_class.extend(Hanami::SliceConfigurable)
|
12
|
+
part_class.include(StandardHelpers)
|
13
|
+
part_class.extend(ClassMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def configure_for_slice(slice)
|
18
|
+
extend SliceConfiguredHelpers.new(slice)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Hanami::View::Part.include(Hanami::Extensions::View::Part)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Extensions
|
5
|
+
module View
|
6
|
+
# @api private
|
7
|
+
module Scope
|
8
|
+
def self.included(scope_class)
|
9
|
+
super
|
10
|
+
|
11
|
+
scope_class.extend(Hanami::SliceConfigurable)
|
12
|
+
scope_class.include(StandardHelpers)
|
13
|
+
scope_class.extend(ClassMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def configure_for_slice(slice)
|
18
|
+
extend SliceConfiguredHelpers.new(slice)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Hanami::View::Scope.include(Hanami::Extensions::View::Scope)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Extensions
|
5
|
+
module View
|
6
|
+
# @api private
|
7
|
+
class SliceConfiguredHelpers < Module
|
8
|
+
attr_reader :slice
|
9
|
+
|
10
|
+
def initialize(slice)
|
11
|
+
super()
|
12
|
+
@slice = slice
|
13
|
+
end
|
14
|
+
|
15
|
+
def extended(klass)
|
16
|
+
include_helpers(klass)
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#<#{self.class.name}[#{slice.name}]>"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def include_helpers(klass)
|
26
|
+
if mod = helpers_module(slice.app)
|
27
|
+
klass.include(mod)
|
28
|
+
end
|
29
|
+
|
30
|
+
if mod = helpers_module(slice)
|
31
|
+
klass.include(mod)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def helpers_module(slice)
|
36
|
+
return unless slice.namespace.const_defined?(:Views)
|
37
|
+
return unless slice.namespace.const_get(:Views).const_defined?(:Helpers)
|
38
|
+
|
39
|
+
slice.namespace.const_get(:Views).const_get(:Helpers)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|