Skip to content

Commit

Permalink
Merge branch 'master' into 0.2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
jodosha committed Dec 11, 2014
2 parents 0152063 + c9854ab commit b9f1726
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -11,7 +11,6 @@ rvm:
- 2.1.4
- 2.1.5
- 2.2
- rbx-2

matrix:
include:
Expand All @@ -21,3 +20,4 @@ matrix:
env: JRUBY_OPTS="--2.1"
allow_failures:
- rvm: jruby-head
- rbx-2
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -22,7 +22,7 @@ Rack compatible, lightweight and fast HTTP Router for [Lotus](http://lotusrb.org

## Rubies

__Lotus::Router__ supports Ruby (MRI) 2+, JRuby 1.7 (with 2.0 mode) and Rubinius 2.3.0+.
__Lotus::Router__ supports Ruby (MRI) 2+, JRuby 1.7 (with 2.0 mode)


## Installation
Expand Down
4 changes: 4 additions & 0 deletions lib/lotus/router.rb
Expand Up @@ -170,6 +170,10 @@ def initialize(options = {}, &blk)
define(&blk)
end

def routes
self
end

# To support defining routes in the `define` wrapper.
#
# @param blk [Proc] the block to define the routes
Expand Down
9 changes: 9 additions & 0 deletions lib/lotus/routing/route.rb
Expand Up @@ -44,6 +44,15 @@ def generate(resolver, options = {}, &endpoint)
self
end

# Introspect the given route to understand if there is a wrapped
# Lotus::Router
#
# @since x.x.x
# @api private
def nested_router
dest.routes if dest.respond_to?(:routes)
end

private
def to=(dest = nil, &blk)
self.to dest, &blk
Expand Down
90 changes: 81 additions & 9 deletions lib/lotus/routing/routes_inspector.rb
@@ -1,3 +1,5 @@
require 'lotus/utils/path_prefix'

module Lotus
module Routing
# Routes inspector
Expand All @@ -10,6 +12,12 @@ class RoutesInspector
# @api private
FORMATTER = "%<name>20s %<methods>-10s %<path>-30s %<endpoint>-30s\n".freeze

# Default HTTP methods separator
#
# @since x.x.x
# @api private
HTTP_METHODS_SEPARATOR = ', '.freeze

# Instantiate a new inspector
#
# @return [Lotus::Routing::RoutesInspector] the new instance
Expand All @@ -23,6 +31,7 @@ def initialize(routes)
# Return a formatted string that describes all the routes
#
# @param formatter [String] the optional formatter for a route
# @param base_path [String] the base path of a nested route
#
# @return [String] routes pretty print
#
Expand Down Expand Up @@ -63,34 +72,97 @@ def initialize(routes)
# | GET, HEAD | login | /login | Sessions::New |
# | POST | | /login | Sessions::Create |
# | GET, HEAD | logout | /logout | Sessions::Destroy |
def to_s(formatter = FORMATTER)
result = ""
#
# @example Nested routes
# require 'lotus/router'
#
# class AdminLotusApp
# def call(env)
# end
# def routes
# Lotus::Router.new {
# get '/home', to: 'home#index'
# }
# end
# end
#
# router = Lotus::Router.new {
# get '/fakeroute', to: 'fake#index'
# mount AdminLotusApp, at: '/admin'
# mount Lotus::Router.new {
# get '/posts', to: 'posts#index'
# mount Lotus::Router.new {
# get '/comments', to: 'comments#index'
# }, at: '/second_mount'
# }, at: '/api'
# }
#
# formatter = "| %{methods} | %{name} | %{path} | %{endpoint} |\n"
#
# puts router.inspector.to_s(formatter)
# # => | GET, HEAD | | /fakeroute | Fake::Index |
# | GET, HEAD | | /admin/home | Home::Index |
# | GET, HEAD | | /api/posts | Posts::Index |
# | GET, HEAD | | /api/second_mount/comments | Comments::Index |
def to_s(formatter = FORMATTER, base_path = nil)
base_path = Utils::PathPrefix.new(base_path)
result = ''

# TODO refactoring: replace conditional with polymorphism
# We're exposing too much knowledge from Routing::Route:
# #path_for_generation and #base_path
@routes.each do |route|
result << formatter % inspect_route(route)
result << if router = route.nested_router
inspect_router(formatter, router, route, base_path)
else
inspect_route(formatter, route, base_path)
end
end

result
end

private
# Return a Hash compatible with formatter

# Returns a string representation of the given route
#
# @return [Hash] serialized route
# @param formatter [String] the template for the output
# @param route [Lotus::Routing::Route] a route
# @param base_path [Lotus::Utils::PathPrefix] the base path
#
# @return [String] serialized route
#
# @since x.x.x
# @api private
#
# @see Lotus::Routing::RoutesInspector#FORMATTER
# @see Lotus::Routing::RoutesInspector#to_s
def inspect_route(route)
Hash[
def inspect_route(formatter, route, base_path)
formatter % Hash[
name: route.name,
methods: route.request_methods.to_a.join(", "),
path: route.original_path,
methods: route.request_methods.to_a.join(HTTP_METHODS_SEPARATOR),
path: base_path.join(route.path_for_generation),
endpoint: route.dest.inspect
]
end

# Returns a string representation of the given router
#
# @param formatter [String] the template for the output
# @param route [Lotus::Routing::Route] a route
# @param route [Lotus::Router] a router
# @param base_path [Lotus::Utils::PathPrefix] the base path
#
# @return [String] serialized routes from router
#
# @since x.x.x
# @api private
#
# @see Lotus::Routing::RoutesInspector#FORMATTER
# @see Lotus::Routing::RoutesInspector#to_s
def inspect_router(formatter, router, route, base_path)
router.inspector.to_s(formatter, base_path.join(route.path_for_generation))
end
end
end
end
50 changes: 50 additions & 0 deletions test/routing/routes_inspector_test.rb
Expand Up @@ -202,5 +202,55 @@ class Index
end
end
end

describe 'nested routes' do
before do
class AdminLotusApp
def call(env)
end

def routes
Lotus::Router.new do
get '/home', to: 'home#index'
end
end
end

inner_router = Lotus::Router.new {
get '/comments', to: 'comments#index'
}
nested_router = Lotus::Router.new {
get '/posts', to: 'posts#index'
mount inner_router, at: '/second_mount'
}

@router = Lotus::Router.new do
get '/fakeroute', to: 'fake#index'
mount AdminLotusApp, at: '/admin'
mount nested_router, at: '/api'
mount RackMiddleware, at: '/class'
mount RackMiddlewareInstanceMethod, at: '/instance_from_class'
mount RackMiddlewareInstanceMethod.new, at: '/instance'
end
end

it 'inspect routes' do
formatter = "| %{methods} | %{name} | %{path} | %{endpoint} |\n"
expectations = [
%(| GET, HEAD | | /fakeroute | Fake::Index |),
%(| GET, HEAD | | /admin/home | Home::Index |),
%(| GET, HEAD | | /api/posts | Posts::Index |),
%(| GET, HEAD | | /api/second_mount/comments | Comments::Index |),
%(| | | /class | RackMiddleware |),
%(| | | /instance_from_class | #<RackMiddlewareInstanceMethod> |),
%(| | | /instance | #<RackMiddlewareInstanceMethod> |)
]

actual = @router.inspector.to_s(formatter)
expectations.each do |expectation|
actual.must_include(expectation)
end
end
end
end
end

0 comments on commit b9f1726

Please sign in to comment.