hanami-controller 2.0.1 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19de4a7e13f8845b766110c62f3fafef0d600cdc7e2ae12c0083f73f91fa0224
4
- data.tar.gz: fe8adf8eaff82024d6dcdfaff5e7e0a41c210e138419807af89a74babc10a6d4
3
+ metadata.gz: 58299df4276e04c035c82a7afcf6c012bd5059213d5fcc375ecc2e001900aa9b
4
+ data.tar.gz: 9c7d4d3a80766da72364f2eee2d6909785a70ef9c63f6e1739d46af11bd9e49b
5
5
  SHA512:
6
- metadata.gz: 85493e28f9f323982bffd69c89e2ffeceaed9d284f21776f118e36cfc6b52ce7355e450c37d67212fc2bc135d60925a2bb7287f123892fabc81148fba076e1ec
7
- data.tar.gz: 37a1e25fd2ea272ef88f203f001830729c40102462be05681a3669c38ece703827948f08d901f2ad93092739b546a23b8714dd79452466be49619e72bf3e9fe3
6
+ metadata.gz: 63d21bbd06003cac35e8b12d94fb829bdaf9a95164b948a7059aab745cb49ca8b9f100b7ac27a244a9cd9c4e9c1db6a1c7cb0c279859e6bf56eb75aa846bfd1c
7
+ data.tar.gz: a04360570cf34f82caff342a04a2d46ca55c951c3aa718c1c15d0ff723f79b9b87b56e8e8ec57489a9f4d06a10ec35ad7f1681b9e6695aa393943a97c191fc99
data/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  Complete, fast and testable actions for Rack
4
4
 
