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.
@@ -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
- # Path prefix
95
+ # Namespace
89
96
  #
90
97
  # @api private
91
- # @since 0.1.0
92
- def prefix
93
- @prefix ||= Utils::PathPrefix.new @options[:prefix]
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 prefixed URL relative path
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
- # prefix 'animals' do
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
- prefix.join(rest_path)
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
- "/#{ resource_name }"
160
+ namespace.join(resource_name)
154
161
  end
155
162
 
156
- # The prefixed name of the action within the whole context of the router.
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
- # prefix 'animals' do
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
- prefix.relative_join(named_route, '_').to_sym
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, &blk)
244
- verb, path, _ = m, *args
245
- @router.send verb, path(path), to: endpoint(path), as: as(path)
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(path)
250
- prefix.join(path)
247
+ def path(action_name)
248
+ rest_path.join(action_name)
251
249
  end
252
250
 
253
- def endpoint(path)
254
- [ resource_name, path ].join separator
251
+ def endpoint(action_name)
252
+ [ resource_name, action_name ].join separator
255
253
  end
256
254
 
257
- def as(path)
258
- Utils::PathPrefix.new(path).relative_join(resource_name, '_').to_sym
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 rest_path
278
- "/#{ resource_name }/#{ action_name }"
275
+ def path
276
+ rest_path.join(action_name)
279
277
  end
280
278
 
281
- def named_route
282
- "#{ action_name }_#{ resource_name }"
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(path)
41
- prefix.join("/:id/#{ path }")
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 rest_path
52
- "/#{ resource_name }/:id"
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 rest_path
100
- "#{ super }/#{ action_name }"
106
+ def path
107
+ super.join(action_name)
101
108
  end
102
109
  end
103
110
 
@@ -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 Router for Lotus}
12
- spec.summary = %q{Ruby HTTP Router for Lotus}
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.1.1
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-06-23 00:00:00.000000000 Z
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 Router for Lotus
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: '0'
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: Ruby HTTP Router for Lotus
140
+ summary: Rack compatible HTTP router for Ruby and Lotus
131
141
  test_files: []
132
142
  has_rdoc: