hanami-router 1.3.1 → 2.0.0.alpha4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +97 -443
  5. data/hanami-router.gemspec +23 -19
  6. data/lib/hanami/middleware/body_parser.rb +21 -15
  7. data/lib/hanami/middleware/body_parser/class_interface.rb +62 -56
  8. data/lib/hanami/middleware/body_parser/errors.rb +7 -4
  9. data/lib/hanami/middleware/body_parser/json_parser.rb +9 -7
  10. data/lib/hanami/middleware/body_parser/parser.rb +58 -0
  11. data/lib/hanami/middleware/error.rb +16 -0
  12. data/lib/hanami/router.rb +548 -957
  13. data/lib/hanami/router/block.rb +88 -0
  14. data/lib/hanami/router/error.rb +67 -0
  15. data/lib/hanami/router/node.rb +91 -0
  16. data/lib/hanami/router/params.rb +35 -0
  17. data/lib/hanami/router/prefix.rb +67 -0
  18. data/lib/hanami/router/recognized_route.rb +92 -0
  19. data/lib/hanami/router/redirect.rb +28 -0
  20. data/lib/hanami/router/segment.rb +19 -0
  21. data/lib/hanami/router/trie.rb +63 -0
  22. data/lib/hanami/router/url_helpers.rb +40 -0
  23. data/lib/hanami/router/version.rb +4 -1
  24. metadata +61 -41
  25. data/lib/hanami-router.rb +0 -1
  26. data/lib/hanami/routing/endpoint.rb +0 -195
  27. data/lib/hanami/routing/endpoint_resolver.rb +0 -238
  28. data/lib/hanami/routing/error.rb +0 -7
  29. data/lib/hanami/routing/force_ssl.rb +0 -212
  30. data/lib/hanami/routing/http_router.rb +0 -220
  31. data/lib/hanami/routing/http_router_monkey_patch.rb +0 -38
  32. data/lib/hanami/routing/namespace.rb +0 -98
  33. data/lib/hanami/routing/parsers.rb +0 -113
  34. data/lib/hanami/routing/parsing/json_parser.rb +0 -33
  35. data/lib/hanami/routing/parsing/parser.rb +0 -61
  36. data/lib/hanami/routing/recognized_route.rb +0 -219
  37. data/lib/hanami/routing/resource.rb +0 -119
  38. data/lib/hanami/routing/resource/action.rb +0 -402
  39. data/lib/hanami/routing/resource/nested.rb +0 -41
  40. data/lib/hanami/routing/resource/options.rb +0 -74
  41. data/lib/hanami/routing/resources.rb +0 -48
  42. data/lib/hanami/routing/resources/action.rb +0 -156
  43. data/lib/hanami/routing/route.rb +0 -71
  44. data/lib/hanami/routing/routes_inspector.rb +0 -221