5
+ ## v2.1.0.beta1 - 2023-06-29
6
+
7
+ ### Added
8
+
9
+ - [Tim Riley] Add `Request#session_enabled?` and `Response#session_enabled?` (#423)
10
+
11
+ ## v2.0.2 - 2023-02-01
12
+
13
+ ### Added
14
+
15
+ - [Adam Lassek] Params Pattern Matching
16
+ - [Adam Lassek, Luca Guidi] Allow to `halt` using a `Symbol`: `halt :unauthorized`
17
+ - [Adam Lassek, Luca Guidi] Introduce `Hanami::Action::Response#status=` to accept an `Integer` or a `Symbol`
18
+
19
+ ### Fixed
20
+
21
+ - [Pat Allan] Ensure action accepting the request with a custom MIME Type
22
+ - [Luca Guidi] Halting with an unknown HTTP code will raise a `Hanami::Action::UnknownHttpStatusError`
23
+ - [Luca Guidi] Fix error message for missing format (MIME Type)
24
+
5
25
  ## v2.0.1 - 2022-12-25
6
26
 
7
27
  ### Added
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2014-2021 Luca Guidi
1
+ Copyright © 2014 Hanami Team
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -961,4 +961,4 @@ __Hanami::Controller__ uses [Semantic Versioning 2.0.0](http://semver.org)
961
961
 
962
962
  ## Copyright
963
963
 
964
- Copyright © 2014-2022 Hanami Team – Released under MIT License
964
+ Copyright © 2014 Hanami Team – Released under MIT License
@@ -88,9 +88,9 @@ module Hanami
88
88
  @directives = []
89
89
  values.each do |directive_key|
90
90
  if directive_key.is_a? Hash
91
- directive_key.each { |name, value| self.<< ValueDirective.new(name, value) }
91
+ directive_key.each { |name, value| self << ValueDirective.new(name, value) }
92
92
  else
93
- self.<< NonValueDirective.new(directive_key)
93
+ self << NonValueDirective.new(directive_key)
94
94
  end
95
95
  end
96
96
  end
@@ -9,6 +9,20 @@ module Hanami
9
9
  class Error < ::StandardError
10
10
  end
11
11
 
12
+ # Unknown status HTTP Status error
13
+ #
14
+ # @since 2.0.2
15
+ #
16
+ # @see Hanami::Action::Response#status=
17
+ # @see https://guides.hanamirb.org/v2.0/actions/status-codes/
18
+ class UnknownHttpStatusError < Error
19
+ # @since 2.0.2
20
+ # @api private
21
+ def initialize(code)
22
+ super("unknown HTTP status: `#{code.inspect}'")
23
+ end
24
+ end
25
+
12
26
  # Unknown format error
13
27
  #
14
28
  # This error is raised when a action sets a format that it isn't recognized
@@ -21,14 +35,26 @@ module Hanami
21
35
  # @since 2.0.0
22
36
  # @api private
23
37
  def initialize(format)
24
- msg =
25
- if format.to_s != "" # rubocop:disable Style/NegatedIfElseCondition
26
- "Cannot find a corresponding MIME type for format #{format.inspect}. Configure one via `config.formats.add(#{format}: \"MIME_TYPE_HERE\")`." # rubocop:disable Layout/LineLength
27
- else
28
- "Cannot find a corresponding MIME type for `nil` format."
29
- end
38
+ message = <<~MSG
39
+ Cannot find a corresponding MIME type for format `#{format.inspect}'.
40
+ MSG
41
+
42
+ unless blank?(format)
43
+ message += <<~MSG
44
+
45
+ Configure one via: `config.actions.formats.add(:#{format}, "MIME_TYPE_HERE")' in `config/app.rb' to share between actions of a Hanami app.
46
+
47
+ Or make it available only in the current action: `config.formats.add(:#{format}, "MIME_TYPE_HERE")'.
48
+ MSG
49
+ end
50
+
51
+ super(message)
52
+ end
53
+
54
+ private
30
55
 
31
- super(msg)
56
+ def blank?(format)
57
+ format.to_s.match(/\A[[:space:]]*\z/)
32
58
  end
33
59
  end
34
60
 
@@ -10,8 +10,8 @@ module Hanami
10
10
  # @api private
11
11
  # @since 2.0.0
12
12
  def self.call(status, body = nil)
13
- body ||= Http::Status.message_for(status)
14
- throw :halt, [status, body]
13
+ code, message = Http::Status.for_code(status)
14
+ throw :halt, [code, body || message]
15
15
  end
16
16
  end
17
17
  end
@@ -237,7 +237,7 @@ module Hanami
237
237
  # @api private
238
238
  def accepted_mime_type?(mime_type, config)
239
239
  accepted_mime_types(config).any? { |accepted_mime_type|
240
- ::Rack::Mime.match?(accepted_mime_type, mime_type)
240
+ ::Rack::Mime.match?(mime_type, accepted_mime_type)
241
241
  }
242
242
  end
243
243
 
@@ -243,6 +243,15 @@ module Hanami
243
243
  @params
244
244
  end
245
245
  alias_method :to_hash, :to_h
246
+
247
+ # Pattern-matching support
248
+ #
249
+ # @return [::Hash]
250
+ #
251
+ # @since 2.0.2
252
+ def deconstruct_keys(*)
253
+ to_hash
254
+ end
246
255
  end
247
256
  end
248
257
  end
@@ -29,11 +29,11 @@ module Hanami
29
29
 
30
30
  # @since 2.0.0
31
31
  # @api private
32
- def initialize(env:, params:, sessions_enabled: false)
32
+ def initialize(env:, params:, session_enabled: false)
33
33
  super(env)
34
34
 
35
35
  @params = params
36
- @sessions_enabled = sessions_enabled
36
+ @session_enabled = session_enabled
37
37
  end
38
38
 
39
39
  # Returns the request's ID
@@ -47,18 +47,29 @@ module Hanami
47
47
  @id ||= @env[Action::REQUEST_ID] = SecureRandom.hex(Action::DEFAULT_ID_LENGTH)
48
48
  end
49
49
 
50
+ # Returns true if the session is enabled for the request.
51
+ #
52
+ # @return [Boolean]
53
+ #
54
+ # @api public
55
+ # @since 2.1.0
56
+ def session_enabled?
57
+ @session_enabled
58
+ end
59
+
50
60
  # Returns the session for the request.
51
61
  #
52
62
  # @return [Hash] the session object
53
63
  #
54
- # @raise [MissingSessionError] if sessions are not enabled
64
+ # @raise [MissingSessionError] if the session is not enabled
55
65
  #
66
+ # @see #session_enabled?
56
67
  # @see Response#session
57
68
  #
58
69
  # @since 2.0.0
59
70
  # @api public
60
71
  def session
61
- unless @sessions_enabled
72
+ unless session_enabled?
62
73
  raise Hanami::Action::MissingSessionError.new("Hanami::Action::Request#session")
63
74
  end
64
75
 
@@ -76,7 +87,7 @@ module Hanami
76
87
  # @since 2.0.0
77
88
  # @api public
78
89
  def flash
79
- unless @sessions_enabled
90
+ unless session_enabled?
80
91
  raise Hanami::Action::MissingSessionError.new("Hanami::Action::Request#flash")
81
92
  end
82
93
 
@@ -48,7 +48,7 @@ module Hanami
48
48
 
49
49
  # @since 2.0.0
50
50
  # @api private
51
- def initialize(request:, config:, content_type: nil, env: {}, headers: {}, view_options: nil, sessions_enabled: false) # rubocop:disable Layout/LineLength, Metrics/ParameterLists
51
+ def initialize(request:, config:, content_type: nil, env: {}, headers: {}, view_options: nil, session_enabled: false) # rubocop:disable Layout/LineLength, Metrics/ParameterLists
52
52
  super([], 200, headers.dup)
53
53
  self.content_type = content_type if content_type
54
54
 
@@ -59,7 +59,7 @@ module Hanami
59
59
  @env = env
60
60
  @view_options = view_options || DEFAULT_VIEW_OPTIONS
61
61
 
62
- @sessions_enabled = sessions_enabled
62
+ @session_enabled = session_enabled
63
63
  @sending_file = false
64
64
  end
65
65
 
@@ -81,6 +81,27 @@ module Hanami
81
81
  end
82
82
  end
83
83
 
84
+ # Set the response status
85
+ #
86
+ # @param code [Integer, Symbol] the status code
87
+ #
88
+ # @since 2.0.2
89
+ # @api public
90
+ #
91
+ # @raise [Hanami::Action::UnknownHttpStatusError] if the given code
92
+ # cannot be associated to a known HTTP status
93
+ #
94
+ # @example
95
+ # response.status = :unprocessable_entity
96
+ #
97
+ # @example
98
+ # response.status = 422
99
+ #
100
+ # @see https://guides.hanamirb.org/v2.0/actions/status-codes/
101
+ def status=(code)
102
+ super(Http::Status.lookup(code))
103
+ end
104
+
84
105
  # This is NOT RELEASED with 2.0.0
85
106
  #
86
107
  # @api private
@@ -166,6 +187,16 @@ module Hanami
166
187
  @exposures[key] = value
167
188
  end
168
189
 
190
+ # Returns true if the session is enabled for the request.
191
+ #
192
+ # @return [Boolean]
193
+ #
194
+ # @api public
195
+ # @since 2.1.0
196
+ def session_enabled?
197
+ @session_enabled
198
+ end
199
+
169
200
  # Returns the session for the response.
170
201
  #
171
202
  # This is the same session object as the {Request}.
@@ -179,7 +210,7 @@ module Hanami
179
210
  # @since 2.0.0
180
211
  # @api public
181
212
  def session
182
- unless @sessions_enabled
213
+ unless session_enabled?
183
214
  raise Hanami::Action::MissingSessionError.new("Hanami::Action::Response#session")
184
215
  end
185
216
 
@@ -199,7 +230,7 @@ module Hanami
199
230
  # @since 2.0.0
200
231
  # @api public
201
232
  def flash
202
- unless @sessions_enabled
233
+ unless session_enabled?
203
234
  raise Hanami::Action::MissingSessionError.new("Hanami::Action::Response#flash")
204
235
  end
205
236
 
@@ -21,7 +21,7 @@ module Hanami
21
21
 
22
22
  private
23
23
 
24
- def sessions_enabled?
24
+ def session_enabled?
25
25
  true
26
26
  end
27
27
 
data/lib/hanami/action.rb CHANGED
@@ -309,7 +309,7 @@ module Hanami
309
309
  request = build_request(
310
310
  env: env,
311
311
  params: params,
312
- sessions_enabled: sessions_enabled?
312
+ session_enabled: session_enabled?
313
313
  )
314
314
  response = build_response(
315
315
  request: request,
@@ -317,7 +317,7 @@ module Hanami
317
317
  content_type: Mime.response_content_type_with_charset(request, config),
318
318
  env: env,
319
319
  headers: config.default_headers,
320
- sessions_enabled: sessions_enabled?
320
+ session_enabled: session_enabled?
321
321
  )
322
322
 
323
323
  enforce_accepted_mime_types(request)
@@ -424,10 +424,10 @@ module Hanami
424
424
  nil
425
425
  end
426
426
 
427
- # @see Session#sessions_enabled?
427
+ # @see Session#session_enabled?
428
428
  # @since 2.0.0
429
429
  # @api private
430
- def sessions_enabled?
430
+ def session_enabled?
431
431
  false
432
432
  end
433
433
 
@@ -8,6 +8,6 @@ module Hanami
8
8
  #
9
9
  # @since 0.1.0
10
10
  # @api public
11
- VERSION = "2.0.1"
11
+ VERSION = "2.1.0.beta1"
12
12
  end
13
13
  end
@@ -17,31 +17,127 @@ module Hanami
17
17
  # @api private
18
18
  ALL = ::Rack::Utils::HTTP_STATUS_CODES
19
19
 
20
+ # Symbolic names for status codes
21
+ #
22
+ # @since 2.0.2
23
+ # @api private
24
+ SYMBOLS = ::Rack::Utils::SYMBOL_TO_STATUS_CODE
25
+
20
26
  # Return a status for the given code
21
27
  #
22
- # @param code [Integer] a valid HTTP code
28
+ # @param code [Integer, Symbol] a valid HTTP code
23
29
  #
24
30
  # @return [Array] a pair of code and message for an HTTP status
25
31
  #
32
+ # @raise [Hanami::Action::UnknownHttpStatusError] if the given code
33
+ # cannot be associated to a known HTTP status
34
+ #
26
35
  # @since 0.1.0
27
36
  # @api private
28
37
  #
29
- # @example
30
- # require 'hanami/http/status'
38
+ # @see https://guides.hanamirb.org/v2.0/actions/status-codes/
39
+ #
40
+ # @example Integer HTTP Status
41
+ # require "hanami/http/status"
42
+ #
43
+ # Hanami::Http::Status.for_code(401)
44
+ # # => [401, "Unauthorized"]
45
+ #
46
+ # @example Symbol HTTP Status
47
+ # require "hanami/http/status"
48
+ #
49
+ # Hanami::Http::Status.for_code(:unauthorized)
50
+ # # => [401, "Unauthorized"]
51
+ #
52
+ # @example Unknown HTTP Status
53
+ # require "hanami/http/status"
31
54
  #
32
- # Hanami::Http::Status.for_code(418) # => [418, "I'm a teapot"]
55
+ # Hanami::Http::Status.for_code(999)
56
+ # # => raise Hanami::Action::UnknownHttpStatusError
57
+ #
58
+ # Hanami::Http::Status.for_code(:foo)
59
+ # # => raise Hanami::Action::UnknownHttpStatusError
33
60
  def self.for_code(code)
34
- ALL.assoc(code)
61
+ case code
62
+ when Integer
63
+ ALL.assoc(code)
64
+ when Symbol
65
+ ALL.assoc(SYMBOLS[code])
66
+ end or raise ::Hanami::Action::UnknownHttpStatusError.new(code)
67
+ end
68
+
69
+ # Return a status code for the given code
70
+ #
71
+ # @param code [Integer,Symbol] a valid HTTP code
72
+ #
73
+ # @return [Integer] a message for the given status code
74
+ #
75
+ # @raise [Hanami::Action::UnknownHttpStatusError] if the given code
76
+ # cannot be associated to a known HTTP status
77
+ #
78
+ # @see https://guides.hanamirb.org/v2.0/actions/status-codes/
79
+ #
80
+ # @since 2.0.2
81
+ # @api private
82
+ #
83
+ # @example Integer HTTP Status
84
+ # require "hanami/http/status"
85
+ #
86
+ # Hanami::Http::Status.lookup(401)
87
+ # # => 401
88
+ #
89
+ # @example Symbol HTTP Status
90
+ # require "hanami/http/status"
91
+ #
92
+ # Hanami::Http::Status.lookup(:unauthorized)
93
+ # # => 401
94
+ #
95
+ # @example Unknown HTTP Status
96
+ # require "hanami/http/status"
97
+ #
98
+ # Hanami::Http::Status.lookup(999)
99
+ # # => raise Hanami::Action::UnknownHttpStatusError
100
+ #
101
+ # Hanami::Http::Status.lookup(:foo)
102
+ # # => raise Hanami::Action::UnknownHttpStatusError
103
+ def self.lookup(code)
104
+ for_code(code)[0]
35
105
  end
36
106
 
37
107
  # Return a message for the given status code
38
108
  #
39
- # @param code [Integer] a valid HTTP code
109
+ # @param code [Integer,Symbol] a valid HTTP code
40
110
  #
41
111
  # @return [String] a message for the given status code
42
112
  #
113
+ # @raise [Hanami::Action::UnknownHttpStatusError] if the given code
114
+ # cannot be associated to a known HTTP status
115
+ #
116
+ # @see https://guides.hanamirb.org/v2.0/actions/status-codes/
117
+ #
43
118
  # @since 0.3.2
44
119
  # @api private
120
+ #
121
+ # @example Integer HTTP Status
122
+ # require "hanami/http/status"
123
+ #
124
+ # Hanami::Http::Status.message_for(401)
125
+ # # => "Unauthorized"
126
+ #
127
+ # @example Symbol HTTP Status
128
+ # require "hanami/http/status"
129
+ #
130
+ # Hanami::Http::Status.message_for(:unauthorized)
131
+ # # => "Unauthorized"
132
+ #
133
+ # @example Unknown HTTP Status
134
+ # require "hanami/http/status"
135
+ #
136
+ # Hanami::Http::Status.message_for(999)
137
+ # # => raise Hanami::Action::UnknownHttpStatusError
138
+ #
139
+ # Hanami::Http::Status.message_for(:foo)
140
+ # # => raise Hanami::Action::UnknownHttpStatusError
45
141
  def self.message_for(code)
46
142
  for_code(code)[1]
47
143
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-25 00:00:00.000000000 Z
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -218,11 +218,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
218
  version: '3.0'
219
219
  required_rubygems_version: !ruby/object:Gem::Requirement
220
220
  requirements:
221
- - - ">="
221
+ - - ">"
222
222
  - !ruby/object:Gem::Version
223
- version: '0'
223
+ version: 1.3.1
224
224
  requirements: []
225
- rubygems_version: 3.4.1
225
+ rubygems_version: 3.4.13
226
226
  signing_key:
227
227
  specification_version: 4
228
228
  summary: Complete, fast and testable actions for Rack and Hanami