lotus-router 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ff45eb9a0d8db10815f562e9d5af4e5cf2649b7a
4
- data.tar.gz: 3a6e353ac3840fc2bab5a0324ec50294493efa20
3
+ metadata.gz: 7ded3effb55d8697f3a45666539825d205771161
4
+ data.tar.gz: ac9b49d12b41b64e694998e4c663895f81279921
5
5
  SHA512:
6
- metadata.gz: 5aba74771a3578cb3654a687b428e9fdca6bbdc2cc186dc1777ff28b9862a4a9f50d7daa9de80fbfc191bcf67ca3ab35eabfdcdbffedfb9d0043aa62601d8b72
7
- data.tar.gz: e0d18ad2c7e1cdb275a58871a321cd635b383c1c6308635cfeab29bfe5859e62eeeab0c728414ba118601787855a3b3e01fc602120ddf0c45304af63b20d84e4
6
+ metadata.gz: 1542eba77ef0f590dd88f9abe472760f09e14375796867dd031bd360bf2e19b4056c8b89c03b32bb45542a23616f6c502df2382a8dc19441b16b5eb0dc657223
7
+ data.tar.gz: ea54e84f9c8507fd70d0c5c3e7f946930444d612dfc89012215d56a7ab55518658599dd0707dbb4da2358f1904d2717b27165f1ce9f77c9f40fdfc1626adb44e
data/CHANGELOG.md ADDED
@@ -0,0 +1,45 @@
1
+ ## v0.1.1
2
+ ### Jun 23, 2014
3
+
4
+ 6f0ea8b 2014-06-12 **Luca Guidi** Introduced Lotus::Router#mount
5
+ 8457e1c 2014-06-08 **Luca Guidi** Use composition over inheritance for Lotus::Routing::Resource::Options
6
+ 9426099 2014-05-13 **Luca Guidi** Let specify a pattern for Lotus::Routing::EndpointResolver
7
+ 340ce17 2014-05-10 **Luca Guidi** Enable Ruby 2.1.2 on Travis CI
8
+ 42b83b8 2014-02-24 **Luca Guidi** Added support for Ruby 2.1.1
9
+ 6a5daf9 2014-02-15 **Luca Guidi** Make Lotus::Routing::Endpoint::EndpointNotFound to inherit from StandardError, instead of Exception. This make it compatible with Rack::ShowExceptions.
10
+
11
+ ## v0.1.0
12
+ ### Jan 23, 2014
13
+
14
+ 594e332 2014-01-23 **Luca Guidi** Added support for OPTIONS HTTP verb
15
+ 10af04b 2014-01-17 **Luca Guidi** Added Lotus::Routing::EndpointNotFound when a lazy endpoint can't be found
16
+ 72165e5 2014-01-17 **Luca Guidi** Make action separator customizable via Lotus::Router options.
17
+ ca7ea8d 2014-01-17 **Luca Guidi** Catch http_router exceptions and re-raise them with names under Lotus::Routing. This helps to have a stable public API.
18
+ 3d678e3 2014-01-16 **Luca Guidi** Lotus::Router now encapsulates Lotus::Routing::HttpRouter, instead of directly inherit from HttpRouter. This will protect our public API against HttpRouter changes.
19
+ 8e8f7f9 2014-01-16 **Luca Guidi** Lotus::Routing::Resource::CollectionAction use configurable controller and action name separator over the hardcoded value
20
+ 0bc8e54 2014-01-10 **Luca Guidi** Implemented Lotus::Routing::Namespace#resource
21
+ e134e5c 2014-01-08 **Luca Guidi** Simplify Lotus::Router public API: removed .draw and let .new to accept a block
22
+ 815391a 2014-01-07 **Luca Guidi** When resetting the router, allow the default values for scheme, host and port to be reinitialized as http_router does
23
+ bc763a8 2013-08-07 **Luca Guidi** Lotus::Routing::EndpointResolver now accepts options to inject namespace and suffix
24
+ 153047f 2013-08-07 **Luca Guidi** Allow resolver and route class to be injected via options. Added options argument to .draw
25
+ cd1128f 2013-08-07 **Luca Guidi** Lotus::EndpointResolver => Lotus::Routing::EndpointResolver
26
+ 96a67c1 2013-07-09 **Luca Guidi** Return 404 for not found and 405 for unacceptable HTTP method
27
+ 7450883 2013-07-05 **Luca Guidi** Allow non-finished Rack responses to be used
28
+ aa92524 2013-06-24 **Luca Guidi** Ensure .draw to always return a Lotus::Router instance
29
+ 30029af 2013-06-22 **Luca Guidi** Implemented lazy loading for endpoints
30
+ 962fbdf 2013-06-21 **Luca Guidi** Implemented Lotus::Router.draw
31
+ 982d95a 2013-06-20 **Luca Guidi** Gemified
32
+ bac478a 2013-06-20 **Luca Guidi** Massive cleanup
33
+ aaf46a1 2013-06-20 **Luca Guidi** Add support for resource
34
+ 41ee67d 2013-06-20 **Luca Guidi** Drastically reduced LOCs :heart_eyes:
35
+ 6b245bf 2013-06-19 **Luca Guidi** Support for resource's member and collection
36
+ 727e997 2013-06-19 **Luca Guidi** Add support for namespaces
37
+ 4950777 2013-06-18 **Luca Guidi** Added support for RESTful resources
38
+ c494c85 2013-06-18 **Luca Guidi** Add support for POST, DELETE, PUT, PATCH, TRACE
39
+ 71fb4a1 2013-06-17 **Luca Guidi** Routes constraints
40
+ 86d696a 2013-06-17 **Luca Guidi** Named urls
41
+ 423cf2c 2013-06-17 **Luca Guidi** Ensure redirect works properly
42
+ 1ee662a 2013-06-17 **Luca Guidi** Run all the test suite
43
+ e2382a0 2013-06-16 **Luca Guidi** Add support for Procs:
44
+ f397aac 2013-06-16 **Luca Guidi** Implemented redirect
45
+ dded0c5 2013-06-14 **Luca Guidi** Initial mess
File without changes
data/README.md CHANGED
@@ -4,11 +4,12 @@ Rack compatible, lightweight and fast HTTP Router for [Lotus](http://lotusrb.org
4
4
 
5
5
  ## Status
6
6
 
7
- [![Gem Version](https://badge.fury.io/rb/lotus-router.png)](http://badge.fury.io/rb/lotus-router)
8
- [![Build Status](https://secure.travis-ci.org/lotus/router.png?branch=master)](http://travis-ci.org/lotus/router?branch=master)
9
- [![Coverage](https://coveralls.io/repos/lotus/router/badge.png?branch=master)](https://coveralls.io/r/lotus/router)
10
- [![Code Climate](https://codeclimate.com/github/lotus/router.png)](https://codeclimate.com/github/lotus/router)
11
- [![Dependencies](https://gemnasium.com/lotus/router.png)](https://gemnasium.com/lotus/router)
7
+ [![Gem Version](http://img.shields.io/gem/v/lotus-router.svg)](https://badge.fury.io/rb/lotus-router)
8
+ [![Build Status](http://img.shields.io/travis/lotus/router/master.svg)](https://travis-ci.org/lotus/router?branch=master)
9
+ [![Coverage](http://img.shields.io/coveralls/lotus/router/master.svg)](https://coveralls.io/r/lotus/router)
10
+ [![Code Climate](http://img.shields.io/codeclimate/github/lotus/router.svg)](https://codeclimate.com/github/lotus/router)
11
+ [![Dependencies](http://img.shields.io/gemnasium/lotus/router.svg)](https://gemnasium.com/lotus/router)
12
+ [![Inline docs](http://inch-ci.org/github/lotus/router.png)](http://inch-ci.org/github/lotus/router)
12
13
 
13
14
  ## Contact
14
15
 
@@ -16,7 +17,8 @@ Rack compatible, lightweight and fast HTTP Router for [Lotus](http://lotusrb.org
16
17
  * Mailing List: http://lotusrb.org/mailing-list
17
18
  * API Doc: http://rdoc.info/gems/lotus-router
18
19
  * Bugs/Issues: https://github.com/lotus/router/issues
19
- * Support: http://stackoverflow.com/questions/tagged/lotusrb
20
+ * Support: http://stackoverflow.com/questions/tagged/lotus-ruby
21
+ * Chat: https://gitter.im/lotus/chat
20
22
 
21
23
  ## Rubies
22
24
 
@@ -74,6 +76,8 @@ Lotus::Router.new do
74
76
 
75
77
  redirect '/legacy', to: '/'
76
78
 
79
+ mount Api::App, to: '/api'
80
+
77
81
  namespace 'admin' do
78
82
  get '/users', to: UsersController::Index
79
83
  end
@@ -129,7 +133,7 @@ router.get '/flowers/:id', id: /\d+/, to: ->(env) { [200, {}, [":id must be a nu
129
133
 
130
134
 
131
135
 
132
- ### String matching with globbling:
136
+ ### String matching with globbing:
133
137
 
134
138
  ```ruby
135
139
  router = Lotus::Router.new
@@ -206,6 +210,26 @@ router.path(:animals_mammals_cats) # => "/animals/mammals/cats"
206
210
 
207
211
 
208
212
 
213
+ ### Mount Rack applications:
214
+
215
+ ```ruby
216
+ Lotus::Router.new do
217
+ mount RackOne, at: '/rack1'
218
+ mount RackTwo, at: '/rack2'
219
+ mount RackThree.new, at: '/rack3'
220
+ mount ->(env) {[200, {}, ['Rack Four']]}, at: '/rack4'
221
+ mount 'dashboard#index', at: '/dashboard'
222
+ end
223
+ ```
224
+
225
+ 1. `RackOne` is used as it is (class), because it respond to `.call`
226
+ 2. `RackTwo` is initialized, because it respond to `#call`
227
+ 3. `RackThree` is used as it is (object), because it respond to `#call`
228
+ 4. That Proc is used as it is, because it respond to `#call`
229
+ 5. That string is resolved as `DashboardController::Index` ([Lotus::Controller](https://github.com/lotus/controller) integration)
230
+
231
+
232
+
209
233
  ### Duck typed endpoints:
210
234
 
211
235
  Everything that responds to `#call` is invoked as it is:
@@ -325,7 +349,7 @@ If you don't need all the default endpoints, just do:
325
349
  router = Lotus::Router.new
326
350
  router.resource 'identity', only: [:edit, :update]
327
351
 
328
- # which is equivalent to:
352
+ #### which is equivalent to:
329
353
 
330
354
  router.resource 'identity', except: [:show, :new, :create, :destroy]
331
355
  ```
@@ -434,7 +458,7 @@ If you don't need all the default endpoints, just do:
434
458
  router = Lotus::Router.new
435
459
  router.resources 'flowers', only: [:new, :create, :show]
436
460
 
437
- # which is equivalent to:
461
+ #### which is equivalent to:
438
462
 
439
463
  router.resources 'flowers', except: [:index, :edit, :update, :destroy]
440
464
  ```
data/lib/lotus/router.rb CHANGED
@@ -75,6 +75,15 @@ module Lotus
75
75
  #
76
76
  # # This isn't mandatory for the default route class (`Lotus::Routing::Route`),
77
77
  # # This behavior can be changed by passing a custom route to `Lotus::Router#initialize`
78
+ #
79
+ # @example Mount an application
80
+ # require 'lotus/router'
81
+ #
82
+ # router = Lotus::Router.new do
83
+ # mount Api::App, at: '/api'
84
+ # end
85
+ #
86
+ # # All the requests starting with "/api" will be forwarded to Api::App
78
87
  class Router
79
88
  # Initialize the router.
80
89
  #
@@ -688,6 +697,95 @@ module Lotus
688
697
  Routing::Resources.new(self, name, options.merge(separator: @router.action_separator), &blk)
689
698
  end
690
699
 
700
+ # Mount a Rack application at the specified path.
701
+ # All the requests starting with the specified path, will be forwarded to
702
+ # the given application.
703
+ #
704
+ # All the other methods (eg #get) support callable objects, but they
705
+ # restrict the range of the acceptable HTTP verb. Mounting an application
706
+ # with #mount doesn't apply this kind of restriction at the router level,
707
+ # but let the application to decide.
708
+ #
709
+ # @param app [#call] a class or an object that responds to #call
710
+ # @param options [Hash] the options to customize the mount
711
+ # @option options [:at] the path prefix where to mount the app
712
+ #
713
+ # @since 0.1.1
714
+ #
715
+ # @example Basic usage
716
+ # require 'lotus/router'
717
+ #
718
+ # Lotus::Router.new do
719
+ # mount Api::App.new, at: '/api'
720
+ # end
721
+ #
722
+ # # Requests:
723
+ # #
724
+ # # GET /api # => 200
725
+ # # GET /api/articles # => 200
726
+ # # POST /api/articles # => 200
727
+ # # GET /api/unknown # => 404
728
+ #
729
+ # @example Difference between #get and #mount
730
+ # require 'lotus/router'
731
+ #
732
+ # Lotus::Router.new do
733
+ # get '/rack1', to: RackOne.new
734
+ # mount RackTwo.new, at: '/rack2'
735
+ # end
736
+ #
737
+ # # Requests:
738
+ # #
739
+ # # # /rack1 will only accept GET
740
+ # # GET /rack1 # => 200 (RackOne.new)
741
+ # # POST /rack1 # => 405
742
+ # #
743
+ # # # /rack2 accepts all the verbs and delegate the decision to RackTwo
744
+ # # GET /rack2 # => 200 (RackTwo.new)
745
+ # # POST /rack2 # => 200 (RackTwo.new)
746
+ #
747
+ # @example Types of mountable applications
748
+ # require 'lotus/router'
749
+ #
750
+ # class RackOne
751
+ # def self.call(env)
752
+ # end
753
+ # end
754
+ #
755
+ # class RackTwo
756
+ # def call(env)
757
+ # end
758
+ # end
759
+ #
760
+ # class RackThree
761
+ # def call(env)
762
+ # end
763
+ # end
764
+ #
765
+ # class DashboardController
766
+ # class Index
767
+ # def call(env)
768
+ # end
769
+ # end
770
+ # end
771
+ #
772
+ # Lotus::Router.new do
773
+ # mount RackOne, at: '/rack1'
774
+ # mount RackTwo, at: '/rack2'
775
+ # mount RackThree.new, at: '/rack3'
776
+ # mount ->(env) {[200, {}, ['Rack Four']]}, at: '/rack4'
777
+ # mount 'dashboard#index', at: '/dashboard'
778
+ # end
779
+ #
780
+ # # 1. RackOne is used as it is (class), because it respond to .call
781
+ # # 2. RackTwo is initialized, because it respond to #call
782
+ # # 3. RackThree is used as it is (object), because it respond to #call
783
+ # # 4. That Proc is used as it is, because it respond to #call
784
+ # # 5. That string is resolved as DashboardController::Index (Lotus::Controller)
785
+ def mount(app, options)
786
+ @router.mount(app, options)
787
+ end
788
+
691
789
  # Resolve the given Rack env to a registered endpoint and invoke it.
692
790
  #
693
791
  # @param env [Hash] a Rack env instance
@@ -1,5 +1,5 @@
1
1
  module Lotus
2
2
  class Router
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.1'
4
4
  end
5
5
  end
@@ -7,7 +7,7 @@ module Lotus
7
7
  # This is raised when the router fails to load an endpoint at the runtime.
8
8
  #
9
9
  # @since 0.1.0
10
- class EndpointNotFound < ::Exception
10
+ class EndpointNotFound < ::StandardError
11
11
  end
12
12
 
13
13
  # Routing endpoint
@@ -26,7 +26,7 @@ module Lotus
26
26
  # end
27
27
  #
28
28
  # # That string is transformed into "Articles(::Controller::|Controller::)Show"
29
- # # because the risolver is able to lookup (in the given order) for:
29
+ # # because the resolver is able to lookup (in the given order) for:
30
30
  # #
31
31
  # # * Articles::Controller::Show
32
32
  # # * ArticlesController::Show
@@ -65,6 +65,11 @@ module Lotus
65
65
  # @option options [String] :suffix the suffix appended to the controller
66
66
  # name during the lookup. (defaults to `SUFFIX`)
67
67
  #
68
+ # @option options [String] :pattern the string to interpolate in order
69
+ # to return an action name. Please note that this option override
70
+ # :suffix. This string SHOULD contain `'%{controller}'` and `'%{action}'`,
71
+ # all the other keys will be ignored. See the examples below.
72
+ #
68
73
  # @option options [String] :action_separator the sepatator between controller and
69
74
  # action name. (defaults to `ACTION_SEPARATOR`)
70
75
  #
@@ -114,6 +119,18 @@ module Lotus
114
119
  #
115
120
  #
116
121
  #
122
+ # @example Specify custom simple pattern
123
+ # require 'lotus/router'
124
+ #
125
+ # resolver = Lotus::Routing::EndpointResolver.new(pattern: 'Controllers::%{controller}::%{action}')
126
+ # router = Lotus::Router.new(resolver: resolver)
127
+ #
128
+ # router.get('/', to: 'articles#show')
129
+ # # => Will look for:
130
+ # # * Controllers::Articles::Show
131
+ #
132
+ #
133
+ #
117
134
  # @example Specify custom controller-action separator
118
135
  # require 'lotus/router'
119
136
  #
@@ -127,8 +144,9 @@ module Lotus
127
144
  def initialize(options = {})
128
145
  @endpoint_class = options[:endpoint] || Endpoint
129
146
  @namespace = options[:namespace] || Object
130
- @suffix = options[:suffix] || SUFFIX
131
147
  @action_separator = options[:action_separator] || ACTION_SEPARATOR
148
+ @pattern = options[:pattern] ||
149
+ "%{controller}#{options[:suffix] || SUFFIX}%{action}"
132
150
  end
133
151
 
134
152
  # Resolve the given set of HTTP verb, path, endpoint and options.
@@ -229,6 +247,8 @@ module Lotus
229
247
  def resolve_callable(callable)
230
248
  if callable.respond_to?(:call)
231
249
  @endpoint_class.new(callable)
250
+ elsif callable.is_a?(Class) && callable.instance_methods.include?(:call)
251
+ @endpoint_class.new(callable.new)
232
252
  end
233
253
  end
234
254
 
@@ -243,7 +263,7 @@ module Lotus
243
263
  def resolve_action(string)
244
264
  if string.match(action_separator)
245
265
  controller, action = string.split(action_separator).map {|token| classify(token) }
246
- controller + @suffix + action
266
+ @pattern % {controller: controller, action: action}
247
267
  end
248
268
  end
249
269
  end
@@ -93,6 +93,18 @@ module Lotus
93
93
  add_with_request_method(path, :options, options, &blk)
94
94
  end
95
95
 
96
+ # Allow to mount a Rack app
97
+ #
98
+ # @see Lotus::Router#mount
99
+ #
100
+ # @since 0.1.1
101
+ # @api private
102
+ def mount(app, options)
103
+ add("#{ options.fetch(:at) }*").to(
104
+ @resolver.resolve(to: app)
105
+ )
106
+ end
107
+
96
108
  # @api private
97
109
  def reset!
98
110
  uncompile
@@ -8,7 +8,7 @@ module Lotus
8
8
  #
9
9
  # @see Lotus::Router#resource
10
10
  # @see Lotus::Router#resources
11
- class Options < Hash
11
+ class Options
12
12
  # @api private
13
13
  # @since 0.1.0
14
14
  attr_reader :actions
@@ -40,7 +40,32 @@ module Lotus
40
40
  except = Array(options.delete(:except))
41
41
  @actions = ( actions & only ) - except
42
42
 
43
- merge! options
43
+ @options = options
44
+ end
45
+
46
+ # Return the option for the given key
47
+ #
48
+ # @param key [Symbol] the key that should be searched
49
+ #
50
+ # @return [Object,nil] returns the object associated to the given key
51
+ # or nil, if missing.
52
+ #
53
+ # @api private
54
+ # @since 0.1.1
55
+ def [](key)
56
+ @options[key]
57
+ end
58
+
59
+ # Merge the current options with the given hash, without mutating self.
60
+ #
61
+ # @param hash [Hash] the hash to be merged
62
+ #
63
+ # @return [Hash] the result of the merging operation
64
+ #
65
+ # @api private
66
+ # @since 0.1.1
67
+ def merge(hash)
68
+ @options.merge(hash)
44
69
  end
45
70
  end
46
71
  end
data/lotus-router.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'http://lotusrb.org'
14
14
  spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files`.split($/)
16
+ spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md lotus-router.gemspec`.split($/)
17
17
  spec.executables = []
18
18
  spec.test_files = spec.files.grep(%r{^(test)/})
19
19
  spec.require_paths = ['lib']
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.0
4
+ version: 0.1.1
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-01-23 00:00:00.000000000 Z
11
+ date: 2014-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http_router
@@ -87,21 +87,9 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
- - ".coveralls.yml"
91
- - ".gitignore"
92
- - ".travis.yml"
93
- - ".yardopts"
94
- - Gemfile
95
- - LICENSE.txt
90
+ - CHANGELOG.md
91
+ - LICENSE.md
96
92
  - README.md
97
- - Rakefile
98
- - benchmarks/callable
99
- - benchmarks/named_routes
100
- - benchmarks/resource
101
- - benchmarks/resources
102
- - benchmarks/routes
103
- - benchmarks/run.sh
104
- - benchmarks/utils.rb
105
93
  - lib/lotus-router.rb
106
94
  - lib/lotus/router.rb
107
95
  - lib/lotus/router/version.rb
@@ -116,20 +104,6 @@ files:
116
104
  - lib/lotus/routing/resources/action.rb
117
105
  - lib/lotus/routing/route.rb
118
106
  - lotus-router.gemspec
119
- - test/fixtures.rb
120
- - test/integration/client_error_test.rb
121
- - test/integration/pass_on_response_test.rb
122
- - test/named_routes_test.rb
123
- - test/namespace_test.rb
124
- - test/new_test.rb
125
- - test/redirect_test.rb
126
- - test/resource_test.rb
127
- - test/resources_test.rb
128
- - test/routing/endpoint_resolver_test.rb
129
- - test/routing/resource/options_test.rb
130
- - test/routing_test.rb
131
- - test/test_helper.rb
132
- - test/version_test.rb
133
107
  homepage: http://lotusrb.org
134
108
  licenses:
135
109
  - MIT
@@ -150,23 +124,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
124
  version: '0'
151
125
  requirements: []
152
126
  rubyforge_project:
153
- rubygems_version: 2.2.0
127
+ rubygems_version: 2.2.2
154
128
  signing_key:
155
129
  specification_version: 4
156
130
  summary: Ruby HTTP Router for Lotus
157
- test_files:
158
- - test/fixtures.rb
159
- - test/integration/client_error_test.rb
160
- - test/integration/pass_on_response_test.rb
161
- - test/named_routes_test.rb
162
- - test/namespace_test.rb
163
- - test/new_test.rb
164
- - test/redirect_test.rb
165
- - test/resource_test.rb
166
- - test/resources_test.rb
167
- - test/routing/endpoint_resolver_test.rb
168
- - test/routing/resource/options_test.rb
169
- - test/routing_test.rb
170
- - test/test_helper.rb
171
- - test/version_test.rb
131
+ test_files: []
172
132
  has_rdoc: