lotus-router 0.0.0 → 0.1.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/.coveralls.yml +2 -0
- data/.gitignore +5 -13
- data/.travis.yml +5 -0
- data/.yardopts +3 -0
- data/Gemfile +10 -3
- data/README.md +470 -6
- data/Rakefile +10 -1
- data/benchmarks/callable +23 -0
- data/benchmarks/named_routes +72 -0
- data/benchmarks/resource +44 -0
- data/benchmarks/resources +58 -0
- data/benchmarks/routes +67 -0
- data/benchmarks/run.sh +11 -0
- data/benchmarks/utils.rb +56 -0
- data/lib/lotus-router.rb +1 -0
- data/lib/lotus/router.rb +752 -3
- data/lib/lotus/router/version.rb +2 -2
- data/lib/lotus/routing/endpoint.rb +114 -0
- data/lib/lotus/routing/endpoint_resolver.rb +251 -0
- data/lib/lotus/routing/http_router.rb +130 -0
- data/lib/lotus/routing/namespace.rb +86 -0
- data/lib/lotus/routing/resource.rb +73 -0
- data/lib/lotus/routing/resource/action.rb +340 -0
- data/lib/lotus/routing/resource/options.rb +48 -0
- data/lib/lotus/routing/resources.rb +40 -0
- data/lib/lotus/routing/resources/action.rb +123 -0
- data/lib/lotus/routing/route.rb +53 -0
- data/lotus-router.gemspec +16 -12
- data/test/fixtures.rb +193 -0
- data/test/integration/client_error_test.rb +16 -0
- data/test/integration/pass_on_response_test.rb +13 -0
- data/test/named_routes_test.rb +123 -0
- data/test/namespace_test.rb +289 -0
- data/test/new_test.rb +67 -0
- data/test/redirect_test.rb +33 -0
- data/test/resource_test.rb +128 -0
- data/test/resources_test.rb +136 -0
- data/test/routing/endpoint_resolver_test.rb +110 -0
- data/test/routing/resource/options_test.rb +36 -0
- data/test/routing_test.rb +99 -0
- data/test/test_helper.rb +32 -0
- data/test/version_test.rb +7 -0
- metadata +102 -10
@@ -0,0 +1,48 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Routing
|
3
|
+
class Resource
|
4
|
+
# Options for RESTFul resource(s)
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
# @see Lotus::Router#resource
|
10
|
+
# @see Lotus::Router#resources
|
11
|
+
class Options < Hash
|
12
|
+
# @api private
|
13
|
+
# @since 0.1.0
|
14
|
+
attr_reader :actions
|
15
|
+
|
16
|
+
# Initialize the options for:
|
17
|
+
# * Lotus::Router#resource
|
18
|
+
# * Lotus::Router#resources
|
19
|
+
#
|
20
|
+
# @param actions [Array<Symbol>] the name of the actions
|
21
|
+
# @param options [Hash]
|
22
|
+
# @option options [Hash] :only white list of the default actions
|
23
|
+
# @option options [Hash] :except black list of the default actions
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @since 0.1.0
|
27
|
+
#
|
28
|
+
# @see Lotus::Routing::Resource
|
29
|
+
# @see Lotus::Routing::Resources
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# require 'lotus/router'
|
33
|
+
#
|
34
|
+
# Lotus::Router.new do
|
35
|
+
# resources 'articles', only: [:index]
|
36
|
+
# resource 'profile', except: [:new, :create, :destroy]
|
37
|
+
# end
|
38
|
+
def initialize(actions, options = {})
|
39
|
+
only = Array(options.delete(:only) || actions)
|
40
|
+
except = Array(options.delete(:except))
|
41
|
+
@actions = ( actions & only ) - except
|
42
|
+
|
43
|
+
merge! options
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'lotus/routing/resource'
|
2
|
+
require 'lotus/routing/resources/action'
|
3
|
+
|
4
|
+
module Lotus
|
5
|
+
module Routing
|
6
|
+
# Set of RESTful resources routes
|
7
|
+
# Implementation of Lotus::Router#resources
|
8
|
+
#
|
9
|
+
# @since 0.1.0
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
# @see Lotus::Router#resources
|
14
|
+
class Resources < Resource
|
15
|
+
# Set of default routes
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
# @since 0.1.0
|
19
|
+
self.actions = [:index, :new, :create, :show, :edit, :update, :destroy]
|
20
|
+
|
21
|
+
# Action class
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
# @since 0.1.0
|
25
|
+
self.action = Resources::Action
|
26
|
+
|
27
|
+
# Member action class
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
self.member = Resources::MemberAction
|
32
|
+
|
33
|
+
# Collection action class
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
# @since 0.1.0
|
37
|
+
self.collection = Resources::CollectionAction
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'lotus/utils/string'
|
2
|
+
require 'lotus/utils/path_prefix'
|
3
|
+
require 'lotus/routing/resource'
|
4
|
+
|
5
|
+
module Lotus
|
6
|
+
module Routing
|
7
|
+
class Resources < Resource
|
8
|
+
# Action for RESTful resources
|
9
|
+
#
|
10
|
+
# @since 0.1.0
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
# @see Lotus::Router#resources
|
15
|
+
class Action < Resource::Action
|
16
|
+
# Ruby namespace where lookup for default subclasses.
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.1.0
|
20
|
+
self.namespace = Resources
|
21
|
+
end
|
22
|
+
|
23
|
+
# Collection action
|
24
|
+
# It implements #collection within a #resources block.
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.1.0
|
28
|
+
# @see Lotus::Router#resources
|
29
|
+
class CollectionAction < Resource::CollectionAction
|
30
|
+
end
|
31
|
+
|
32
|
+
# Member action
|
33
|
+
# It implements #member within a #resources block.
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
# @since 0.1.0
|
37
|
+
# @see Lotus::Router#resources
|
38
|
+
class MemberAction < Resource::MemberAction
|
39
|
+
private
|
40
|
+
def path(path)
|
41
|
+
prefix.join("/:id/#{ path }")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Implementation of common methods for concrete member actions
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.1.0
|
49
|
+
module DefaultMemberAction
|
50
|
+
private
|
51
|
+
def rest_path
|
52
|
+
"/#{ resource_name }/:id"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Index action
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
# @since 0.1.0
|
60
|
+
# @see Lotus::Router#resources
|
61
|
+
class Index < Action
|
62
|
+
self.verb = :get
|
63
|
+
end
|
64
|
+
|
65
|
+
# New action
|
66
|
+
#
|
67
|
+
# @api private
|
68
|
+
# @since 0.1.0
|
69
|
+
# @see Lotus::Router#resources
|
70
|
+
class New < Resource::New
|
71
|
+
end
|
72
|
+
|
73
|
+
# Create action
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
# @since 0.1.0
|
77
|
+
# @see Lotus::Router#resources
|
78
|
+
class Create < Resource::Create
|
79
|
+
end
|
80
|
+
|
81
|
+
# Show action
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
# @since 0.1.0
|
85
|
+
# @see Lotus::Router#resources
|
86
|
+
class Show < Resource::Show
|
87
|
+
include DefaultMemberAction
|
88
|
+
end
|
89
|
+
|
90
|
+
# Edit action
|
91
|
+
#
|
92
|
+
# @api private
|
93
|
+
# @since 0.1.0
|
94
|
+
# @see Lotus::Router#resources
|
95
|
+
class Edit < Resource::Edit
|
96
|
+
include DefaultMemberAction
|
97
|
+
|
98
|
+
private
|
99
|
+
def rest_path
|
100
|
+
"#{ super }/#{ action_name }"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Update action
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
# @since 0.1.0
|
108
|
+
# @see Lotus::Router#resources
|
109
|
+
class Update < Resource::Update
|
110
|
+
include DefaultMemberAction
|
111
|
+
end
|
112
|
+
|
113
|
+
# Destroy action
|
114
|
+
#
|
115
|
+
# @api private
|
116
|
+
# @since 0.1.0
|
117
|
+
# @see Lotus::Router#resources
|
118
|
+
class Destroy < Resource::Destroy
|
119
|
+
include DefaultMemberAction
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'http_router/route'
|
2
|
+
|
3
|
+
module Lotus
|
4
|
+
module Routing
|
5
|
+
# Entry of the routing system
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
# @since 0.1.0
|
10
|
+
#
|
11
|
+
# @see http://rdoc.info/gems/http_router/HttpRouter/Route
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# require 'lotus/router'
|
15
|
+
#
|
16
|
+
# router = Lotus::Router.new
|
17
|
+
# router.get('/', to: endpoint) # => #<Lotus::Routing::Route:0x007f83083ba028 ...>
|
18
|
+
class Route < HttpRouter::Route
|
19
|
+
# Asks the given resolver to return an endpoint that will be associated
|
20
|
+
# with the other options.
|
21
|
+
#
|
22
|
+
# @param resolver [Lotus::Routing::EndpointResolver, #resolve] this may change
|
23
|
+
# according to the :resolve option passed to Lotus::Router#initialize.
|
24
|
+
#
|
25
|
+
# @param options [Hash] options to customize the route
|
26
|
+
# @option options [Symbol] :as the name we want to use for the route
|
27
|
+
#
|
28
|
+
# @since 0.1.0
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
#
|
32
|
+
# @see Lotus::Router#initialize
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# require 'lotus/router'
|
36
|
+
#
|
37
|
+
# router = Lotus::Router.new
|
38
|
+
# router.get('/', to: endpoint, as: :home_page).name # => :home_page
|
39
|
+
#
|
40
|
+
# router.path(:home_page) # => '/'
|
41
|
+
def generate(resolver, options = {}, &endpoint)
|
42
|
+
self.to = resolver.resolve(options, &endpoint)
|
43
|
+
self.name = options[:as].to_sym if options[:as]
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def to=(dest = nil, &blk)
|
49
|
+
self.to dest, &blk
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lotus-router.gemspec
CHANGED
@@ -4,20 +4,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'lotus/router/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'lotus-router'
|
8
8
|
spec.version = Lotus::Router::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
9
|
+
spec.authors = ['Luca Guidi']
|
10
|
+
spec.email = ['me@lucaguidi.com']
|
11
|
+
spec.description = %q{HTTP Router for Lotus}
|
12
|
+
spec.summary = %q{Ruby HTTP Router for Lotus}
|
13
|
+
spec.homepage = 'http://lotusrb.org'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.executables =
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test
|
19
|
-
spec.require_paths = [
|
17
|
+
spec.executables = []
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.
|
22
|
-
spec.
|
21
|
+
spec.add_dependency 'http_router', '~> 0'
|
22
|
+
spec.add_dependency 'lotus-utils', '~> 0'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
25
|
+
spec.add_development_dependency 'minitest', '~> 5'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10'
|
23
27
|
end
|
data/test/fixtures.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
class TestEndpoint
|
2
|
+
def call(env)
|
3
|
+
'Hi from TestEndpoint!'
|
4
|
+
end
|
5
|
+
end #TestEndpoint
|
6
|
+
|
7
|
+
class TestController
|
8
|
+
class Show
|
9
|
+
def call(env)
|
10
|
+
'Hi from Test::Show!'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end #TestController
|
14
|
+
|
15
|
+
class TestApp
|
16
|
+
class TestEndpoint
|
17
|
+
def call(env)
|
18
|
+
'Hi from TestApp::TestEndpoint!'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Test2Controller
|
23
|
+
class Show
|
24
|
+
def call(env)
|
25
|
+
'Hi from TestApp::Test2Controller::Show!'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end # TestApp
|
30
|
+
|
31
|
+
class AvatarController
|
32
|
+
class New
|
33
|
+
def call(env)
|
34
|
+
[200, {}, ['Avatar::New']]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Create
|
39
|
+
def call(env)
|
40
|
+
[200, {}, ['Avatar::Create']]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Show
|
45
|
+
def call(env)
|
46
|
+
[200, {}, ['Avatar::Show']]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Edit
|
51
|
+
def call(env)
|
52
|
+
[200, {}, ['Avatar::Edit']]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Update
|
57
|
+
def call(env)
|
58
|
+
[200, {}, ['Avatar::Update']]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Destroy
|
63
|
+
def call(env)
|
64
|
+
[200, {}, ['Avatar::Destroy']]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end # AvatarController
|
68
|
+
|
69
|
+
class ProfileController
|
70
|
+
class Show
|
71
|
+
def call(env)
|
72
|
+
[200, {}, ['Profile::Show']]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class New
|
77
|
+
def call(env)
|
78
|
+
[200, {}, ['Profile::New']]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Create
|
83
|
+
def call(env)
|
84
|
+
[200, {}, ['Profile::Create']]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Edit
|
89
|
+
def call(env)
|
90
|
+
[200, {}, ['Profile::Edit']]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Update
|
95
|
+
def call(env)
|
96
|
+
[200, {}, ['Profile::Update']]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Destroy
|
101
|
+
def call(env)
|
102
|
+
[200, {}, ['Profile::Destroy']]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class Activate
|
107
|
+
def call(env)
|
108
|
+
[200, {}, ['Profile::Activate']]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Keys
|
113
|
+
def call(env)
|
114
|
+
[200, {}, ['Profile::Keys']]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end # ProfileController
|
118
|
+
|
119
|
+
class FlowersController
|
120
|
+
class Index
|
121
|
+
def call(env)
|
122
|
+
[200, {}, ['Flowers::Index']]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class New
|
127
|
+
def call(env)
|
128
|
+
[200, {}, ['Flowers::New']]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class Create
|
133
|
+
def call(env)
|
134
|
+
[200, {}, ['Flowers::Create']]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Show
|
139
|
+
def call(env)
|
140
|
+
[200, {}, ['Flowers::Show ' + env['router.params'][:id]]]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Edit
|
145
|
+
def call(env)
|
146
|
+
[200, {}, ['Flowers::Edit ' + env['router.params'][:id]]]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class Update
|
151
|
+
def call(env)
|
152
|
+
[200, {}, ['Flowers::Update ' + env['router.params'][:id]]]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class Destroy
|
157
|
+
def call(env)
|
158
|
+
[200, {}, ['Flowers::Destroy ' + env['router.params'][:id]]]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end # FlowersController
|
162
|
+
|
163
|
+
class KeyboardsController
|
164
|
+
class Index
|
165
|
+
def call(env)
|
166
|
+
[200, {}, ['Keyboards::Index']]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class Create
|
171
|
+
def call(env)
|
172
|
+
[200, {}, ['Keyboards::Create']]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class Edit
|
177
|
+
def call(env)
|
178
|
+
[200, {}, ['Keyboards::Edit ' + env['router.params'][:id]]]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
class Search
|
183
|
+
def call(env)
|
184
|
+
[200, {}, ['Keyboards::Search']]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class Screenshot
|
189
|
+
def call(env)
|
190
|
+
[200, {}, ['Keyboards::Screenshot ' + env['router.params'][:id]]]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end # KeyboardsController
|