hanami-controller 2.0.0.beta4 → 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 +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
|