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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +5 -13
  4. data/.travis.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +10 -3
  7. data/README.md +470 -6
  8. data/Rakefile +10 -1
  9. data/benchmarks/callable +23 -0
  10. data/benchmarks/named_routes +72 -0
  11. data/benchmarks/resource +44 -0
  12. data/benchmarks/resources +58 -0
  13. data/benchmarks/routes +67 -0
  14. data/benchmarks/run.sh +11 -0
  15. data/benchmarks/utils.rb +56 -0
  16. data/lib/lotus-router.rb +1 -0
  17. data/lib/lotus/router.rb +752 -3
  18. data/lib/lotus/router/version.rb +2 -2
  19. data/lib/lotus/routing/endpoint.rb +114 -0
  20. data/lib/lotus/routing/endpoint_resolver.rb +251 -0
  21. data/lib/lotus/routing/http_router.rb +130 -0
  22. data/lib/lotus/routing/namespace.rb +86 -0
  23. data/lib/lotus/routing/resource.rb +73 -0
  24. data/lib/lotus/routing/resource/action.rb +340 -0
  25. data/lib/lotus/routing/resource/options.rb +48 -0
  26. data/lib/lotus/routing/resources.rb +40 -0
  27. data/lib/lotus/routing/resources/action.rb +123 -0
  28. data/lib/lotus/routing/route.rb +53 -0
  29. data/lotus-router.gemspec +16 -12
  30. data/test/fixtures.rb +193 -0
  31. data/test/integration/client_error_test.rb +16 -0
  32. data/test/integration/pass_on_response_test.rb +13 -0
  33. data/test/named_routes_test.rb +123 -0
  34. data/test/namespace_test.rb +289 -0
  35. data/test/new_test.rb +67 -0
  36. data/test/redirect_test.rb +33 -0
  37. data/test/resource_test.rb +128 -0
  38. data/test/resources_test.rb +136 -0
  39. data/test/routing/endpoint_resolver_test.rb +110 -0
  40. data/test/routing/resource/options_test.rb +36 -0
  41. data/test/routing_test.rb +99 -0
  42. data/test/test_helper.rb +32 -0
  43. data/test/version_test.rb +7 -0
  44. 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 = "lotus-router"
7
+ spec.name = 'lotus-router'
8
8
  spec.version = Lotus::Router::VERSION
9
- spec.authors = ["Luca Guidi"]
10
- spec.email = ["me@lucaguidi.com"]
11
- spec.summary = %q{HTTP router for Lotus}
12
- spec.description = %q{HTTP router for Lotus}
13
- spec.homepage = ""
14
- spec.license = "MIT"
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 = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
17
+ spec.executables = []
18
+ spec.test_files = spec.files.grep(%r{^(test)/})
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.5"
22
- spec.add_development_dependency "rake"
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