hanami-router 1.3.1 → 2.0.0.alpha4
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 +44 -0
- data/LICENSE.md +1 -1
- data/README.md +97 -443
- data/hanami-router.gemspec +23 -19
- data/lib/hanami/middleware/body_parser.rb +21 -15
- data/lib/hanami/middleware/body_parser/class_interface.rb +62 -56
- data/lib/hanami/middleware/body_parser/errors.rb +7 -4
- data/lib/hanami/middleware/body_parser/json_parser.rb +9 -7
- data/lib/hanami/middleware/body_parser/parser.rb +58 -0
- data/lib/hanami/middleware/error.rb +16 -0
- data/lib/hanami/router.rb +548 -957
- data/lib/hanami/router/block.rb +88 -0
- data/lib/hanami/router/error.rb +67 -0
- data/lib/hanami/router/node.rb +91 -0
- data/lib/hanami/router/params.rb +35 -0
- data/lib/hanami/router/prefix.rb +67 -0
- data/lib/hanami/router/recognized_route.rb +92 -0
- data/lib/hanami/router/redirect.rb +28 -0
- data/lib/hanami/router/segment.rb +19 -0
- data/lib/hanami/router/trie.rb +63 -0
- data/lib/hanami/router/url_helpers.rb +40 -0
- data/lib/hanami/router/version.rb +4 -1
- metadata +61 -41
- data/lib/hanami-router.rb +0 -1
- data/lib/hanami/routing/endpoint.rb +0 -195
- data/lib/hanami/routing/endpoint_resolver.rb +0 -238
- data/lib/hanami/routing/error.rb +0 -7
- data/lib/hanami/routing/force_ssl.rb +0 -212
- data/lib/hanami/routing/http_router.rb +0 -220
- data/lib/hanami/routing/http_router_monkey_patch.rb +0 -38
- data/lib/hanami/routing/namespace.rb +0 -98
- data/lib/hanami/routing/parsers.rb +0 -113
- data/lib/hanami/routing/parsing/json_parser.rb +0 -33
- data/lib/hanami/routing/parsing/parser.rb +0 -61
- data/lib/hanami/routing/recognized_route.rb +0 -219
- data/lib/hanami/routing/resource.rb +0 -119
- data/lib/hanami/routing/resource/action.rb +0 -402
- data/lib/hanami/routing/resource/nested.rb +0 -41
- data/lib/hanami/routing/resource/options.rb +0 -74
- data/lib/hanami/routing/resources.rb +0 -48
- data/lib/hanami/routing/resources/action.rb +0 -156
- data/lib/hanami/routing/route.rb +0 -71
- 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
|