hanami-router 2.0.0.alpha1 → 2.0.0.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +11 -401
- data/hanami-router.gemspec +2 -4
- data/lib/hanami/middleware/body_parser.rb +2 -2
- data/lib/hanami/middleware/body_parser/class_interface.rb +10 -4
- data/lib/hanami/middleware/body_parser/json_parser.rb +4 -4
- data/lib/hanami/router.rb +525 -1040
- data/lib/hanami/router/block.rb +88 -0
- data/lib/hanami/router/error.rb +67 -0
- data/lib/hanami/router/node.rb +93 -0
- data/lib/hanami/router/params.rb +35 -0
- data/lib/hanami/router/prefix.rb +65 -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 +2 -1
- metadata +17 -48
- data/lib/hanami/routing.rb +0 -193
- data/lib/hanami/routing/endpoint.rb +0 -213
- data/lib/hanami/routing/endpoint_resolver.rb +0 -242
- data/lib/hanami/routing/prefix.rb +0 -102
- data/lib/hanami/routing/recognized_route.rb +0 -233
- data/lib/hanami/routing/resource.rb +0 -121
- data/lib/hanami/routing/resource/action.rb +0 -427
- data/lib/hanami/routing/resource/nested.rb +0 -44
- data/lib/hanami/routing/resource/options.rb +0 -76
- data/lib/hanami/routing/resources.rb +0 -50
- data/lib/hanami/routing/resources/action.rb +0 -161
- data/lib/hanami/routing/routes_inspector.rb +0 -223
- data/lib/hanami/routing/scope.rb +0 -112
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hanami
|
4
|
-
module Routing
|
5
|
-
class Resource
|
6
|
-
# Options for RESTFul resource(s)
|
7
|
-
#
|
8
|
-
# @api private
|
9
|
-
# @since 0.1.0
|
10
|
-
#
|
11
|
-
# @see Hanami::Router#resource
|
12
|
-
# @see Hanami::Router#resources
|
13
|
-
class Options
|
14
|
-
# @api private
|
15
|
-
# @since 0.1.0
|
16
|
-
attr_reader :actions
|
17
|
-
|
18
|
-
# Initialize the options for:
|
19
|
-
# * Hanami::Router#resource
|
20
|
-
# * Hanami::Router#resources
|
21
|
-
#
|
22
|
-
# @param actions [Array<Symbol>] the name of the actions
|
23
|
-
# @param options [Hash]
|
24
|
-
# @option options [Hash] :only white list of the default actions
|
25
|
-
# @option options [Hash] :except black list of the default actions
|
26
|
-
# @option options [String] :controller namespace for an actions
|
27
|
-
#
|
28
|
-
# @api private
|
29
|
-
# @since 0.1.0
|
30
|
-
#
|
31
|
-
# @see Hanami::Routing::Resource
|
32
|
-
# @see Hanami::Routing::Resources
|
33
|
-
#
|
34
|
-
# @example
|
35
|
-
# require 'hanami/router'
|
36
|
-
#
|
37
|
-
# Hanami::Router.new do
|
38
|
-
# resources 'articles', only: [:index]
|
39
|
-
# resource 'profile', except: [:new, :create, :destroy]
|
40
|
-
# end
|
41
|
-
def initialize(actions, options = {})
|
42
|
-
only = Array(options.delete(:only) || actions)
|
43
|
-
except = Array(options.delete(:except))
|
44
|
-
@actions = (actions & only) - except
|
45
|
-
|
46
|
-
@options = options
|
47
|
-
end
|
48
|
-
|
49
|
-
# Return the option for the given key
|
50
|
-
#
|
51
|
-
# @param key [Symbol] the key that should be searched
|
52
|
-
#
|
53
|
-
# @return [Object,nil] returns the object associated to the given key
|
54
|
-
# or nil, if missing.
|
55
|
-
#
|
56
|
-
# @api private
|
57
|
-
# @since 0.1.1
|
58
|
-
def [](key)
|
59
|
-
@options[key]
|
60
|
-
end
|
61
|
-
|
62
|
-
# Merge the current options with the given hash, without mutating self.
|
63
|
-
#
|
64
|
-
# @param hash [Hash] the hash to be merged
|
65
|
-
#
|
66
|
-
# @return [Hash] the result of the merging operation
|
67
|
-
#
|
68
|
-
# @api private
|
69
|
-
# @since 0.1.1
|
70
|
-
def merge(hash)
|
71
|
-
@options.merge(hash)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "hanami/routing/resource"
|
4
|
-
require "hanami/routing/resources/action"
|
5
|
-
|
6
|
-
module Hanami
|
7
|
-
module Routing
|
8
|
-
# Set of RESTful resources routes
|
9
|
-
# Implementation of Hanami::Router#resources
|
10
|
-
#
|
11
|
-
# @since 0.1.0
|
12
|
-
#
|
13
|
-
# @api private
|
14
|
-
#
|
15
|
-
# @see Hanami::Router#resources
|
16
|
-
class Resources < Resource
|
17
|
-
# Set of default routes
|
18
|
-
#
|
19
|
-
# @api private
|
20
|
-
# @since 0.1.0
|
21
|
-
self.actions = %i[index new create show edit update destroy]
|
22
|
-
|
23
|
-
# Action class
|
24
|
-
#
|
25
|
-
# @api private
|
26
|
-
# @since 0.1.0
|
27
|
-
self.action = Resources::Action
|
28
|
-
|
29
|
-
# Member action class
|
30
|
-
#
|
31
|
-
# @api private
|
32
|
-
# @since 0.1.0
|
33
|
-
self.member = Resources::MemberAction
|
34
|
-
|
35
|
-
# Collection action class
|
36
|
-
#
|
37
|
-
# @api private
|
38
|
-
# @since 0.1.0
|
39
|
-
self.collection = Resources::CollectionAction
|
40
|
-
|
41
|
-
# Return wildcard param between separators
|
42
|
-
#
|
43
|
-
# @api private
|
44
|
-
# @since 0.4.0
|
45
|
-
def wildcard_param(route_param = nil)
|
46
|
-
"/:#{@router.inflector.singularize(route_param)}_id/"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,161 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "hanami/utils/path_prefix"
|
4
|
-
require "hanami/routing/resource"
|
5
|
-
|
6
|
-
module Hanami
|
7
|
-
module Routing
|
8
|
-
class Resources < Resource
|
9
|
-
# Action for RESTful resources
|
10
|
-
#
|
11
|
-
# @since 0.1.0
|
12
|
-
#
|
13
|
-
# @api private
|
14
|
-
#
|
15
|
-
# @see Hanami::Router#resources
|
16
|
-
class Action < Resource::Action
|
17
|
-
# Ruby namespace where lookup for default subclasses.
|
18
|
-
#
|
19
|
-
# @api private
|
20
|
-
# @since 0.1.0
|
21
|
-
self.namespace = Resources
|
22
|
-
|
23
|
-
# Id route variable
|
24
|
-
#
|
25
|
-
# @since 0.2.0
|
26
|
-
# @api private
|
27
|
-
class_attribute :identifier
|
28
|
-
self.identifier = ":id"
|
29
|
-
end
|
30
|
-
|
31
|
-
# Pluralize concrete actions
|
32
|
-
#
|
33
|
-
# @api private
|
34
|
-
# @since 0.4.0
|
35
|
-
module PluralizedAction
|
36
|
-
private
|
37
|
-
|
38
|
-
# The name of the RESTful action.
|
39
|
-
#
|
40
|
-
# @api private
|
41
|
-
# @since 0.4.0
|
42
|
-
def as
|
43
|
-
@router.inflector.pluralize(super).to_sym
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Collection action
|
48
|
-
# It implements #collection within a #resources block.
|
49
|
-
#
|
50
|
-
# @api private
|
51
|
-
# @since 0.1.0
|
52
|
-
# @see Hanami::Router#resources
|
53
|
-
class CollectionAction < Resource::CollectionAction
|
54
|
-
def as(action_name)
|
55
|
-
@router.inflector.pluralize(super(action_name)).to_sym
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Member action
|
60
|
-
# It implements #member within a #resources block.
|
61
|
-
#
|
62
|
-
# @api private
|
63
|
-
# @since 0.1.0
|
64
|
-
# @see Hanami::Router#resources
|
65
|
-
class MemberAction < Resource::MemberAction
|
66
|
-
private
|
67
|
-
|
68
|
-
# @since 0.1.0
|
69
|
-
# @api private
|
70
|
-
def path(action_name)
|
71
|
-
rest_path.join(Action.identifier, action_name)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Implementation of common methods for concrete member actions
|
76
|
-
#
|
77
|
-
# @api private
|
78
|
-
# @since 0.1.0
|
79
|
-
module DefaultMemberAction
|
80
|
-
private
|
81
|
-
|
82
|
-
# @since 0.1.0
|
83
|
-
# @api private
|
84
|
-
def path
|
85
|
-
rest_path.join(Action.identifier)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Index action
|
90
|
-
#
|
91
|
-
# @api private
|
92
|
-
# @since 0.1.0
|
93
|
-
# @see Hanami::Router#resources
|
94
|
-
class Index < Action
|
95
|
-
include PluralizedAction
|
96
|
-
self.verb = :get
|
97
|
-
end
|
98
|
-
|
99
|
-
# New action
|
100
|
-
#
|
101
|
-
# @api private
|
102
|
-
# @since 0.1.0
|
103
|
-
# @see Hanami::Router#resources
|
104
|
-
class New < Resource::New
|
105
|
-
end
|
106
|
-
|
107
|
-
# Create action
|
108
|
-
#
|
109
|
-
# @api private
|
110
|
-
# @since 0.1.0
|
111
|
-
# @see Hanami::Router#resources
|
112
|
-
class Create < Resource::Create
|
113
|
-
include PluralizedAction
|
114
|
-
end
|
115
|
-
|
116
|
-
# Show action
|
117
|
-
#
|
118
|
-
# @api private
|
119
|
-
# @since 0.1.0
|
120
|
-
# @see Hanami::Router#resources
|
121
|
-
class Show < Resource::Show
|
122
|
-
include DefaultMemberAction
|
123
|
-
end
|
124
|
-
|
125
|
-
# Edit action
|
126
|
-
#
|
127
|
-
# @api private
|
128
|
-
# @since 0.1.0
|
129
|
-
# @see Hanami::Router#resources
|
130
|
-
class Edit < Resource::Edit
|
131
|
-
include DefaultMemberAction
|
132
|
-
|
133
|
-
private
|
134
|
-
|
135
|
-
# @since 0.1.0
|
136
|
-
# @api private
|
137
|
-
def path
|
138
|
-
super.join(action_name)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Update action
|
143
|
-
#
|
144
|
-
# @api private
|
145
|
-
# @since 0.1.0
|
146
|
-
# @see Hanami::Router#resources
|
147
|
-
class Update < Resource::Update
|
148
|
-
include DefaultMemberAction
|
149
|
-
end
|
150
|
-
|
151
|
-
# Destroy action
|
152
|
-
#
|
153
|
-
# @api private
|
154
|
-
# @since 0.1.0
|
155
|
-
# @see Hanami::Router#resources
|
156
|
-
class Destroy < Resource::Destroy
|
157
|
-
include DefaultMemberAction
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
@@ -1,223 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "hanami/utils/path_prefix"
|
4
|
-
|
5
|
-
module Hanami
|
6
|
-
module Routing
|
7
|
-
# Routes inspector
|
8
|
-
#
|
9
|
-
# @since 0.2.0
|
10
|
-
class RoutesInspector
|
11
|
-
# Default route formatter
|
12
|
-
#
|
13
|
-
# @since 0.2.0
|
14
|
-
# @api private
|
15
|
-
FORMATTER = "%<name>20s %<methods>-10s %<path>-30s %<endpoint>-30s\n"
|
16
|
-
|
17
|
-
# Default HTTP methods separator
|
18
|
-
#
|
19
|
-
# @since 0.2.0
|
20
|
-
# @api private
|
21
|
-
HTTP_METHODS_SEPARATOR = ", "
|
22
|
-
|
23
|
-
# Default inspector header hash values
|
24
|
-
#
|
25
|
-
# @since 0.5.0
|
26
|
-
# @api private
|
27
|
-
INSPECTOR_HEADER_HASH = ::Hash[
|
28
|
-
name: "Name",
|
29
|
-
methods: "Method",
|
30
|
-
path: "Path",
|
31
|
-
endpoint: "Action"
|
32
|
-
].freeze
|
33
|
-
|
34
|
-
# Default inspector header name values
|
35
|
-
#
|
36
|
-
# @since 0.5.0
|
37
|
-
# @api private
|
38
|
-
INSPECTOR_HEADER_NAME = "Name"
|
39
|
-
|
40
|
-
# Empty line string
|
41
|
-
#
|
42
|
-
# @since 0.5.0
|
43
|
-
# @api private
|
44
|
-
EMPTY_LINE = "\n"
|
45
|
-
|
46
|
-
# Instantiate a new inspector
|
47
|
-
#
|
48
|
-
# @return [Hanami::Routing::RoutesInspector] the new instance
|
49
|
-
#
|
50
|
-
# @since 0.2.0
|
51
|
-
# @api private
|
52
|
-
def initialize(routes, prefix)
|
53
|
-
@routes = routes
|
54
|
-
@prefix = prefix
|
55
|
-
end
|
56
|
-
|
57
|
-
# Return a formatted string that describes all the routes
|
58
|
-
#
|
59
|
-
# @param formatter [String] the optional formatter for a route
|
60
|
-
# @param base_path [String] the base path of a nested route
|
61
|
-
#
|
62
|
-
# @return [String] routes pretty print
|
63
|
-
#
|
64
|
-
# @since 0.2.0
|
65
|
-
# @api private
|
66
|
-
#
|
67
|
-
# @see Hanami::Routing::RoutesInspector::FORMATTER
|
68
|
-
#
|
69
|
-
# @example Default formatter
|
70
|
-
# require 'hanami/router'
|
71
|
-
#
|
72
|
-
# router = Hanami::Router.new do
|
73
|
-
# get '/', to: 'home#index'
|
74
|
-
# get '/login', to: 'sessions#new', as: :login
|
75
|
-
# post '/login', to: 'sessions#create'
|
76
|
-
# delete '/logout', to: 'sessions#destroy', as: :logout
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# puts router.inspector.to_s
|
80
|
-
# # => Name Method Path Action
|
81
|
-
#
|
82
|
-
# GET, HEAD / Home::Index
|
83
|
-
# login GET, HEAD /login Sessions::New
|
84
|
-
# POST /login Sessions::Create
|
85
|
-
# logout GET, HEAD /logout Sessions::Destroy
|
86
|
-
#
|
87
|
-
# @example Custom formatter
|
88
|
-
# require 'hanami/router'
|
89
|
-
#
|
90
|
-
# router = Hanami::Router.new do
|
91
|
-
# get '/', to: 'home#index'
|
92
|
-
# get '/login', to: 'sessions#new', as: :login
|
93
|
-
# post '/login', to: 'sessions#create'
|
94
|
-
# delete '/logout', to: 'sessions#destroy', as: :logout
|
95
|
-
# end
|
96
|
-
#
|
97
|
-
# formatter = "| %{methods} | %{name} | %{path} | %{endpoint} |\n"
|
98
|
-
#
|
99
|
-
# puts router.inspector.to_s(formatter)
|
100
|
-
# # => | Method | Name | Path | Action |
|
101
|
-
#
|
102
|
-
# | GET, HEAD | | / | Home::Index |
|
103
|
-
# | GET, HEAD | login | /login | Sessions::New |
|
104
|
-
# | POST | | /login | Sessions::Create |
|
105
|
-
# | GET, HEAD | logout | /logout | Sessions::Destroy |
|
106
|
-
#
|
107
|
-
# @example Nested routes
|
108
|
-
# require 'hanami/router'
|
109
|
-
#
|
110
|
-
# class AdminHanamiApp
|
111
|
-
# def call(env)
|
112
|
-
# end
|
113
|
-
# def routes
|
114
|
-
# Hanami::Router.new {
|
115
|
-
# get '/home', to: 'home#index'
|
116
|
-
# }
|
117
|
-
# end
|
118
|
-
# end
|
119
|
-
#
|
120
|
-
# router = Hanami::Router.new {
|
121
|
-
# get '/fakeroute', to: 'fake#index'
|
122
|
-
# mount AdminHanamiApp, at: '/admin'
|
123
|
-
# mount Hanami::Router.new {
|
124
|
-
# get '/posts', to: 'posts#index'
|
125
|
-
# mount Hanami::Router.new {
|
126
|
-
# get '/comments', to: 'comments#index'
|
127
|
-
# }, at: '/second_mount'
|
128
|
-
# }, at: '/api'
|
129
|
-
# }
|
130
|
-
#
|
131
|
-
# formatter = "| %{methods} | %{name} | %{path} | %{endpoint} |\n"
|
132
|
-
#
|
133
|
-
# puts router.inspector.to_s(formatter)
|
134
|
-
# # => | Method | Name | Path | Action |
|
135
|
-
#
|
136
|
-
# | GET, HEAD | | /fakeroute | Fake::Index |
|
137
|
-
# | GET, HEAD | | /admin/home | Home::Index |
|
138
|
-
# | GET, HEAD | | /api/posts | Posts::Index |
|
139
|
-
# | GET, HEAD | | /api/second_mount/comments | Comments::Index |
|
140
|
-
def to_s(formatter = FORMATTER, base_path = prefix)
|
141
|
-
base_path = Utils::PathPrefix.new(base_path)
|
142
|
-
|
143
|
-
inspect_routes(formatter, base_path)
|
144
|
-
.insert(0, formatter % INSPECTOR_HEADER_HASH + EMPTY_LINE)
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns a string representation of routes
|
148
|
-
#
|
149
|
-
# @param formatter [String] the template for the output
|
150
|
-
# @param base_path [Hanami::Utils::PathPrefix] the base path
|
151
|
-
#
|
152
|
-
# @return [String] serialized routes from router
|
153
|
-
#
|
154
|
-
# @since 0.5.1
|
155
|
-
# @api private
|
156
|
-
#
|
157
|
-
# @see Hanami::Routing::RoutesInspector#FORMATTER
|
158
|
-
# @see Hanami::Routing::RoutesInspector#to_s
|
159
|
-
def inspect_routes(formatter, base_path)
|
160
|
-
result = ""
|
161
|
-
|
162
|
-
# TODO: refactoring: replace conditional with polymorphism
|
163
|
-
# We're exposing too much knowledge from Routing::Route:
|
164
|
-
# #path_for_generation and #base_path
|
165
|
-
@routes.each do |route|
|
166
|
-
result << if (router = route.nested_router)
|
167
|
-
inspect_router(formatter, router, route, base_path)
|
168
|
-
else
|
169
|
-
inspect_route(formatter, route, base_path)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
result
|
174
|
-
end
|
175
|
-
|
176
|
-
private
|
177
|
-
|
178
|
-
# @since 0.8.0
|
179
|
-
# @api private
|
180
|
-
attr_reader :prefix
|
181
|
-
|
182
|
-
# Returns a string representation of the given route
|
183
|
-
#
|
184
|
-
# @param formatter [String] the template for the output
|
185
|
-
# @param route [Hanami::Routing::Route] a route
|
186
|
-
# @param base_path [Hanami::Utils::PathPrefix] the base path
|
187
|
-
#
|
188
|
-
# @return [String] serialized route
|
189
|
-
#
|
190
|
-
# @since 0.2.0
|
191
|
-
# @api private
|
192
|
-
#
|
193
|
-
# @see Hanami::Routing::RoutesInspector#FORMATTER
|
194
|
-
# @see Hanami::Routing::RoutesInspector#to_s
|
195
|
-
def inspect_route(formatter, route, base_path)
|
196
|
-
formatter % Hash[
|
197
|
-
name: route.name,
|
198
|
-
methods: route.request_methods.to_a.join(HTTP_METHODS_SEPARATOR),
|
199
|
-
path: base_path.join(route.path_for_generation),
|
200
|
-
endpoint: route.dest.inspect
|
201
|
-
]
|
202
|
-
end
|
203
|
-
|
204
|
-
# Returns a string representation of the given router
|
205
|
-
#
|
206
|
-
# @param formatter [String] the template for the output
|
207
|
-
# @param router [Hanami::Router] a router
|
208
|
-
# @param route [Hanami::Routing::Route] a route
|
209
|
-
# @param base_path [Hanami::Utils::PathPrefix] the base path
|
210
|
-
#
|
211
|
-
# @return [String] serialized routes from router
|
212
|
-
#
|
213
|
-
# @since 0.2.0
|
214
|
-
# @api private
|
215
|
-
#
|
216
|
-
# @see Hanami::Routing::RoutesInspector#FORMATTER
|
217
|
-
# @see Hanami::Routing::RoutesInspector#to_s
|
218
|
-
def inspect_router(formatter, router, route, base_path)
|
219
|
-
router.inspector.inspect_routes(formatter, base_path.join(route.path_for_generation))
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|