lotus-router 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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