Skip to content

Commit 6c60b4c

Browse files
author
Michael Bleigh
committed
References #60. Adds mount class method to mount bare Rack apps. Next up, inheritable settings.
1 parent 83762d0 commit 6c60b4c

File tree

2 files changed

+52
-11
lines changed

2 files changed

+52
-11
lines changed

lib/grape/api.rb

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ def settings_stack
5151
def set(key, value)
5252
@settings.last[key.to_sym] = value
5353
end
54+
55+
# Merge multiple setting in at once. Mostly for internal use.
56+
def merge_settings(settings)
57+
settings_stack.last.merge!(settings)
58+
end
5459

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

188+
def mount(mounts)
189+
mounts.each_pair do |app, path|
190+
next unless app.respond_to?(:call)
191+
route_set.add_route(app,
192+
path_info: compile_path(path, false)
193+
)
194+
end
195+
end
196+
183197
# Defines a route that will be recognized
184198
# by the Grape API.
185199
#
@@ -200,16 +214,12 @@ def route(methods, paths = ['/'], route_options = {}, &block)
200214

201215
endpoint = build_endpoint(&block)
202216

203-
endpoint_options = {}
204-
endpoint_options[:version] = /#{version.join('|')}/ if version
205-
206217
route_options ||= {}
207218

208219
methods.each do |method|
209220
paths.each do |path|
210-
211-
compiled_path = compile_path(path)
212-
path = Rack::Mount::Strexp.compile(compiled_path, endpoint_options, %w( / . ? ), true)
221+
prepared_path = prepare_path(path)
222+
path = compile_path(path)
213223
regex = Rack::Mount::RegexpWithNamedGroups.new(path)
214224
path_params = regex.named_captures.map { |nc| nc[0] } - [ 'version', 'format' ]
215225
path_params |= (route_options[:params] || [])
@@ -220,7 +230,7 @@ def route(methods, paths = ['/'], route_options = {}, &block)
220230
:version => version ? version.join('|') : nil,
221231
:namespace => namespace,
222232
:method => request_method,
223-
:path => compiled_path,
233+
:path => prepared_path,
224234
:params => path_params}))
225235

226236
route_set.add_route(endpoint,
@@ -352,7 +362,7 @@ def route_set
352362
@route_set ||= Rack::Mount::RouteSet.new
353363
end
354364

355-
def compile_path(path)
365+
def prepare_path(path)
356366
parts = []
357367
parts << prefix if prefix
358368
parts << ':version' if version
@@ -361,6 +371,13 @@ def compile_path(path)
361371
parts.last << '(.:format)'
362372
Rack::Mount::Utils.normalize_path(parts.join('/'))
363373
end
374+
375+
def compile_path(path, anchor = true)
376+
endpoint_options = {}
377+
endpoint_options[:version] = /#{version.join('|')}/ if version
378+
379+
Rack::Mount::Strexp.compile(prepare_path(path), endpoint_options, %w( / . ? ), anchor)
380+
end
364381
end
365382

366383
reset!

spec/grape/api_spec.rb

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def app; subject end
113113
subject.version :v1
114114

115115
subject.namespace :awesome do
116-
compile_path('hello').should == '/rad/:version/awesome/hello(.:format)'
116+
prepare_path('hello').should == '/rad/:version/awesome/hello(.:format)'
117117
end
118118
end
119119

@@ -151,9 +151,9 @@ def app; subject end
151151
it 'should be callable with nil just to push onto the stack' do
152152
subject.namespace do
153153
version 'v2'
154-
compile_path('hello').should == '/:version/hello(.:format)'
154+
prepare_path('hello').should == '/:version/hello(.:format)'
155155
end
156-
subject.send(:compile_path, 'hello').should == '/hello(.:format)'
156+
subject.send(:prepare_path, 'hello').should == '/hello(.:format)'
157157
end
158158

159159
%w(group resource resources segment).each do |als|
@@ -755,4 +755,28 @@ class CommunicationError < RuntimeError; end
755755
end
756756
end
757757

758+
describe '#settings=' do
759+
it 'should set the last settings on the stack' do
760+
subject.merge_settings :biff => 'bap'
761+
subject.settings[:biff].should == 'bap'
762+
end
763+
end
764+
765+
describe '.mount.' do
766+
context 'with a bare rack app' do
767+
before do
768+
subject.mount lambda{|env| [200, {}, ["MOUNTED"]]} => '/mounty'
769+
end
770+
771+
it 'should make a bare Rack app available at the endpoint' do
772+
get '/mounty'
773+
last_response.body.should == 'MOUNTED'
774+
end
775+
776+
it 'should anchor the routes, passing all subroutes to it' do
777+
get '/mounty/awesome'
778+
last_response.body.should == 'MOUNTED'
779+
end
780+
end
781+
end
758782
end

0 commit comments

Comments
 (0)