Skip to content

Commit

Permalink
References #60. Adds mount class method to mount bare Rack apps. Next…
Browse files Browse the repository at this point in the history
… up, inheritable settings.
  • Loading branch information
Michael Bleigh committed Sep 2, 2011
1 parent 83762d0 commit 6c60b4c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 11 deletions.
33 changes: 25 additions & 8 deletions lib/grape/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ def settings_stack
def set(key, value)
@settings.last[key.to_sym] = value
end

# Merge multiple setting in at once. Mostly for internal use.
def merge_settings(settings)
settings_stack.last.merge!(settings)
end

# Define a root URL prefix for your entire
# API.
Expand Down Expand Up @@ -180,6 +185,15 @@ def http_digest(options = {}, &block)
auth :http_digest, options, &block
end

def mount(mounts)
mounts.each_pair do |app, path|
next unless app.respond_to?(:call)
route_set.add_route(app,
path_info: compile_path(path, false)
)
end
end

# Defines a route that will be recognized
# by the Grape API.
#
Expand All @@ -200,16 +214,12 @@ def route(methods, paths = ['/'], route_options = {}, &block)

endpoint = build_endpoint(&block)

endpoint_options = {}
endpoint_options[:version] = /#{version.join('|')}/ if version

route_options ||= {}

methods.each do |method|
paths.each do |path|

compiled_path = compile_path(path)
path = Rack::Mount::Strexp.compile(compiled_path, endpoint_options, %w( / . ? ), true)
prepared_path = prepare_path(path)
path = compile_path(path)
regex = Rack::Mount::RegexpWithNamedGroups.new(path)
path_params = regex.named_captures.map { |nc| nc[0] } - [ 'version', 'format' ]
path_params |= (route_options[:params] || [])
Expand All @@ -220,7 +230,7 @@ def route(methods, paths = ['/'], route_options = {}, &block)
:version => version ? version.join('|') : nil,
:namespace => namespace,
:method => request_method,
:path => compiled_path,
:path => prepared_path,
:params => path_params}))

route_set.add_route(endpoint,
Expand Down Expand Up @@ -352,7 +362,7 @@ def route_set
@route_set ||= Rack::Mount::RouteSet.new
end

def compile_path(path)
def prepare_path(path)
parts = []
parts << prefix if prefix
parts << ':version' if version
Expand All @@ -361,6 +371,13 @@ def compile_path(path)
parts.last << '(.:format)'
Rack::Mount::Utils.normalize_path(parts.join('/'))
end

def compile_path(path, anchor = true)
endpoint_options = {}
endpoint_options[:version] = /#{version.join('|')}/ if version

Rack::Mount::Strexp.compile(prepare_path(path), endpoint_options, %w( / . ? ), anchor)
end
end

reset!
Expand Down
30 changes: 27 additions & 3 deletions spec/grape/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def app; subject end
subject.version :v1

subject.namespace :awesome do
compile_path('hello').should == '/rad/:version/awesome/hello(.:format)'
prepare_path('hello').should == '/rad/:version/awesome/hello(.:format)'
end
end

Expand Down Expand Up @@ -151,9 +151,9 @@ def app; subject end
it 'should be callable with nil just to push onto the stack' do
subject.namespace do
version 'v2'
compile_path('hello').should == '/:version/hello(.:format)'
prepare_path('hello').should == '/:version/hello(.:format)'
end
subject.send(:compile_path, 'hello').should == '/hello(.:format)'
subject.send(:prepare_path, 'hello').should == '/hello(.:format)'
end

%w(group resource resources segment).each do |als|
Expand Down Expand Up @@ -755,4 +755,28 @@ class CommunicationError < RuntimeError; end
end
end

describe '#settings=' do
it 'should set the last settings on the stack' do
subject.merge_settings :biff => 'bap'
subject.settings[:biff].should == 'bap'
end
end

describe '.mount.' do
context 'with a bare rack app' do
before do
subject.mount lambda{|env| [200, {}, ["MOUNTED"]]} => '/mounty'
end

it 'should make a bare Rack app available at the endpoint' do
get '/mounty'
last_response.body.should == 'MOUNTED'
end

it 'should anchor the routes, passing all subroutes to it' do
get '/mounty/awesome'
last_response.body.should == 'MOUNTED'
end
end
end
end

0 comments on commit 6c60b4c

Please sign in to comment.