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.
@@ -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, :format, :env, :view_options
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
- set_header(Action::CONTENT_TYPE, content_type)
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
- # @since 2.0.0
77
- # @api public
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=(args)
85
- @format, content_type = *args
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 public
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 public
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 API
7
+ # Session support for actions.
8
8
  #
9
- # This module isn't included by default.
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/error"
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 private
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
- # Define a callback for an Action.
137
- # The callback will be executed **before** the action is called, in the
138
- # order they are added.
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
- # @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
141
- # each of them is representing a name of a method available in the
142
- # context of the Action.
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
- # @param blk [Proc] an anonymous function to be executed
145
+ # @param blk [Proc] an anonymous function to be executed
145
146
  #
146
- # @return [void]
147
+ # @return [void]
147
148
  #
148
- # @since 0.3.2
149
+ # @since 0.3.2
149
150
  #
150
- # @see Hanami::Action::Callbacks::ClassMethods#append_after
151
+ # @see Hanami::Action::Callbacks::ClassMethods#append_after
151
152
  #
152
- # @example Method names (symbols)
153
- # require "hanami/controller"
153
+ # @example Method names (symbols)
154
+ # require "hanami/controller"
154
155
  #
155
- # class Show < Hanami::Action
156
- # before :authenticate, :set_article
156
+ # class Show < Hanami::Action
157
+ # before :authenticate, :set_article
157
158
  #
158
- # def handle(req, res)
159
- # end
159
+ # def handle(req, res)
160
+ # end
160
161
  #
161
- # private
162
- # def authenticate
163
- # # ...
164
- # end
162
+ # private
163
+ # def authenticate
164
+ # # ...
165
+ # end
165
166
  #
166
- # # `params` in the method signature is optional
167
- # def set_article(params)
168
- # @article = Article.find params[:id]
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
- # # The order of execution will be:
173
- # #
174
- # # 1. #authenticate
175
- # # 2. #set_article
176
- # # 3. #call
173
+ # # The order of execution will be:
174
+ # #
175
+ # # 1. #authenticate
176
+ # # 2. #set_article
177
+ # # 3. #call
177
178
  #
178
- # @example Anonymous functions (Procs)
179
- # require "hanami/controller"
179
+ # @example Anonymous functions (Procs)
180
+ # require "hanami/controller"
180
181
  #
181
- # class Show < Hanami::Action
182
- # before { ... } # 1 do some authentication stuff
183
- # before {|req, res| @article = Article.find params[:id] } # 2
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
- # def handle(req, res)
186
+ # def handle(req, res)
187
+ # end
186
188
  # end
187
- # end
188
189
  #
189
- # # The order of execution will be:
190
- # #
191
- # # 1. authentication
192
- # # 2. set the article
193
- # # 3. `#handle`
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
- # Define a callback for an Action.
204
- # The callback will be executed **after** the action is called, in the
205
- # order they are added.
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
- # @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
208
- # each of them is representing a name of a method available in the
209
- # context of the Action.
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
- # @param blk [Proc] an anonymous function to be executed
213
+ # @param blk [Proc] an anonymous function to be executed
212
214
  #
213
- # @return [void]
215
+ # @return [void]
214
216
  #
215
- # @since 0.3.2
217
+ # @since 0.3.2
216
218
  #
217
- # @see Hanami::Action::Callbacks::ClassMethods#append_before
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
- # Define a callback for an Action.
228
- # The callback will be executed **before** the action is called.
229
- # It will add the callback at the beginning of the callbacks' chain.
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
- # @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
232
- # each of them is representing a name of a method available in the
233
- # context of the Action.
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
- # @param blk [Proc] an anonymous function to be executed
238
+ # @param blk [Proc] an anonymous function to be executed
236
239
  #
237
- # @return [void]
240
+ # @return [void]
238
241
  #
239
- # @since 0.3.2
242
+ # @since 0.3.2
240
243
  #
241
- # @see Hanami::Action::Callbacks::ClassMethods#prepend_after
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
- # Define a callback for an Action.
247
- # The callback will be executed **after** the action is called.
248
- # It will add the callback at the beginning of the callbacks' chain.
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
- # @param callbacks [Symbol, Array<Symbol>] a single or multiple symbol(s)
251
- # each of them is representing a name of a method available in the
252
- # context of the Action.
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
- # @param blk [Proc] an anonymous function to be executed
258
+ # @param blk [Proc] an anonymous function to be executed
255
259
  #
256
- # @return [void]
260
+ # @return [void]
257
261
  #
258
- # @since 0.3.2
262
+ # @since 0.3.2
259
263
  #
260
- # @see Hanami::Action::Callbacks::ClassMethods#prepend_before
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::Controller::UnknownFormatError] if the symbol cannot
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
@@ -2,9 +2,7 @@
2
2
 
3
3
  module Hanami
4
4
  module Controller
5
- # Defines the version
6
- #
7
- # @since 0.1.0
8
- VERSION = "2.0.0.beta4"
5
+ # @api public
6
+ VERSION = "2.0.0.rc1"
9
7
  end
10
8
  end
@@ -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