lotus-router 0.1.1 → 0.2.0
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 +49 -42
- data/README.md +55 -30
- data/lib/lotus/router.rb +234 -126
- data/lib/lotus/router/version.rb +1 -1
- data/lib/lotus/routing/endpoint.rb +38 -2
- data/lib/lotus/routing/endpoint_resolver.rb +24 -73
- data/lib/lotus/routing/http_router.rb +8 -1
- data/lib/lotus/routing/namespace.rb +3 -3
- data/lib/lotus/routing/parsers.rb +71 -0
- data/lib/lotus/routing/parsing/json_parser.rb +17 -0
- data/lib/lotus/routing/parsing/parser.rb +43 -0
- data/lib/lotus/routing/resource.rb +4 -4
- data/lib/lotus/routing/resource/action.rb +34 -36
- data/lib/lotus/routing/resources/action.rb +13 -6
- data/lib/lotus/routing/route.rb +9 -0
- data/lib/lotus/routing/routes_inspector.rb +168 -0
- data/lotus-router.gemspec +5 -4
- metadata +19 -9
@@ -29,6 +29,13 @@ module Lotus
|
|
29
29
|
class_attribute :verb
|
30
30
|
self.verb = :get
|
31
31
|
|
32
|
+
# Separator for named routes
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.2.0
|
36
|
+
class_attribute :named_route_separator
|
37
|
+
self.named_route_separator = '_'.freeze
|
38
|
+
|
32
39
|
# Generate an action for the given router
|
33
40
|
#
|
34
41
|
# @param router [Lotus::Router]
|
@@ -85,12 +92,12 @@ module Lotus
|
|
85
92
|
@options[:name]
|
86
93
|
end
|
87
94
|
|
88
|
-
#
|
95
|
+
# Namespace
|
89
96
|
#
|
90
97
|
# @api private
|
91
|
-
# @since 0.
|
92
|
-
def
|
93
|
-
@
|
98
|
+
# @since 0.2.0
|
99
|
+
def namespace
|
100
|
+
@namespace ||= Utils::PathPrefix.new @options[:namespace]
|
94
101
|
end
|
95
102
|
|
96
103
|
private
|
@@ -118,7 +125,7 @@ module Lotus
|
|
118
125
|
self.class.verb
|
119
126
|
end
|
120
127
|
|
121
|
-
# The
|
128
|
+
# The namespaced URL relative path
|
122
129
|
#
|
123
130
|
# @example
|
124
131
|
# require 'lotus/router'
|
@@ -126,7 +133,7 @@ module Lotus
|
|
126
133
|
# Lotus::Router.new do
|
127
134
|
# resources 'flowers'
|
128
135
|
#
|
129
|
-
#
|
136
|
+
# namespace 'animals' do
|
130
137
|
# resources 'mammals'
|
131
138
|
# end
|
132
139
|
# end
|
@@ -137,7 +144,7 @@ module Lotus
|
|
137
144
|
# @api private
|
138
145
|
# @since 0.1.0
|
139
146
|
def path
|
140
|
-
|
147
|
+
rest_path
|
141
148
|
end
|
142
149
|
|
143
150
|
# The URL relative path
|
@@ -150,10 +157,10 @@ module Lotus
|
|
150
157
|
# @api private
|
151
158
|
# @since 0.1.0
|
152
159
|
def rest_path
|
153
|
-
|
160
|
+
namespace.join(resource_name)
|
154
161
|
end
|
155
162
|
|
156
|
-
# The
|
163
|
+
# The namespaced name of the action within the whole context of the router.
|
157
164
|
#
|
158
165
|
# @example
|
159
166
|
# require 'lotus/router'
|
@@ -161,7 +168,7 @@ module Lotus
|
|
161
168
|
# Lotus::Router.new do
|
162
169
|
# resources 'flowers'
|
163
170
|
#
|
164
|
-
#
|
171
|
+
# namespace 'animals' do
|
165
172
|
# resources 'mammals'
|
166
173
|
# end
|
167
174
|
# end
|
@@ -172,19 +179,7 @@ module Lotus
|
|
172
179
|
# @api private
|
173
180
|
# @since 0.1.0
|
174
181
|
def as
|
175
|
-
|
176
|
-
end
|
177
|
-
|
178
|
-
# The name of the action within the whole context of the router.
|
179
|
-
#
|
180
|
-
# @example
|
181
|
-
# :flowers
|
182
|
-
# :new_flowers
|
183
|
-
#
|
184
|
-
# @api private
|
185
|
-
# @since 0.1.0
|
186
|
-
def named_route
|
187
|
-
resource_name
|
182
|
+
namespace.relative_join(resource_name, self.class.named_route_separator).to_sym
|
188
183
|
end
|
189
184
|
|
190
185
|
# The name of the RESTful action.
|
@@ -240,22 +235,25 @@ module Lotus
|
|
240
235
|
end
|
241
236
|
|
242
237
|
protected
|
243
|
-
def method_missing(m, *args
|
244
|
-
verb
|
245
|
-
|
238
|
+
def method_missing(m, *args)
|
239
|
+
verb = m
|
240
|
+
action_name = Utils::PathPrefix.new(args.first).relative_join(nil)
|
241
|
+
|
242
|
+
@router.__send__ verb, path(action_name),
|
243
|
+
to: endpoint(action_name), as: as(action_name)
|
246
244
|
end
|
247
245
|
|
248
246
|
private
|
249
|
-
def path(
|
250
|
-
|
247
|
+
def path(action_name)
|
248
|
+
rest_path.join(action_name)
|
251
249
|
end
|
252
250
|
|
253
|
-
def endpoint(
|
254
|
-
[ resource_name,
|
251
|
+
def endpoint(action_name)
|
252
|
+
[ resource_name, action_name ].join separator
|
255
253
|
end
|
256
254
|
|
257
|
-
def as(
|
258
|
-
|
255
|
+
def as(action_name)
|
256
|
+
[ action_name, super() ].join(self.class.named_route_separator).to_sym
|
259
257
|
end
|
260
258
|
end
|
261
259
|
|
@@ -274,12 +272,12 @@ module Lotus
|
|
274
272
|
# @since 0.1.0
|
275
273
|
module DefaultMemberAction
|
276
274
|
private
|
277
|
-
def
|
278
|
-
|
275
|
+
def path
|
276
|
+
rest_path.join(action_name)
|
279
277
|
end
|
280
278
|
|
281
|
-
def
|
282
|
-
|
279
|
+
def as
|
280
|
+
[ action_name, super ].join(self.class.named_route_separator).to_sym
|
283
281
|
end
|
284
282
|
end
|
285
283
|
|
@@ -18,6 +18,13 @@ module Lotus
|
|
18
18
|
# @api private
|
19
19
|
# @since 0.1.0
|
20
20
|
self.namespace = Resources
|
21
|
+
|
22
|
+
# Id route variable
|
23
|
+
#
|
24
|
+
# @since 0.2.0
|
25
|
+
# @api private
|
26
|
+
class_attribute :identifier
|
27
|
+
self.identifier = ':id'.freeze
|
21
28
|
end
|
22
29
|
|
23
30
|
# Collection action
|
@@ -37,8 +44,8 @@ module Lotus
|
|
37
44
|
# @see Lotus::Router#resources
|
38
45
|
class MemberAction < Resource::MemberAction
|
39
46
|
private
|
40
|
-
def path(
|
41
|
-
|
47
|
+
def path(action_name)
|
48
|
+
rest_path.join(Action.identifier, action_name)
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
@@ -48,8 +55,8 @@ module Lotus
|
|
48
55
|
# @since 0.1.0
|
49
56
|
module DefaultMemberAction
|
50
57
|
private
|
51
|
-
def
|
52
|
-
|
58
|
+
def path
|
59
|
+
rest_path.join(Action.identifier)
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
@@ -96,8 +103,8 @@ module Lotus
|
|
96
103
|
include DefaultMemberAction
|
97
104
|
|
98
105
|
private
|
99
|
-
def
|
100
|
-
|
106
|
+
def path
|
107
|
+
super.join(action_name)
|
101
108
|
end
|
102
109
|
end
|
103
110
|
|
data/lib/lotus/routing/route.rb
CHANGED
@@ -44,6 +44,15 @@ module Lotus
|
|
44
44
|
self
|
45
45
|
end
|
46
46
|
|
47
|
+
# Introspect the given route to understand if there is a wrapped
|
48
|
+
# Lotus::Router
|
49
|
+
#
|
50
|
+
# @since 0.2.0
|
51
|
+
# @api private
|
52
|
+
def nested_router
|
53
|
+
dest.routes if dest.respond_to?(:routes)
|
54
|
+
end
|
55
|
+
|
47
56
|
private
|
48
57
|
def to=(dest = nil, &blk)
|
49
58
|
self.to dest, &blk
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'lotus/utils/path_prefix'
|
2
|
+
|
3
|
+
module Lotus
|
4
|
+
module Routing
|
5
|
+
# Routes inspector
|
6
|
+
#
|
7
|
+
# @since 0.2.0
|
8
|
+
class RoutesInspector
|
9
|
+
# Default route formatter
|
10
|
+
#
|
11
|
+
# @since 0.2.0
|
12
|
+
# @api private
|
13
|
+
FORMATTER = "%<name>20s %<methods>-10s %<path>-30s %<endpoint>-30s\n".freeze
|
14
|
+
|
15
|
+
# Default HTTP methods separator
|
16
|
+
#
|
17
|
+
# @since 0.2.0
|
18
|
+
# @api private
|
19
|
+
HTTP_METHODS_SEPARATOR = ', '.freeze
|
20
|
+
|
21
|
+
# Instantiate a new inspector
|
22
|
+
#
|
23
|
+
# @return [Lotus::Routing::RoutesInspector] the new instance
|
24
|
+
#
|
25
|
+
# @since 0.2.0
|
26
|
+
# @api private
|
27
|
+
def initialize(routes)
|
28
|
+
@routes = routes
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return a formatted string that describes all the routes
|
32
|
+
#
|
33
|
+
# @param formatter [String] the optional formatter for a route
|
34
|
+
# @param base_path [String] the base path of a nested route
|
35
|
+
#
|
36
|
+
# @return [String] routes pretty print
|
37
|
+
#
|
38
|
+
# @since 0.2.0
|
39
|
+
#
|
40
|
+
# @see Lotus::Routing::RoutesInspector::FORMATTER
|
41
|
+
#
|
42
|
+
# @example Default formatter
|
43
|
+
# require 'lotus/router'
|
44
|
+
#
|
45
|
+
# router = Lotus::Router.new do
|
46
|
+
# get '/', to: 'home#index'
|
47
|
+
# get '/login', to: 'sessions#new', as: :login
|
48
|
+
# post '/login', to: 'sessions#create'
|
49
|
+
# delete '/logout', to: 'sessions#destroy', as: :logout
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# puts router.inspector.to_s
|
53
|
+
# # => GET, HEAD / Home::Index
|
54
|
+
# login GET, HEAD /login Sessions::New
|
55
|
+
# POST /login Sessions::Create
|
56
|
+
# logout GET, HEAD /logout Sessions::Destroy
|
57
|
+
#
|
58
|
+
# @example Custom formatter
|
59
|
+
# require 'lotus/router'
|
60
|
+
#
|
61
|
+
# router = Lotus::Router.new do
|
62
|
+
# get '/', to: 'home#index'
|
63
|
+
# get '/login', to: 'sessions#new', as: :login
|
64
|
+
# post '/login', to: 'sessions#create'
|
65
|
+
# delete '/logout', to: 'sessions#destroy', as: :logout
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# formatter = "| %{methods} | %{name} | %{path} | %{endpoint} |\n"
|
69
|
+
#
|
70
|
+
# puts router.inspector.to_s(formatter)
|
71
|
+
# # => | GET, HEAD | | / | Home::Index |
|
72
|
+
# | GET, HEAD | login | /login | Sessions::New |
|
73
|
+
# | POST | | /login | Sessions::Create |
|
74
|
+
# | GET, HEAD | logout | /logout | Sessions::Destroy |
|
75
|
+
#
|
76
|
+
# @example Nested routes
|
77
|
+
# require 'lotus/router'
|
78
|
+
#
|
79
|
+
# class AdminLotusApp
|
80
|
+
# def call(env)
|
81
|
+
# end
|
82
|
+
# def routes
|
83
|
+
# Lotus::Router.new {
|
84
|
+
# get '/home', to: 'home#index'
|
85
|
+
# }
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# router = Lotus::Router.new {
|
90
|
+
# get '/fakeroute', to: 'fake#index'
|
91
|
+
# mount AdminLotusApp, at: '/admin'
|
92
|
+
# mount Lotus::Router.new {
|
93
|
+
# get '/posts', to: 'posts#index'
|
94
|
+
# mount Lotus::Router.new {
|
95
|
+
# get '/comments', to: 'comments#index'
|
96
|
+
# }, at: '/second_mount'
|
97
|
+
# }, at: '/api'
|
98
|
+
# }
|
99
|
+
#
|
100
|
+
# formatter = "| %{methods} | %{name} | %{path} | %{endpoint} |\n"
|
101
|
+
#
|
102
|
+
# puts router.inspector.to_s(formatter)
|
103
|
+
# # => | GET, HEAD | | /fakeroute | Fake::Index |
|
104
|
+
# | GET, HEAD | | /admin/home | Home::Index |
|
105
|
+
# | GET, HEAD | | /api/posts | Posts::Index |
|
106
|
+
# | GET, HEAD | | /api/second_mount/comments | Comments::Index |
|
107
|
+
def to_s(formatter = FORMATTER, base_path = nil)
|
108
|
+
base_path = Utils::PathPrefix.new(base_path)
|
109
|
+
result = ''
|
110
|
+
|
111
|
+
# TODO refactoring: replace conditional with polymorphism
|
112
|
+
# We're exposing too much knowledge from Routing::Route:
|
113
|
+
# #path_for_generation and #base_path
|
114
|
+
@routes.each do |route|
|
115
|
+
result << if router = route.nested_router
|
116
|
+
inspect_router(formatter, router, route, base_path)
|
117
|
+
else
|
118
|
+
inspect_route(formatter, route, base_path)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
result
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
# Returns a string representation of the given route
|
128
|
+
#
|
129
|
+
# @param formatter [String] the template for the output
|
130
|
+
# @param route [Lotus::Routing::Route] a route
|
131
|
+
# @param base_path [Lotus::Utils::PathPrefix] the base path
|
132
|
+
#
|
133
|
+
# @return [String] serialized route
|
134
|
+
#
|
135
|
+
# @since 0.2.0
|
136
|
+
# @api private
|
137
|
+
#
|
138
|
+
# @see Lotus::Routing::RoutesInspector#FORMATTER
|
139
|
+
# @see Lotus::Routing::RoutesInspector#to_s
|
140
|
+
def inspect_route(formatter, route, base_path)
|
141
|
+
formatter % Hash[
|
142
|
+
name: route.name,
|
143
|
+
methods: route.request_methods.to_a.join(HTTP_METHODS_SEPARATOR),
|
144
|
+
path: base_path.join(route.path_for_generation),
|
145
|
+
endpoint: route.dest.inspect
|
146
|
+
]
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns a string representation of the given router
|
150
|
+
#
|
151
|
+
# @param formatter [String] the template for the output
|
152
|
+
# @param router [Lotus::Router] a router
|
153
|
+
# @param route [Lotus::Routing::Route] a route
|
154
|
+
# @param base_path [Lotus::Utils::PathPrefix] the base path
|
155
|
+
#
|
156
|
+
# @return [String] serialized routes from router
|
157
|
+
#
|
158
|
+
# @since 0.2.0
|
159
|
+
# @api private
|
160
|
+
#
|
161
|
+
# @see Lotus::Routing::RoutesInspector#FORMATTER
|
162
|
+
# @see Lotus::Routing::RoutesInspector#to_s
|
163
|
+
def inspect_router(formatter, router, route, base_path)
|
164
|
+
router.inspector.to_s(formatter, base_path.join(route.path_for_generation))
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/lotus-router.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Lotus::Router::VERSION
|
9
9
|
spec.authors = ['Luca Guidi']
|
10
10
|
spec.email = ['me@lucaguidi.com']
|
11
|
-
spec.description = %q{HTTP
|
12
|
-
spec.summary = %q{
|
11
|
+
spec.description = %q{Rack compatible HTTP router for Ruby}
|
12
|
+
spec.summary = %q{Rack compatible HTTP router for Ruby and Lotus}
|
13
13
|
spec.homepage = 'http://lotusrb.org'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
@@ -17,9 +17,10 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = []
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
|
+
spec.required_ruby_version = '>= 2.0.0'
|
20
21
|
|
21
|
-
spec.add_dependency 'http_router', '~> 0'
|
22
|
-
spec.add_dependency 'lotus-utils', '~> 0'
|
22
|
+
spec.add_dependency 'http_router', '~> 0.11'
|
23
|
+
spec.add_dependency 'lotus-utils', '~> 0.3', '>= 0.3.2'
|
23
24
|
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.5'
|
25
26
|
spec.add_development_dependency 'minitest', '~> 5'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lotus-router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http_router
|
@@ -16,28 +16,34 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '0.11'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '0.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: lotus-utils
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '0.3'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.3.2
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
43
|
+
version: '0.3'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.3.2
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: bundler
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,7 +86,7 @@ dependencies:
|
|
80
86
|
- - "~>"
|
81
87
|
- !ruby/object:Gem::Version
|
82
88
|
version: '10'
|
83
|
-
description: HTTP
|
89
|
+
description: Rack compatible HTTP router for Ruby
|
84
90
|
email:
|
85
91
|
- me@lucaguidi.com
|
86
92
|
executables: []
|
@@ -97,12 +103,16 @@ files:
|
|
97
103
|
- lib/lotus/routing/endpoint_resolver.rb
|
98
104
|
- lib/lotus/routing/http_router.rb
|
99
105
|
- lib/lotus/routing/namespace.rb
|
106
|
+
- lib/lotus/routing/parsers.rb
|
107
|
+
- lib/lotus/routing/parsing/json_parser.rb
|
108
|
+
- lib/lotus/routing/parsing/parser.rb
|
100
109
|
- lib/lotus/routing/resource.rb
|
101
110
|
- lib/lotus/routing/resource/action.rb
|
102
111
|
- lib/lotus/routing/resource/options.rb
|
103
112
|
- lib/lotus/routing/resources.rb
|
104
113
|
- lib/lotus/routing/resources/action.rb
|
105
114
|
- lib/lotus/routing/route.rb
|
115
|
+
- lib/lotus/routing/routes_inspector.rb
|
106
116
|
- lotus-router.gemspec
|
107
117
|
homepage: http://lotusrb.org
|
108
118
|
licenses:
|
@@ -116,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
126
|
requirements:
|
117
127
|
- - ">="
|
118
128
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
129
|
+
version: 2.0.0
|
120
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
131
|
requirements:
|
122
132
|
- - ">="
|
@@ -127,6 +137,6 @@ rubyforge_project:
|
|
127
137
|
rubygems_version: 2.2.2
|
128
138
|
signing_key:
|
129
139
|
specification_version: 4
|
130
|
-
summary:
|
140
|
+
summary: Rack compatible HTTP router for Ruby and Lotus
|
131
141
|
test_files: []
|
132
142
|
has_rdoc:
|