lotus-router 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +53 -11
- data/lib/lotus/router/version.rb +1 -1
- data/lib/lotus/routing/resource.rb +47 -4
- data/lib/lotus/routing/resource/action.rb +41 -8
- data/lib/lotus/routing/resource/nested.rb +39 -0
- data/lib/lotus/routing/resources.rb +8 -0
- data/lib/lotus/routing/resources/action.rb +20 -0
- data/lotus-router.gemspec +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3fcb5db6c1bdb046aeb93c5d0950301d5ed551d
|
4
|
+
data.tar.gz: 577b5c170f3d469369ce4c43c11782f6f9d6ea3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 189025ab49239109b74a6f939585d2cdc56b7568a9864c0a82af39fc166a36b8f4f4ae7e5335a53b5ca3bcadd2120b75705ca6dc8d12a1b9bf05501aaa45f652
|
7
|
+
data.tar.gz: 339c1ac13cb39971e7594675646b2c7f2a0baafa96a5bd7b44c16be0ce291d089857abbd797ab6fa6be44fa1b7a279c1d159562acd1d46c60ba97c43779d102f
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# Lotus::Router
|
2
2
|
Rack compatible HTTP router for Ruby
|
3
3
|
|
4
|
+
## v0.4.0 - 2015-05-15
|
5
|
+
### Added
|
6
|
+
- [Alfonso Uceda Pompa] Nested RESTful resource(s)
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
- [Alfonso Uceda Pompa] RESTful resource(s) have a correct pluralization/singularization for variables and named routes (eg. `/books/:id` is now `:book` instead of `:books`)
|
10
|
+
|
4
11
|
## v0.3.0 - 2015-03-23
|
5
12
|
|
6
13
|
## v0.2.1 - 2015-01-30
|
data/README.md
CHANGED
@@ -407,6 +407,27 @@ router.resource 'profile', controller: 'identity'
|
|
407
407
|
router.path(:profile) # => /profile # Will route to Identity::Show
|
408
408
|
```
|
409
409
|
|
410
|
+
#### Nested Resources
|
411
|
+
|
412
|
+
We can nest resource(s):
|
413
|
+
|
414
|
+
```ruby
|
415
|
+
router = Lotus::Router.new
|
416
|
+
router.resource :identity do
|
417
|
+
resource :avatar
|
418
|
+
resources :api_keys
|
419
|
+
end
|
420
|
+
|
421
|
+
router.path(:identity_avatar) # => /identity/avatar
|
422
|
+
router.path(:new_identity_avatar) # => /identity/avatar/new
|
423
|
+
router.path(:edit_identity_avatar) # => /identity/avatar/new
|
424
|
+
|
425
|
+
router.path(:identity_api_keys) # => /identity/api_keys
|
426
|
+
router.path(:identity_api_key) # => /identity/api_keys/:id
|
427
|
+
router.path(:new_identity_api_key) # => /identity/api_keys/new
|
428
|
+
router.path(:edit_identity_api_key) # => /identity/api_keys/:id/edit
|
429
|
+
```
|
430
|
+
|
410
431
|
|
411
432
|
|
412
433
|
### RESTful Resources:
|
@@ -438,14 +459,14 @@ It will map:
|
|
438
459
|
<td>/flowers/:id</td>
|
439
460
|
<td>Flowers::Show</td>
|
440
461
|
<td>:show</td>
|
441
|
-
<td>:
|
462
|
+
<td>:flower</td>
|
442
463
|
</tr>
|
443
464
|
<tr>
|
444
465
|
<td>GET</td>
|
445
466
|
<td>/flowers/new</td>
|
446
467
|
<td>Flowers::New</td>
|
447
468
|
<td>:new</td>
|
448
|
-
<td>:
|
469
|
+
<td>:new_flower</td>
|
449
470
|
</tr>
|
450
471
|
<tr>
|
451
472
|
<td>POST</td>
|
@@ -459,29 +480,29 @@ It will map:
|
|
459
480
|
<td>/flowers/:id/edit</td>
|
460
481
|
<td>Flowers::Edit</td>
|
461
482
|
<td>:edit</td>
|
462
|
-
<td>:
|
483
|
+
<td>:edit_flower</td>
|
463
484
|
</tr>
|
464
485
|
<tr>
|
465
486
|
<td>PATCH</td>
|
466
487
|
<td>/flowers/:id</td>
|
467
488
|
<td>Flowers::Update</td>
|
468
489
|
<td>:update</td>
|
469
|
-
<td>:
|
490
|
+
<td>:flower</td>
|
470
491
|
</tr>
|
471
492
|
<tr>
|
472
493
|
<td>DELETE</td>
|
473
494
|
<td>/flowers/:id</td>
|
474
495
|
<td>Flowers::Destroy</td>
|
475
496
|
<td>:destroy</td>
|
476
|
-
<td>:
|
497
|
+
<td>:flower</td>
|
477
498
|
</tr>
|
478
499
|
</table>
|
479
500
|
|
480
501
|
|
481
502
|
```ruby
|
482
|
-
router.path(:flowers)
|
483
|
-
router.path(:
|
484
|
-
router.path(:
|
503
|
+
router.path(:flowers) # => /flowers
|
504
|
+
router.path(:flower, id: 23) # => /flowers/23
|
505
|
+
router.path(:edit_flower, id: 23) # => /flowers/23/edit
|
485
506
|
```
|
486
507
|
|
487
508
|
|
@@ -512,8 +533,8 @@ router.resources 'flowers' do
|
|
512
533
|
end
|
513
534
|
end
|
514
535
|
|
515
|
-
router.path(:
|
516
|
-
router.path(:search_flowers)
|
536
|
+
router.path(:toggle_flower, id: 23) # => /flowers/23/toggle
|
537
|
+
router.path(:search_flowers) # => /flowers/search
|
517
538
|
```
|
518
539
|
|
519
540
|
|
@@ -523,7 +544,28 @@ Configure controller:
|
|
523
544
|
router = Lotus::Router.new
|
524
545
|
router.resources 'blossoms', controller: 'flowers'
|
525
546
|
|
526
|
-
router.path(:
|
547
|
+
router.path(:blossom, id: 23) # => /blossoms/23 # Will route to Flowers::Show
|
548
|
+
```
|
549
|
+
|
550
|
+
#### Nested Resources
|
551
|
+
|
552
|
+
We can nest resource(s):
|
553
|
+
|
554
|
+
```ruby
|
555
|
+
router = Lotus::Router.new
|
556
|
+
router.resources :users do
|
557
|
+
resource :avatar
|
558
|
+
resources :favorites
|
559
|
+
end
|
560
|
+
|
561
|
+
router.path(:user_avatar, user_id: 1) # => /users/1/avatar
|
562
|
+
router.path(:new_user_avatar, user_id: 1) # => /users/1/avatar/new
|
563
|
+
router.path(:edit_user_avatar, user_id: 1) # => /users/1/avatar/edit
|
564
|
+
|
565
|
+
router.path(:user_favorites, user_id: 1) # => /users/1/favorites
|
566
|
+
router.path(:user_favorite, user_id: 1, id: 2) # => /users/1/favorites/2
|
567
|
+
router.path(:new_user_favorites, user_id: 1) # => /users/1/favorites/new
|
568
|
+
router.path(:edit_user_favorites, user_id: 1, id: 2) # => /users/1/favorites/2/edit
|
527
569
|
```
|
528
570
|
|
529
571
|
## Testing
|
data/lib/lotus/router/version.rb
CHANGED
@@ -15,6 +15,10 @@ module Lotus
|
|
15
15
|
class Resource
|
16
16
|
include Utils::ClassAttribute
|
17
17
|
|
18
|
+
# @api private
|
19
|
+
# @since 0.4.0
|
20
|
+
NESTED_ROUTES_SEPARATOR = '/'.freeze
|
21
|
+
|
18
22
|
# Set of default routes
|
19
23
|
#
|
20
24
|
# @api private
|
@@ -43,30 +47,69 @@ module Lotus
|
|
43
47
|
class_attribute :collection
|
44
48
|
self.collection = Resource::CollectionAction
|
45
49
|
|
50
|
+
# @api private
|
51
|
+
# @since 0.4.0
|
52
|
+
attr_reader :parent
|
53
|
+
|
46
54
|
# @api private
|
47
55
|
# @since 0.1.0
|
48
|
-
def initialize(router, name, options = {}, &blk)
|
56
|
+
def initialize(router, name, options = {}, parent = nil, &blk)
|
49
57
|
@router = router
|
50
58
|
@name = name
|
59
|
+
@parent = parent
|
51
60
|
@options = Options.new(self.class.actions, options.merge(name: @name))
|
52
61
|
generate(&blk)
|
53
62
|
end
|
54
63
|
|
64
|
+
# Allow nested resources inside resource or resources
|
65
|
+
#
|
66
|
+
# @since 0.4.0
|
67
|
+
#
|
68
|
+
# @see Lotus::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 Lotus::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
|
+
|
55
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
|
+
|
56
99
|
def generate(&blk)
|
57
100
|
instance_eval(&blk) if block_given?
|
58
101
|
|
59
102
|
@options.actions.each do |action|
|
60
|
-
self.class.action.generate(@router, action, @options)
|
103
|
+
self.class.action.generate(@router, action, @options, self)
|
61
104
|
end
|
62
105
|
end
|
63
106
|
|
64
107
|
def member(&blk)
|
65
|
-
self.class.member.new(@router, @options, &blk)
|
108
|
+
self.class.member.new(@router, @options, self, &blk)
|
66
109
|
end
|
67
110
|
|
68
111
|
def collection(&blk)
|
69
|
-
self.class.collection.new(@router, @options, &blk)
|
112
|
+
self.class.collection.new(@router, @options, self, &blk)
|
70
113
|
end
|
71
114
|
end
|
72
115
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'lotus/utils/string'
|
2
2
|
require 'lotus/utils/path_prefix'
|
3
3
|
require 'lotus/utils/class_attribute'
|
4
|
+
require 'lotus/routing/resource/nested'
|
4
5
|
|
5
6
|
module Lotus
|
6
7
|
module Routing
|
@@ -15,6 +16,12 @@ module Lotus
|
|
15
16
|
class Action
|
16
17
|
include Utils::ClassAttribute
|
17
18
|
|
19
|
+
# Nested routes separator
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.4.0
|
23
|
+
NESTED_ROUTES_SEPARATOR = '/'.freeze
|
24
|
+
|
18
25
|
# Ruby namespace where lookup for default subclasses.
|
19
26
|
#
|
20
27
|
# @api private
|
@@ -41,25 +48,29 @@ module Lotus
|
|
41
48
|
# @param router [Lotus::Router]
|
42
49
|
# @param action [Lotus::Routing::Resource::Action]
|
43
50
|
# @param options [Hash]
|
51
|
+
# @param resource [Lotus::Routing::Resource, Lotus::Routing::Resources]
|
44
52
|
#
|
45
53
|
# @api private
|
46
54
|
#
|
47
55
|
# @since 0.1.0
|
48
|
-
def self.generate(router, action, options)
|
49
|
-
class_for(action).new(router, options)
|
56
|
+
def self.generate(router, action, options = {}, resource = nil)
|
57
|
+
class_for(action).new(router, options, resource)
|
50
58
|
end
|
51
59
|
|
52
60
|
# Initialize an action
|
53
61
|
#
|
54
62
|
# @param router [Lotus::Router]
|
55
63
|
# @param options [Hash]
|
64
|
+
# @param resource [Lotus::Routing::Resource, Lotus::Routing::Resources]
|
56
65
|
# @param blk [Proc]
|
57
66
|
#
|
58
67
|
# @api private
|
59
68
|
#
|
60
69
|
# @since 0.1.0
|
61
|
-
def initialize(router, options, &blk)
|
62
|
-
@router
|
70
|
+
def initialize(router, options = {}, resource = nil, &blk)
|
71
|
+
@router = router
|
72
|
+
@options = options
|
73
|
+
@resource = resource
|
63
74
|
generate(&blk)
|
64
75
|
end
|
65
76
|
|
@@ -77,6 +88,8 @@ module Lotus
|
|
77
88
|
|
78
89
|
# Resource name
|
79
90
|
#
|
91
|
+
# @return [String]
|
92
|
+
#
|
80
93
|
# @api private
|
81
94
|
# @since 0.1.0
|
82
95
|
#
|
@@ -89,7 +102,7 @@ module Lotus
|
|
89
102
|
#
|
90
103
|
# # 'identity' is the name passed in the @options
|
91
104
|
def resource_name
|
92
|
-
@options[:name]
|
105
|
+
@resource_name ||= @options[:name].to_s
|
93
106
|
end
|
94
107
|
|
95
108
|
# Namespace
|
@@ -157,7 +170,7 @@ module Lotus
|
|
157
170
|
# @api private
|
158
171
|
# @since 0.1.0
|
159
172
|
def rest_path
|
160
|
-
namespace.join(resource_name)
|
173
|
+
namespace.join(_nested_rest_path || resource_name.to_s)
|
161
174
|
end
|
162
175
|
|
163
176
|
# The namespaced name of the action within the whole context of the router.
|
@@ -179,7 +192,7 @@ module Lotus
|
|
179
192
|
# @api private
|
180
193
|
# @since 0.1.0
|
181
194
|
def as
|
182
|
-
namespace.relative_join(
|
195
|
+
namespace.relative_join(_singularized_as, self.class.named_route_separator).to_sym
|
183
196
|
end
|
184
197
|
|
185
198
|
# The name of the RESTful action.
|
@@ -233,10 +246,30 @@ module Lotus
|
|
233
246
|
# # Same for other action names
|
234
247
|
#
|
235
248
|
# @api private
|
236
|
-
# @since
|
249
|
+
# @since 0.4.0
|
237
250
|
def controller_name
|
238
251
|
@options[:controller] || resource_name
|
239
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
|
+
resource_name.split(NESTED_ROUTES_SEPARATOR).map do |name|
|
262
|
+
Lotus::Utils::String.new(name).singularize
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Create nested rest path
|
267
|
+
#
|
268
|
+
# @api private
|
269
|
+
# @since 0.4.0
|
270
|
+
def _nested_rest_path
|
271
|
+
Nested.new(resource_name, @resource).to_path
|
272
|
+
end
|
240
273
|
end
|
241
274
|
|
242
275
|
# Collection action
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Routing
|
3
|
+
class Resource
|
4
|
+
# Helper class to calculate nested path
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
# @since 0.4.0
|
8
|
+
class Nested
|
9
|
+
# @api private
|
10
|
+
# @since 0.4.0
|
11
|
+
SEPARATOR = '/'.freeze
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
# @since 0.4.0
|
15
|
+
def initialize(resource_name, resource)
|
16
|
+
@resource_name = resource_name.to_s.split(SEPARATOR)
|
17
|
+
@resource = resource
|
18
|
+
@path = []
|
19
|
+
_calculate(@resource_name.dup, @resource)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
# @since 0.4.0
|
24
|
+
def to_path
|
25
|
+
@path.reverse!.pop
|
26
|
+
@resource_name.zip(@path).flatten.join
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def _calculate(param_wildcard, resource = nil)
|
32
|
+
return if resource.nil?
|
33
|
+
@path << resource.wildcard_param(param_wildcard.pop)
|
34
|
+
_calculate(param_wildcard, resource.parent)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -35,6 +35,14 @@ module Lotus
|
|
35
35
|
# @api private
|
36
36
|
# @since 0.1.0
|
37
37
|
self.collection = Resources::CollectionAction
|
38
|
+
|
39
|
+
# Return wildcard param between separators
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
# @since 0.4.0
|
43
|
+
def wildcard_param(route_param = nil)
|
44
|
+
"/:#{ Lotus::Utils::String.new(route_param).singularize }_id/"
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
@@ -27,6 +27,21 @@ module Lotus
|
|
27
27
|
self.identifier = ':id'.freeze
|
28
28
|
end
|
29
29
|
|
30
|
+
# Pluralize concrete actions
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.4.0
|
34
|
+
module PluralizedAction
|
35
|
+
private
|
36
|
+
# The name of the RESTful action.
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.4.0
|
40
|
+
def as
|
41
|
+
Lotus::Utils::String.new(super).pluralize
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
30
45
|
# Collection action
|
31
46
|
# It implements #collection within a #resources block.
|
32
47
|
#
|
@@ -34,6 +49,9 @@ module Lotus
|
|
34
49
|
# @since 0.1.0
|
35
50
|
# @see Lotus::Router#resources
|
36
51
|
class CollectionAction < Resource::CollectionAction
|
52
|
+
def as(action_name)
|
53
|
+
Lotus::Utils::String.new(super(action_name)).pluralize
|
54
|
+
end
|
37
55
|
end
|
38
56
|
|
39
57
|
# Member action
|
@@ -66,6 +84,7 @@ module Lotus
|
|
66
84
|
# @since 0.1.0
|
67
85
|
# @see Lotus::Router#resources
|
68
86
|
class Index < Action
|
87
|
+
include PluralizedAction
|
69
88
|
self.verb = :get
|
70
89
|
end
|
71
90
|
|
@@ -83,6 +102,7 @@ module Lotus
|
|
83
102
|
# @since 0.1.0
|
84
103
|
# @see Lotus::Router#resources
|
85
104
|
class Create < Resource::Create
|
105
|
+
include PluralizedAction
|
86
106
|
end
|
87
107
|
|
88
108
|
# Show action
|
data/lotus-router.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.required_ruby_version = '>= 2.0.0'
|
21
21
|
|
22
22
|
spec.add_dependency 'http_router', '~> 0.11'
|
23
|
-
spec.add_dependency 'lotus-utils', '~> 0.4'
|
23
|
+
spec.add_dependency 'lotus-utils', '~> 0.4', '>= 0.4.1'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.5'
|
26
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.4.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: 2015-
|
11
|
+
date: 2015-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http_router
|
@@ -31,6 +31,9 @@ dependencies:
|
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0.4'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.4.1
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +41,9 @@ dependencies:
|
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '0.4'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.4.1
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: bundler
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,6 +108,7 @@ files:
|
|
102
108
|
- lib/lotus/routing/parsing/parser.rb
|
103
109
|
- lib/lotus/routing/resource.rb
|
104
110
|
- lib/lotus/routing/resource/action.rb
|
111
|
+
- lib/lotus/routing/resource/nested.rb
|
105
112
|
- lib/lotus/routing/resource/options.rb
|
106
113
|
- lib/lotus/routing/resources.rb
|
107
114
|
- lib/lotus/routing/resources/action.rb
|