hanami-controller 2.0.0.beta4 → 2.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +3 -3
- data/hanami-controller.gemspec +2 -2
- data/lib/hanami/action/base_params.rb +39 -16
- data/lib/hanami/action/config.rb +8 -2
- data/lib/hanami/action/constants.rb +0 -6
- data/lib/hanami/action/csrf_protection.rb +1 -7
- data/lib/hanami/action/{error.rb → errors.rb} +31 -3
- data/lib/hanami/action/flash.rb +29 -22
- data/lib/hanami/action/halt.rb +3 -1
- data/lib/hanami/action/mime.rb +16 -4
- data/lib/hanami/action/rack/file.rb +6 -2
- data/lib/hanami/action/request.rb +46 -3
- data/lib/hanami/action/response.rb +203 -10
- data/lib/hanami/action/session.rb +7 -2
- data/lib/hanami/action/validatable.rb +9 -5
- data/lib/hanami/action.rb +78 -88
- data/lib/hanami/controller/version.rb +2 -4
- data/lib/hanami/controller.rb +0 -16
- data/lib/hanami/http/status.rb +2 -0
- metadata +12 -13
- data/lib/hanami/controller/error.rb +0 -9
@@ -8,9 +8,18 @@ require "hanami/action/cookie_jar"
|
|
8
8
|
require "hanami/action/cache/cache_control"
|
9
9
|
require "hanami/action/cache/expires"
|
10
10
|
require "hanami/action/cache/conditional_get"
|
11
|
+
require_relative "errors"
|
11
12
|
|
12
13
|
module Hanami
|
13
14
|
class Action
|
15
|
+
# The HTTP response for an action, given to {Action#handle}.
|
16
|
+
#
|
17
|
+
# Inherits from `Rack::Response`, providing compatibility with Rack functionality.
|
18
|
+
#
|
19
|
+
# @see http://www.rubydoc.info/gems/rack/Rack/Response
|
20
|
+
#
|
21
|
+
# @since 2.0.0
|
22
|
+
# @api private
|
14
23
|
class Response < ::Rack::Response
|
15
24
|
# @since 2.0.0
|
16
25
|
# @api private
|
@@ -26,7 +35,7 @@ module Hanami
|
|
26
35
|
|
27
36
|
# @since 2.0.0
|
28
37
|
# @api private
|
29
|
-
attr_reader :request, :exposures, :
|
38
|
+
attr_reader :request, :exposures, :env, :view_options
|
30
39
|
|
31
40
|
# @since 2.0.0
|
32
41
|
# @api private
|
@@ -46,7 +55,7 @@ module Hanami
|
|
46
55
|
# @api private
|
47
56
|
def initialize(request:, config:, content_type: nil, env: {}, headers: {}, view_options: nil, sessions_enabled: false) # rubocop:disable Layout/LineLength, Metrics/ParameterLists
|
48
57
|
super([], 200, headers.dup)
|
49
|
-
|
58
|
+
self.content_type = content_type if content_type
|
50
59
|
|
51
60
|
@request = request
|
52
61
|
@config = config
|
@@ -59,6 +68,10 @@ module Hanami
|
|
59
68
|
@sending_file = false
|
60
69
|
end
|
61
70
|
|
71
|
+
# Sets the response body.
|
72
|
+
#
|
73
|
+
# @param str [String] the body string
|
74
|
+
#
|
62
75
|
# @since 2.0.0
|
63
76
|
# @api public
|
64
77
|
def body=(str)
|
@@ -73,32 +86,96 @@ module Hanami
|
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
76
|
-
#
|
77
|
-
#
|
89
|
+
# This is NOT RELEASED with 2.0.0
|
90
|
+
#
|
91
|
+
# @api private
|
78
92
|
def render(view, **options)
|
79
93
|
self.body = view.(**view_options.(request, self), **exposures.merge(options)).to_str
|
80
94
|
end
|
81
95
|
|
96
|
+
# Returns the format for the response.
|
97
|
+
#
|
98
|
+
# Returns nil if a format has not been assigned and also cannot be determined from the
|
99
|
+
# response's `#content_type`.
|
100
|
+
#
|
101
|
+
# @example
|
102
|
+
# response.format # => :json
|
103
|
+
#
|
104
|
+
# @return [Symbol, nil]
|
105
|
+
#
|
82
106
|
# @since 2.0.0
|
83
107
|
# @api public
|
84
|
-
def format
|
85
|
-
@format
|
86
|
-
content_type = Action::Mime.content_type_with_charset(content_type, charset)
|
87
|
-
set_header("Content-Type", content_type)
|
108
|
+
def format
|
109
|
+
@format ||= Mime.detect_format(content_type, @config)
|
88
110
|
end
|
89
111
|
|
112
|
+
# Sets the format and associated content type for the response.
|
113
|
+
#
|
114
|
+
# Either a format name (`:json`) or a content type string (`"application/json"`) may be given.
|
115
|
+
# In either case, the format or content type will be derived from the given value, and both
|
116
|
+
# will be set.
|
117
|
+
#
|
118
|
+
# @example Assigning via a format name symbol
|
119
|
+
# response.format = :json
|
120
|
+
# response.content_type # => "application/json"
|
121
|
+
# response.headers["Content-Type"] # => "application/json"
|
122
|
+
#
|
123
|
+
# @example Assigning via a content type string
|
124
|
+
# response.format = "application/json"
|
125
|
+
# response.format # => :json
|
126
|
+
# response.content_type # => "application/json"
|
127
|
+
#
|
128
|
+
# @param value [Symbol, String] the format name or content type
|
129
|
+
#
|
130
|
+
# @see Config#formats
|
131
|
+
#
|
132
|
+
# @since 2.0.0
|
133
|
+
# @api public
|
134
|
+
def format=(value)
|
135
|
+
format, content_type = Mime.detect_format_and_content_type(value, @config)
|
136
|
+
|
137
|
+
self.content_type = Mime.content_type_with_charset(content_type, charset)
|
138
|
+
|
139
|
+
@format = format
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns the exposure value for the given key.
|
143
|
+
#
|
144
|
+
# @param key [Object]
|
145
|
+
#
|
146
|
+
# @return [Object] the exposure value, if found
|
147
|
+
#
|
148
|
+
# @raise [KeyError] if the exposure was not found
|
149
|
+
#
|
90
150
|
# @since 2.0.0
|
91
151
|
# @api public
|
92
152
|
def [](key)
|
93
153
|
@exposures.fetch(key)
|
94
154
|
end
|
95
155
|
|
156
|
+
# Sets an exposure value for the given key.
|
157
|
+
#
|
158
|
+
# @param key [Object]
|
159
|
+
# @param value [Object]
|
160
|
+
#
|
161
|
+
# @return [Object] the value
|
162
|
+
#
|
96
163
|
# @since 2.0.0
|
97
164
|
# @api public
|
98
165
|
def []=(key, value)
|
99
166
|
@exposures[key] = value
|
100
167
|
end
|
101
168
|
|
169
|
+
# Returns the session for the response.
|
170
|
+
#
|
171
|
+
# This is the same session object as the {Request}.
|
172
|
+
#
|
173
|
+
# @return [Hash] the session object
|
174
|
+
#
|
175
|
+
# @raise [MissingSessionError] if sessions are not enabled
|
176
|
+
#
|
177
|
+
# @see Request#session
|
178
|
+
#
|
102
179
|
# @since 2.0.0
|
103
180
|
# @api public
|
104
181
|
def session
|
@@ -109,6 +186,16 @@ module Hanami
|
|
109
186
|
request.session
|
110
187
|
end
|
111
188
|
|
189
|
+
# Returns the flash for the request.
|
190
|
+
#
|
191
|
+
# This is the same flash object as the {Request}.
|
192
|
+
#
|
193
|
+
# @return [Flash]
|
194
|
+
#
|
195
|
+
# @raise [MissingSessionError] if sessions are not enabled
|
196
|
+
#
|
197
|
+
# @see Request#flash
|
198
|
+
#
|
112
199
|
# @since 2.0.0
|
113
200
|
# @api public
|
114
201
|
def flash
|
@@ -119,12 +206,21 @@ module Hanami
|
|
119
206
|
request.flash
|
120
207
|
end
|
121
208
|
|
209
|
+
# Returns the set of cookies to be included in the response.
|
210
|
+
#
|
211
|
+
# @return [CookieJar]
|
212
|
+
#
|
122
213
|
# @since 2.0.0
|
123
214
|
# @api public
|
124
215
|
def cookies
|
125
216
|
@cookies ||= CookieJar.new(env.dup, headers, @config.cookies)
|
126
217
|
end
|
127
218
|
|
219
|
+
# Sets the response to redirect to the given URL and halts further handling.
|
220
|
+
#
|
221
|
+
# @param url [String]
|
222
|
+
# @param status [Integer] the HTTP status to use for the redirect
|
223
|
+
#
|
128
224
|
# @since 2.0.0
|
129
225
|
# @api public
|
130
226
|
def redirect_to(url, status: 302)
|
@@ -134,6 +230,22 @@ module Hanami
|
|
134
230
|
Halt.call(status)
|
135
231
|
end
|
136
232
|
|
233
|
+
# Sends the file at the given path as the response, for any file within the configured
|
234
|
+
# `public_directory`.
|
235
|
+
#
|
236
|
+
# Handles the following aspects for file responses:
|
237
|
+
#
|
238
|
+
# - Setting `Content-Type` and `Content-Length` headers
|
239
|
+
# - File Not Found responses (returns a 404)
|
240
|
+
# - Conditional GET (via `If-Modified-Since` header)
|
241
|
+
# - Range requests (via `Range` header)
|
242
|
+
#
|
243
|
+
# @param path [String] the file path
|
244
|
+
#
|
245
|
+
# @return [void]
|
246
|
+
#
|
247
|
+
# @see Config#public_directory
|
248
|
+
#
|
137
249
|
# @since 2.0.0
|
138
250
|
# @api public
|
139
251
|
def send_file(path)
|
@@ -142,6 +254,14 @@ module Hanami
|
|
142
254
|
)
|
143
255
|
end
|
144
256
|
|
257
|
+
# Send the file at the given path as the response, for a file anywhere in the file system.
|
258
|
+
#
|
259
|
+
# @see #send_file
|
260
|
+
#
|
261
|
+
# @param path [String, Pathname] path to the file to be sent
|
262
|
+
#
|
263
|
+
# @return [void]
|
264
|
+
#
|
145
265
|
# @since 2.0.0
|
146
266
|
# @api public
|
147
267
|
def unsafe_send_file(path)
|
@@ -156,6 +276,37 @@ module Hanami
|
|
156
276
|
)
|
157
277
|
end
|
158
278
|
|
279
|
+
# Specifies the response freshness policy for HTTP caches using the `Cache-Control` header.
|
280
|
+
#
|
281
|
+
# Any number of non-value directives (`:public`, `:private`, `:no_cache`, `:no_store`,
|
282
|
+
# `:must_revalidate`, `:proxy_revalidate`) may be passed along with a Hash of value directives
|
283
|
+
# (`:max_age`, `:min_stale`, `:s_max_age`).
|
284
|
+
#
|
285
|
+
# See [RFC 2616 / 14.9](http://tools.ietf.org/html/rfc2616#section-14.9.1) for more on
|
286
|
+
# standard cache control directives.
|
287
|
+
#
|
288
|
+
# @example
|
289
|
+
# # Set Cache-Control directives
|
290
|
+
# response.cache_control :public, max_age: 900, s_maxage: 86400
|
291
|
+
#
|
292
|
+
# # Overwrite previous Cache-Control directives
|
293
|
+
# response.cache_control :private, :no_cache, :no_store
|
294
|
+
#
|
295
|
+
# response.get_header("Cache-Control") # => "private, no-store, max-age=900"
|
296
|
+
#
|
297
|
+
# @param values [Array<Symbol, Hash>] values to map to `Cache-Control` directives
|
298
|
+
# @option values [Symbol] :public
|
299
|
+
# @option values [Symbol] :private
|
300
|
+
# @option values [Symbol] :no_cache
|
301
|
+
# @option values [Symbol] :no_store
|
302
|
+
# @option values [Symbol] :must_validate
|
303
|
+
# @option values [Symbol] :proxy_revalidate
|
304
|
+
# @option values [Hash] :max_age
|
305
|
+
# @option values [Hash] :min_stale
|
306
|
+
# @option values [Hash] :s_max_age
|
307
|
+
#
|
308
|
+
# @return void
|
309
|
+
#
|
159
310
|
# @since 2.0.0
|
160
311
|
# @api public
|
161
312
|
def cache_control(*values)
|
@@ -163,6 +314,28 @@ module Hanami
|
|
163
314
|
headers.merge!(directives.headers)
|
164
315
|
end
|
165
316
|
|
317
|
+
# Sets the `Expires` header and `Cache-Control`/`max-age` directive for the response.
|
318
|
+
#
|
319
|
+
# You can provide an integer number of seconds in the future, or a Time object indicating when
|
320
|
+
# the response should be considered "stale". The remaining arguments are passed to
|
321
|
+
# {#cache_control}.
|
322
|
+
#
|
323
|
+
# @example
|
324
|
+
# # Set Cache-Control directives and Expires
|
325
|
+
# response.expires 900, :public
|
326
|
+
#
|
327
|
+
# # Overwrite Cache-Control directives and Expires
|
328
|
+
# response.expires 300, :private, :no_cache, :no_store
|
329
|
+
#
|
330
|
+
# response.get_header("Expires") # => "Thu, 26 Jun 2014 12:00:00 GMT"
|
331
|
+
# response.get_header("Cache-Control") # => "private, no-cache, no-store max-age=300"
|
332
|
+
#
|
333
|
+
# @param amount [Integer, Time] number of seconds or point in time
|
334
|
+
# @param values [Array<Symbols>] values to map to `Cache-Control` directives via
|
335
|
+
# {#cache_control}
|
336
|
+
#
|
337
|
+
# @return void
|
338
|
+
#
|
166
339
|
# @since 2.0.0
|
167
340
|
# @api public
|
168
341
|
def expires(amount, *values)
|
@@ -170,6 +343,26 @@ module Hanami
|
|
170
343
|
headers.merge!(directives.headers)
|
171
344
|
end
|
172
345
|
|
346
|
+
# Sets the `etag` and/or `last_modified` headers on the response and halts with a `304 Not
|
347
|
+
# Modified` response if the request is still fresh according to the `IfNoneMatch` and
|
348
|
+
# `IfModifiedSince` request headers.
|
349
|
+
#
|
350
|
+
# @example
|
351
|
+
# # Set etag header and halt 304 if request matches IF_NONE_MATCH header
|
352
|
+
# response.fresh etag: some_resource.updated_at.to_i
|
353
|
+
#
|
354
|
+
# # Set last_modified header and halt 304 if request matches IF_MODIFIED_SINCE
|
355
|
+
# response.fresh last_modified: some_resource.updated_at
|
356
|
+
#
|
357
|
+
# # Set etag and last_modified header and halt 304 if request matches IF_MODIFIED_SINCE and IF_NONE_MATCH
|
358
|
+
# response.fresh last_modified: some_resource.updated_at
|
359
|
+
#
|
360
|
+
# @param options [Hash]
|
361
|
+
# @option options [Integer] :etag for testing IfNoneMatch conditions
|
362
|
+
# @option options [Date] :last_modified for testing IfModifiedSince conditions
|
363
|
+
#
|
364
|
+
# @return void
|
365
|
+
#
|
173
366
|
# @since 2.0.0
|
174
367
|
# @api public
|
175
368
|
def fresh(options)
|
@@ -183,7 +376,7 @@ module Hanami
|
|
183
376
|
end
|
184
377
|
|
185
378
|
# @since 2.0.0
|
186
|
-
# @api
|
379
|
+
# @api private
|
187
380
|
def set_format(value) # rubocop:disable Naming/AccessorMethodName
|
188
381
|
@format = value
|
189
382
|
end
|
@@ -209,7 +402,7 @@ module Hanami
|
|
209
402
|
alias_method :to_ary, :to_a
|
210
403
|
|
211
404
|
# @since 2.0.0
|
212
|
-
# @api
|
405
|
+
# @api private
|
213
406
|
def head?
|
214
407
|
env[Action::REQUEST_METHOD] == Action::HEAD
|
215
408
|
end
|
@@ -4,12 +4,17 @@ require "hanami/action/flash"
|
|
4
4
|
|
5
5
|
module Hanami
|
6
6
|
class Action
|
7
|
-
# Session
|
7
|
+
# Session support for actions.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Not included by default; you should include this module manually to enable session support.
|
10
|
+
# For actions within an Hanami app, this module will be included automatically if sessions are
|
11
|
+
# configured in the app config.
|
10
12
|
#
|
13
|
+
# @api public
|
11
14
|
# @since 0.1.0
|
12
15
|
module Session
|
16
|
+
# @api private
|
17
|
+
# @since 0.1.0
|
13
18
|
def self.included(base)
|
14
19
|
base.class_eval do
|
15
20
|
before { |req, _| req.id }
|
@@ -4,6 +4,12 @@ require "hanami/action/params"
|
|
4
4
|
|
5
5
|
module Hanami
|
6
6
|
class Action
|
7
|
+
# Support for validating params when calling actions.
|
8
|
+
#
|
9
|
+
# Included only when hanami-validations (and its dependencies) are bundled.
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
7
13
|
module Validatable
|
8
14
|
# Defines the class name for anonymous params
|
9
15
|
#
|
@@ -34,13 +40,10 @@ module Hanami
|
|
34
40
|
# Once whitelisted, the params are available as an Hash with symbols
|
35
41
|
# as keys.
|
36
42
|
#
|
37
|
-
#
|
38
|
-
#
|
39
43
|
# It accepts an anonymous block where all the params can be listed.
|
40
44
|
# It internally creates an inner class which inherits from
|
41
45
|
# Hanami::Action::Params.
|
42
46
|
#
|
43
|
-
#
|
44
47
|
# Alternatively, it accepts an concrete class that should inherit from
|
45
48
|
# Hanami::Action::Params.
|
46
49
|
#
|
@@ -49,8 +52,6 @@ module Hanami
|
|
49
52
|
#
|
50
53
|
# @return void
|
51
54
|
#
|
52
|
-
# @since 0.3.0
|
53
|
-
#
|
54
55
|
# @see Hanami::Action::Params
|
55
56
|
# @see https://guides.hanamirb.org//validations/overview
|
56
57
|
#
|
@@ -93,6 +94,9 @@ module Hanami
|
|
93
94
|
# req.params[:admin] # => nil
|
94
95
|
# end
|
95
96
|
# end
|
97
|
+
#
|
98
|
+
# @since 0.3.0
|
99
|
+
# @api public
|
96
100
|
def params(klass = nil, &blk)
|
97
101
|
if klass.nil?
|
98
102
|
klass = const_set(PARAMS_CLASS_NAME, Class.new(Params))
|
data/lib/hanami/action.rb
CHANGED
@@ -24,7 +24,7 @@ require_relative "action/mime"
|
|
24
24
|
require_relative "action/rack/file"
|
25
25
|
require_relative "action/request"
|
26
26
|
require_relative "action/response"
|
27
|
-
require_relative "action/
|
27
|
+
require_relative "action/errors"
|
28
28
|
|
29
29
|
module Hanami
|
30
30
|
# An HTTP endpoint
|
@@ -126,71 +126,72 @@ module Hanami
|
|
126
126
|
#
|
127
127
|
# @raise [NoMethodError]
|
128
128
|
#
|
129
|
-
# @api
|
129
|
+
# @api public
|
130
130
|
# @since 2.0.0
|
131
131
|
def self.params(_klass = nil)
|
132
132
|
raise NoMethodError,
|
133
133
|
"To use `params`, please add 'hanami/validations' gem to your Gemfile"
|
134
134
|
end
|
135
135
|
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
136
|
+
# @overload self.append_before(*callbacks, &block)
|
137
|
+
# Define a callback for an Action.
|
138
|
+
# The callback will be executed **before** the action is called, in the
|
139
|
+
# order they are added.
|
139
140
|
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
141
|
+
# @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
|
142
|
+
# each of them is representing a name of a method available in the
|
143
|
+
# context of the Action.
|
143
144
|
#
|
144
|
-
#
|
145
|
+
# @param blk [Proc] an anonymous function to be executed
|
145
146
|
#
|
146
|
-
#
|
147
|
+
# @return [void]
|
147
148
|
#
|
148
|
-
#
|
149
|
+
# @since 0.3.2
|
149
150
|
#
|
150
|
-
#
|
151
|
+
# @see Hanami::Action::Callbacks::ClassMethods#append_after
|
151
152
|
#
|
152
|
-
#
|
153
|
-
#
|
153
|
+
# @example Method names (symbols)
|
154
|
+
# require "hanami/controller"
|
154
155
|
#
|
155
|
-
#
|
156
|
-
#
|
156
|
+
# class Show < Hanami::Action
|
157
|
+
# before :authenticate, :set_article
|
157
158
|
#
|
158
|
-
#
|
159
|
-
#
|
159
|
+
# def handle(req, res)
|
160
|
+
# end
|
160
161
|
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
162
|
+
# private
|
163
|
+
# def authenticate
|
164
|
+
# # ...
|
165
|
+
# end
|
165
166
|
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
167
|
+
# # `params` in the method signature is optional
|
168
|
+
# def set_article(params)
|
169
|
+
# @article = Article.find params[:id]
|
170
|
+
# end
|
169
171
|
# end
|
170
|
-
# end
|
171
172
|
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
176
|
-
#
|
173
|
+
# # The order of execution will be:
|
174
|
+
# #
|
175
|
+
# # 1. #authenticate
|
176
|
+
# # 2. #set_article
|
177
|
+
# # 3. #call
|
177
178
|
#
|
178
|
-
#
|
179
|
-
#
|
179
|
+
# @example Anonymous functions (Procs)
|
180
|
+
# require "hanami/controller"
|
180
181
|
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
182
|
+
# class Show < Hanami::Action
|
183
|
+
# before { ... } # 1 do some authentication stuff
|
184
|
+
# before {|req, res| @article = Article.find params[:id] } # 2
|
184
185
|
#
|
185
|
-
#
|
186
|
+
# def handle(req, res)
|
187
|
+
# end
|
186
188
|
# end
|
187
|
-
# end
|
188
189
|
#
|
189
|
-
#
|
190
|
-
#
|
191
|
-
#
|
192
|
-
#
|
193
|
-
#
|
190
|
+
# # The order of execution will be:
|
191
|
+
# #
|
192
|
+
# # 1. authentication
|
193
|
+
# # 2. set the article
|
194
|
+
# # 3. `#handle`
|
194
195
|
def self.append_before(...)
|
195
196
|
config.before_callbacks.append(...)
|
196
197
|
end
|
@@ -200,21 +201,22 @@ module Hanami
|
|
200
201
|
alias_method :before, :append_before
|
201
202
|
end
|
202
203
|
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
204
|
+
# @overload self.append_after(*callbacks, &block)
|
205
|
+
# Define a callback for an Action.
|
206
|
+
# The callback will be executed **after** the action is called, in the
|
207
|
+
# order they are added.
|
206
208
|
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
209
|
+
# @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
|
210
|
+
# each of them is representing a name of a method available in the
|
211
|
+
# context of the Action.
|
210
212
|
#
|
211
|
-
#
|
213
|
+
# @param blk [Proc] an anonymous function to be executed
|
212
214
|
#
|
213
|
-
#
|
215
|
+
# @return [void]
|
214
216
|
#
|
215
|
-
#
|
217
|
+
# @since 0.3.2
|
216
218
|
#
|
217
|
-
#
|
219
|
+
# @see Hanami::Action::Callbacks::ClassMethods#append_before
|
218
220
|
def self.append_after(...)
|
219
221
|
config.after_callbacks.append(...)
|
220
222
|
end
|
@@ -224,40 +226,42 @@ module Hanami
|
|
224
226
|
alias_method :after, :append_after
|
225
227
|
end
|
226
228
|
|
227
|
-
#
|
228
|
-
#
|
229
|
-
#
|
229
|
+
# @overload self.prepend_before(*callbacks, &block)
|
230
|
+
# Define a callback for an Action.
|
231
|
+
# The callback will be executed **before** the action is called.
|
232
|
+
# It will add the callback at the beginning of the callbacks' chain.
|
230
233
|
#
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
234
|
+
# @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
|
235
|
+
# each of them is representing a name of a method available in the
|
236
|
+
# context of the Action.
|
234
237
|
#
|
235
|
-
#
|
238
|
+
# @param blk [Proc] an anonymous function to be executed
|
236
239
|
#
|
237
|
-
#
|
240
|
+
# @return [void]
|
238
241
|
#
|
239
|
-
#
|
242
|
+
# @since 0.3.2
|
240
243
|
#
|
241
|
-
#
|
244
|
+
# @see Hanami::Action::Callbacks::ClassMethods#prepend_after
|
242
245
|
def self.prepend_before(...)
|
243
246
|
config.before_callbacks.prepend(...)
|
244
247
|
end
|
245
248
|
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
+
# @overload self.prepend_after(*callbacks, &block)
|
250
|
+
# Define a callback for an Action.
|
251
|
+
# The callback will be executed **after** the action is called.
|
252
|
+
# It will add the callback at the beginning of the callbacks' chain.
|
249
253
|
#
|
250
|
-
#
|
251
|
-
#
|
252
|
-
#
|
254
|
+
# @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
|
255
|
+
# each of them is representing a name of a method available in the
|
256
|
+
# context of the Action.
|
253
257
|
#
|
254
|
-
#
|
258
|
+
# @param blk [Proc] an anonymous function to be executed
|
255
259
|
#
|
256
|
-
#
|
260
|
+
# @return [void]
|
257
261
|
#
|
258
|
-
#
|
262
|
+
# @since 0.3.2
|
259
263
|
#
|
260
|
-
#
|
264
|
+
# @see Hanami::Action::Callbacks::ClassMethods#prepend_before
|
261
265
|
def self.prepend_after(...)
|
262
266
|
config.after_callbacks.prepend(...)
|
263
267
|
end
|
@@ -266,7 +270,7 @@ module Hanami
|
|
266
270
|
#
|
267
271
|
# @param formats[Array<Symbol>] one or more symbols representing mime type(s)
|
268
272
|
#
|
269
|
-
# @raise [Hanami::
|
273
|
+
# @raise [Hanami::Action::UnknownFormatError] if the symbol cannot
|
270
274
|
# be converted into a mime type
|
271
275
|
#
|
272
276
|
# @since 0.1.0
|
@@ -586,20 +590,6 @@ module Hanami
|
|
586
590
|
res.body = Response::EMPTY_BODY
|
587
591
|
end
|
588
592
|
|
589
|
-
# @since 2.0.0
|
590
|
-
# @api private
|
591
|
-
def format(value)
|
592
|
-
case value
|
593
|
-
when Symbol
|
594
|
-
format = Utils::Kernel.Symbol(value)
|
595
|
-
[format, Action::Mime.format_to_mime_type(format, config)]
|
596
|
-
when String
|
597
|
-
[Action::Mime.detect_format(value, config), value]
|
598
|
-
else
|
599
|
-
raise Hanami::Controller::UnknownFormatError.new(value)
|
600
|
-
end
|
601
|
-
end
|
602
|
-
|
603
593
|
# Finalize the response
|
604
594
|
#
|
605
595
|
# Prepare the data before the response will be returned to the webserver
|
data/lib/hanami/controller.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "hanami/action"
|
4
4
|
require "hanami/controller/version"
|
5
|
-
require "hanami/controller/error"
|
6
5
|
|
7
6
|
# Hanami
|
8
7
|
#
|
@@ -27,20 +26,5 @@ module Hanami
|
|
27
26
|
# end
|
28
27
|
# end
|
29
28
|
module Controller
|
30
|
-
# Unknown format error
|
31
|
-
#
|
32
|
-
# This error is raised when a action sets a format that it isn't recognized
|
33
|
-
# both by `Hanami::Action::Configuration` and the list of Rack mime types
|
34
|
-
#
|
35
|
-
# @since 0.2.0
|
36
|
-
#
|
37
|
-
# @see Hanami::Action::Mime#format=
|
38
|
-
class UnknownFormatError < Hanami::Controller::Error
|
39
|
-
# @since 0.2.0
|
40
|
-
# @api private
|
41
|
-
def initialize(format)
|
42
|
-
super("Cannot find a corresponding Mime type for '#{format}'. Please configure it with Hanami::Controller::Configuration#format.") # rubocop:disable Layout/LineLength
|
43
|
-
end
|
44
|
-
end
|
45
29
|
end
|
46
30
|
end
|