@@ -1,33 +0,0 @@
1
- require 'hanami/utils/json'
2
-
3
- module Hanami
4
- module Routing
5
- module Parsing
6
- # @since 0.2.0
7
- # @api private
8
- class JsonParser < Parser
9
- # @since 0.2.0
10
- # @api private
11
- def mime_types
12
- ['application/json', 'application/vnd.api+json']
13
- end
14
-
15
- # Parse a json string
16
- #
17
- # @param body [String] a json string
18
- #
19
- # @return [Hash] the parsed json
20
- #
21
- # @raise [Hanami::Routing::Parsing::BodyParsingError] when the body can't be parsed.
22
- #
23
- # @since 0.2.0
24
- # @api private
25
- def parse(body)
26
- Hanami::Utils::Json.parse(body)
27
- rescue Hanami::Utils::Json::ParserError => e
28
- raise BodyParsingError.new(e.message)
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,61 +0,0 @@
1
- require 'hanami/utils/class'
2
- require 'hanami/utils/string'
3
- require 'hanami/routing/error'
4
-
5
- module Hanami
6
- module Routing
7
- module Parsing
8
- # Body parsing error
9
- # This is raised when parser fails to parse the body
10
- #
11
- # @since 0.5.0
12
- class BodyParsingError < Hanami::Routing::Error
13
- end
14
-
15
- # @since 0.2.0
16
- class UnknownParserError < Hanami::Routing::Error
17
- # @since 0.2.0
18
- # @api private
19
- def initialize(parser)
20
- super("Unknown Parser: `#{ parser }'")
21
- end
22
- end
23
-
24
- # @since 0.2.0
25
- class Parser
26
- # @since 0.2.0
27
- # @api private
28
- def self.for(parser)
29
- case parser
30
- when String, Symbol
31
- require_parser(parser)
32
- else
33
- parser
34
- end
35
- end
36
-
37
- # @since 0.2.0
38
- def mime_types
39
- raise NotImplementedError
40
- end
41
-
42
- # @since 0.2.0
43
- def parse(body)
44
- Hash.new
45
- end
46
-
47
- private
48
- # @since 0.2.0
49
- # @api private
50
- def self.require_parser(parser)
51
- require "hanami/routing/parsing/#{ parser }_parser"
52
-
53
- parser = Utils::String.classify(parser)
54
- Utils::Class.load!("Hanami::Routing::Parsing::#{ parser }Parser").new
55
- rescue LoadError, NameError
56
- raise UnknownParserError.new(parser)
57
- end
58
- end
59
- end
60
- end
61
- end
@@ -1,219 +0,0 @@
1
- require 'hanami/utils/string'
2
-
3
- module Hanami
4
- module Routing
5
- # Represents a result of router path recognition.
6
- #
7
- # @since 0.5.0
8
- #
9
- # @see Hanami::Router#recognize
10
- class RecognizedRoute
11
- # @since 0.5.0
12
- # @api private
13
- REQUEST_METHOD = 'REQUEST_METHOD'.freeze
14
-
15
- # @since 0.7.0
16
- # @api private
17
- PATH_INFO = 'PATH_INFO'.freeze
18
-
19
- # @since 0.5.0
20
- # @api private
21
- NAMESPACE = '%s::'.freeze
22
-
23
- # @since 0.5.0
24
- # @api private
25
- NAMESPACE_REPLACEMENT = ''.freeze
26
-
27
- # @since 0.5.0
28
- # @api private
29
- ACTION_PATH_SEPARATOR = '/'.freeze
30
-
31
- # @since 0.5.0
32
- # @api public
33
- attr_reader :params
34
-
35
- # Creates a new instance
36
- #
37
- # @param response [HttpRouter::Response] raw response of recognition
38
- # @param env [Hash] Rack env
39
- # @param router [Hanami::Routing::HttpRouter] low level router
40
- #
41
- # @return [Hanami::Routing::RecognizedRoute]
42
- #
43
- # @since 0.5.0
44
- # @api private
45
- def initialize(response, env, router)
46
- @env = env
47
- @endpoint = nil
48
- @params = {}
49
-
50
- unless response.nil?
51
- @endpoint = response.route.dest
52
- @params = response.params
53
- end
54
-
55
- @namespace = router.namespace
56
- @action_separator = router.action_separator
57
- end
58
-
59
- # Rack protocol compatibility
60
- #
61
- # @param env [Hash] Rack env
62
- #
63
- # @return [Array] serialized Rack response
64
- #
65
- # @raise [Hanami::Router::NotRoutableEndpointError] if not routable
66
- #
67
- # @since 0.5.0
68
- # @api public
69
- #
70
- # @see Hanami::Routing::RecognizedRoute#routable?
71
- # @see Hanami::Router::NotRoutableEndpointError
72
- def call(env)
73
- if routable?
74
- @endpoint.call(env)
75
- else
76
- raise Hanami::Router::NotRoutableEndpointError.new(@env)
77
- end
78
- end
79
-
80
- # HTTP verb (aka method)
81
- #
82
- # @return [String]
83
- #
84
- # @since 0.5.0
85
- # @api public
86
- def verb
87
- @env[REQUEST_METHOD]
88
- end
89
-
90
- # Relative URL (path)
91
- #
92
- # @return [String]
93
- #
94
- # @since 0.7.0
95
- # @api public
96
- def path
97
- @env[PATH_INFO]
98
- end
99
-
100
- # Action name
101
- #
102
- # @return [String]
103
- #
104
- # @since 0.5.0
105
- # @api public
106
- #
107
- # @see Hanami::Router#recognize
108
- #
109
- # @example
110
- # require 'hanami/router'
111
- #
112
- # router = Hanami::Router.new do
113
- # get '/books/:id', to: 'books#show'
114
- # end
115
- #
116
- # puts router.recognize('/books/23').action # => "books#show"
117
- def action
118
- return if !routable? || redirect?
119
- namespace = NAMESPACE % @namespace
120
-
121
- if destination.match(namespace)
122
- Hanami::Utils::String.transform(
123
- destination.sub(namespace, NAMESPACE_REPLACEMENT),
124
- :underscore, [:rsub, ACTION_PATH_SEPARATOR, @action_separator])
125
- else
126
- destination
127
- end
128
- end
129
-
130
- # Check if routable
131
- #
132
- # @return [TrueClass,FalseClass]
133
- #
134
- # @since 0.5.0
135
- # @api public
136
- #
137
- # @see Hanami::Router#recognize
138
- #
139
- # @example
140
- # require 'hanami/router'
141
- #
142
- # router = Hanami::Router.new do
143
- # get '/', to: 'home#index'
144
- # end
145
- #
146
- # puts router.recognize('/').routable? # => true
147
- # puts router.recognize('/foo').routable? # => false
148
- def routable?
149
- @endpoint&.routable? || false
150
- end
151
-
152
- # Check if redirect
153
- #
154
- # @return [TrueClass,FalseClass]
155
- #
156
- # @since 1.0.1
157
- # @api public
158
- #
159
- # @see Hanami::Router#recognize
160
- #
161
- # @example
162
- # require 'hanami/router'
163
- #
164
- # router = Hanami::Router.new do
165
- # get '/', to: 'home#index'
166
- # redirect '/home', to: '/'
167
- # end
168
- #
169
- # puts router.recognize('/home').redirect? # => true
170
- # puts router.recognize('/').redirect? # => false
171
- def redirect?
172
- @endpoint&.redirect? || false
173
- end
174
-
175
- # Returns the redirect destination path
176
- #
177
- # @return [String,NilClass] the destination path, if it's a redirect
178
- #
179
- # @since 1.0.1
180
- # @api public
181
- #
182
- # @see Hanami::Router#recognize
183
- # @see #redirect?
184
- #
185
- # @example
186
- # require 'hanami/router'
187
- #
188
- # router = Hanami::Router.new do
189
- # get '/', to: 'home#index'
190
- # redirect '/home', to: '/'
191
- # end
192
- #
193
- # puts router.recognize('/home').destination_path # => "/"
194
- # puts router.recognize('/').destination_path # => nil
195
- def redirection_path
196
- @endpoint&.destination_path
197
- end
198
-
199
- private
200
-
201
- # @since 0.5.0
202
- # @api private
203
- #
204
- # @see Hanami::Routing::Endpoint
205
- def destination
206
- @destination ||= begin
207
- case k = @endpoint.__getobj__
208
- when Class
209
- k.name
210
- when Proc
211
- @endpoint.inspect
212
- else
213
- k.class.name
214
- end
215
- end
216
- end
217
- end
218
- end
219
- end
@@ -1,119 +0,0 @@
1
- require 'hanami/utils/class_attribute'
2
- require 'hanami/routing/resource/options'
3
- require 'hanami/routing/resource/action'
4
-
5
- module Hanami
6
- module Routing
7
- # Set of RESTful resource routes
8
- # Implementation of Hanami::Router#resource
9
- #
10
- # @since 0.1.0
11
- #
12
- # @api private
13
- #
14
- # @see Hanami::Router#resource
15
- class Resource
16
- include Utils::ClassAttribute
17
-
18
- # @api private
19
- # @since 0.4.0
20
- NESTED_ROUTES_SEPARATOR = '/'.freeze
21
-
22
- # Set of default routes
23
- #
24
- # @api private
25
- # @since 0.1.0
26
- class_attribute :actions
27
- self.actions = [:new, :create, :show, :edit, :update, :destroy]
28
-
29
- # Action class
30
- #
31
- # @api private
32
- # @since 0.1.0
33
- class_attribute :action
34
- self.action = Resource::Action
35
-
36
- # Member action class
37
- #
38
- # @api private
39
- # @since 0.1.0
40
- class_attribute :member
41
- self.member = Resource::MemberAction
42
-
43
- # Collection action class
44
- #
45
- # @api private
46
- # @since 0.1.0
47
- class_attribute :collection
48
- self.collection = Resource::CollectionAction
49
-
50
- # @api private
51
- # @since 0.4.0
52
- attr_reader :parent
53
-
54
- # @api private
55
- # @since 0.1.0
56
- def initialize(router, name, options = {}, parent = nil, &blk)
57
- @router = router
58
- @name = name
59
- @parent = parent
60
- @options = Options.new(self.class.actions, options.merge(name: @name))
61
- generate(&blk)
62
- end
63
-
64
- # Allow nested resources inside resource or resources
65
- #
66
- # @since 0.4.0
67
- #
68
- # @see Hanami::Router#resources
69
- def resources(name, options = {}, &blk)
70
- _resource(Resources, name, options, &blk)
71
- end
72
-
73
- # Allow nested resource inside resource or resources
74
- #
75
- # @since 0.4.0
76
- #
77
- # @see Hanami::Router#resource
78
- def resource(name, options = {}, &blk)
79
- _resource(Resource, name, options, &blk)
80
- end
81
-
82
- # Return separator
83
- #
84
- # @api private
85
- # @since 0.4.0
86
- def wildcard_param(route_param = nil)
87
- NESTED_ROUTES_SEPARATOR
88
- end
89
-
90
- private
91
-
92
- # @api private
93
- # @since 0.4.0
94
- def _resource(klass, name, options, &blk)
95
- options = options.merge(separator: @options[:separator], namespace: @options[:namespace])
96
- klass.new(@router, [@name, name].join(NESTED_ROUTES_SEPARATOR), options, self, &blk)
97
- end
98
-
99
- # @api private
100
- def generate(&blk)
101
- instance_eval(&blk) if block_given?
102
-
103
- @options.actions.each do |action|
104
- self.class.action.generate(@router, action, @options, self)
105
- end
106
- end
107
-
108
- # @api private
109
- def member(&blk)
110
- self.class.member.new(@router, @options, self, &blk)
111
- end
112
-
113
- # @api private
114
- def collection(&blk)
115
- self.class.collection.new(@router, @options, self, &blk)
116
- end
117
- end
118
- end
119
- end
@@ -1,402 +0,0 @@
1
- require 'hanami/utils/string'
2
- require 'hanami/utils/path_prefix'
3
- require 'hanami/utils/class_attribute'
4
- require 'hanami/routing/resource/nested'
5
-
6
- module Hanami
7
- module Routing
8
- class Resource
9
- # Action for RESTful resource
10
- #
11
- # @since 0.1.0
12
- #
13
- # @api private
14
- #
15
- # @see Hanami::Router#resource
16
- class Action
17
- include Utils::ClassAttribute
18
-
19
- # Nested routes separator
20
- #
21
- # @api private
22
- # @since 0.4.0
23
- NESTED_ROUTES_SEPARATOR = '/'.freeze
24
-
25
- # Ruby namespace where lookup for default subclasses.
26
- #
27
- # @api private
28
- # @since 0.1.0
29
- class_attribute :namespace
30
- self.namespace = Resource
31
-
32
- # Accepted HTTP verb
33
- #
34
- # @api private
35
- # @since 0.1.0
36
- class_attribute :verb
37
- self.verb = :get
38
-
39
- # Separator for named routes
40
- #
41
- # @api private
42
- # @since 0.2.0
43
- class_attribute :named_route_separator
44
- self.named_route_separator = '_'.freeze
45
-
46
- # Generate an action for the given router
47
- #
48
- # @param router [Hanami::Router]
49
- # @param action [Hanami::Routing::Resource::Action]
50
- # @param options [Hash]
51
- # @param resource [Hanami::Routing::Resource, Hanami::Routing::Resources]
52
- #
53
- # @api private
54
- #
55
- # @since 0.1.0
56
- def self.generate(router, action, options = {}, resource = nil)
57
- class_for(action).new(router, options, resource)
58
- end
59
-
60
- # Initialize an action
61
- #
62
- # @param router [Hanami::Router]
63
- # @param options [Hash]
64
- # @param resource [Hanami::Routing::Resource, Hanami::Routing::Resources]
65
- # @param blk [Proc]
66
- #
67
- # @api private
68
- #
69
- # @since 0.1.0
70
- def initialize(router, options = {}, resource = nil, &blk)
71
- @router = router
72
- @options = options
73
- @resource = resource
74
- generate(&blk)
75
- end
76
-
77
- # Generate an action for the given router
78
- #
79
- # @param blk [Proc]
80
- #
81
- # @api private
82
- #
83
- # @since 0.1.0
84
- def generate(&blk)
85
- @router.send verb, path, to: endpoint, as: as
86
- instance_eval(&blk) if block_given?
87
- end
88
-
89
- # Resource name
90
- #
91
- # @return [String]
92
- #
93
- # @api private
94
- # @since 0.1.0
95
- #
96
- # @example
97
- # require 'hanami/router'
98
- #
99
- # Hanami::Router.new do
100
- # resource 'identity'
101
- # end
102
- #
103
- # # 'identity' is the name passed in the @options
104
- def resource_name
105
- @resource_name ||= @options[:name].to_s
106
- end
107
-
108
- # Namespace
109
- #
110
- # @api private
111
- # @since 0.2.0
112
- def namespace
113
- @namespace ||= Utils::PathPrefix.new @options[:namespace]
114
- end
115
-
116
- private
117
- # Load a subclass, according to the given action name
118
- #
119
- # @param action [String] the action name
120
- #
121
- # @example
122
- # Hanami::Routing::Resource::Action.send(:class_for, 'New') # =>
123
- # Hanami::Routing::Resource::New
124
- #
125
- # @api private
126
- # @since 0.1.0
127
- def self.class_for(action)
128
- Utils::Class.load!(Utils::String.classify(action), namespace)
129
- end
130
-
131
- # Accepted HTTP verb
132
- #
133
- # @see Hanami::Routing::Resource::Action.verb
134
- #
135
- # @api private
136
- # @since 0.1.0
137
- def verb
138
- self.class.verb
139
- end
140
-
141
- # The namespaced URL relative path
142
- #
143
- # @example
144
- # require 'hanami/router'
145
- #
146
- # Hanami::Router.new do
147
- # resources 'flowers'
148
- #
149
- # namespace 'animals' do
150
- # resources 'mammals'
151
- # end
152
- # end
153
- #
154
- # # It will generate paths like '/flowers', '/flowers/:id' ..
155
- # # It will generate paths like '/animals/mammals', '/animals/mammals/:id' ..
156
- #
157
- # @api private
158
- # @since 0.1.0
159
- def path
160
- rest_path
161
- end
162
-
163
- # The URL relative path
164
- #
165
- # @example
166
- # '/flowers'
167
- # '/flowers/new'
168
- # '/flowers/:id'
169
- #
170
- # @api private
171
- # @since 0.1.0
172
- def rest_path
173
- namespace.join(_nested_rest_path || resource_name.to_s)
174
- end
175
-
176
- # The namespaced name of the action within the whole context of the router.
177
- #
178
- # @example
179
- # require 'hanami/router'
180
- #
181
- # Hanami::Router.new do
182
- # resources 'flowers'
183
- #
184
- # namespace 'animals' do
185
- # resources 'mammals'
186
- # end
187
- # end
188
- #
189
- # # It will generate named routes like :flowers, :new_flowers ..
190
- # # It will generate named routes like :animals_mammals, :animals_new_mammals ..
191
- #
192
- # @api private
193
- # @since 0.1.0
194
- def as
195
- namespace.relative_join(_singularized_as, self.class.named_route_separator).to_sym
196
- end
197
-
198
- # The name of the RESTful action.
199
- #
200
- # @example
201
- # 'index'
202
- # 'new'
203
- # 'create'
204
- #
205
- # @api private
206
- # @since 0.1.0
207
- def action_name
208
- Utils::String.transform(self.class.name, :demodulize, :downcase)
209
- end
210
-
211
- # A string that represents the endpoint to be loaded.
212
- # It is composed by controller and action name.
213
- #
214
- # @see Hanami::Routing::Resource::Action#separator
215
- #
216
- # @example
217
- # 'flowers#index'
218
- #
219
- # @api private
220
- # @since 0.1.0
221
- def endpoint
222
- [ controller_name, action_name ].join separator
223
- end
224
-
225
- # Separator between controller and action name
226
- #
227
- # @see Hanami::Routing::EndpointResolver#separator
228
- #
229
- # @example
230
- # '#' # default
231
- #
232
- # @api private
233
- # @since 0.1.0
234
- def separator
235
- @options[:separator]
236
- end
237
-
238
- # Resource controller name
239
- #
240
- # @example
241
- # Hanami::Router.new do
242
- # resources 'flowers', controller: 'rocks'
243
- # end
244
- #
245
- # # It will mount path 'flowers/new' to Rocks::New instead of Flowers::New
246
- # # Same for other action names
247
- #
248
- # @api private
249
- # @since 0.4.0
250
- def controller_name
251
- @options[:controller] || resource_name
252
- end
253
-
254
- private
255
-
256
- # Singularize as (helper route)
257
- #
258
- # @api private
259
- # @since 0.4.0
260
- def _singularized_as
261
- name = @options[:as] ? @options[:as].to_s : resource_name
262
- name.split(NESTED_ROUTES_SEPARATOR).map do |n|
263
- Hanami::Utils::String.singularize(n)
264
- end
265
- end
266
-
267
- # Create nested rest path
268
- #
269
- # @api private
270
- # @since 0.4.0
271
- def _nested_rest_path
272
- Nested.new(resource_name, @resource).to_path
273
- end
274
- end
275
-
276
- # Collection action
277
- # It implements #collection within a #resource block.
278
- #
279
- # @api private
280
- # @since 0.1.0
281
- # @see Hanami::Router#resource
282
- class CollectionAction < Action
283
- # @since 0.1.0
284
- # @api private
285
- def generate(&blk)
286
- instance_eval(&blk) if block_given?
287
- end
288
-
289
- protected
290
- # @since 0.1.0
291
- # @api private
292
- def method_missing(m, *args)
293
- verb = m
294
- action_name = Utils::PathPrefix.new(args.first).relative_join(nil)
295
-
296
- @router.__send__ verb, path(action_name),
297
- to: endpoint(action_name), as: as(action_name)
298
- end
299
-
300
- private
301
- # @since 0.1.0
302
- # @api private
303
- def path(action_name)
304
- rest_path.join(action_name)
305
- end
306
-
307
- # @since 0.1.0
308
- # @api private
309
- def endpoint(action_name)
310
- [ controller_name, action_name ].join separator
311
- end
312
-
313
- # @since 0.1.0
314
- # @api private
315
- def as(action_name)
316
- [ action_name, super() ].join(self.class.named_route_separator).to_sym
317
- end
318
- end
319
-
320
- # Collection action
321
- # It implements #member within a #resource block.
322
- #
323
- # @api private
324
- # @since 0.1.0
325
- # @see Hanami::Router#resource
326
- class MemberAction < CollectionAction
327
- end
328
-
329
- # Implementation of common methods for concrete member actions
330
- #
331
- # @api private
332
- # @since 0.1.0
333
- module DefaultMemberAction
334
- private
335
- # @since 0.1.0
336
- # @api private
337
- def path
338
- rest_path.join(action_name)
339
- end
340
-
341
- # @since 0.1.0
342
- # @api private
343
- def as
344
- [ action_name, super ].join(self.class.named_route_separator).to_sym
345
- end
346
- end
347
-
348
- # New action
349
- #
350
- # @api private
351
- # @since 0.1.0
352
- # @see Hanami::Router#resource
353
- class New < Action
354
- include DefaultMemberAction
355
- end
356
-
357
- # Create action
358
- #
359
- # @api private
360
- # @since 0.1.0
361
- # @see Hanami::Router#resource
362
- class Create < Action
363
- self.verb = :post
364
- end
365
-
366
- # Show action
367
- #
368
- # @api private
369
- # @since 0.1.0
370
- # @see Hanami::Router#resource
371
- class Show < Action
372
- end
373
-
374
- # Edit action
375
- #
376
- # @api private
377
- # @since 0.1.0
378
- # @see Hanami::Router#resource
379
- class Edit < Action
380
- include DefaultMemberAction
381
- end
382
-
383
- # Update action
384
- #
385
- # @api private
386
- # @since 0.1.0
387
- # @see Hanami::Router#resource
388
- class Update < Action
389
- self.verb = :patch
390
- end
391
-
392
- # Destroy action
393
- #
394
- # @api private
395
- # @since 0.1.0
396
- # @see Hanami::Router#resource
397
- class Destroy < Action
398
- self.verb = :delete
399
- end
400
- end
401
- end
402
- end