Skip to content

Commit 51fb5c4

Browse files
committed
Allowing arbitrary option hashes along with the api declaration.
1 parent b544913 commit 51fb5c4

File tree

4 files changed

+69
-40
lines changed

4 files changed

+69
-40
lines changed

README.markdown

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ Grape exposes arrays of API versions and compiled routes. Each route contains a
105105

106106
TwitterAPI::versions # yields [ 'v1', 'v2' ]
107107
TwitterAPI::routes # yields an array of Grape::Route objects
108+
TwitterAPI::routes[0].route_version # yields 'v1'
109+
110+
Grape also supports storing additional options with the route information. This can be useful for generating documentation.
111+
The optional hash that follows the API path may contain any number of keys and values are accessible via `route_[name]`.
112+
113+
class StringAPI < Grape::API
114+
get :split, { :params => [ :string, :token ] } do
115+
params[:string].split(params[:token])
116+
end
117+
end
118+
119+
StringAPI::routes[0].route_params # yields an array [ :string, :token ]
108120

109121
## Note on Patches/Pull Requests
110122

lib/grape/api.rb

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,25 +182,32 @@ def http_digest(options = {}, &block)
182182
# {:hello => 'world'}
183183
# end
184184
# end
185-
def route(methods, paths, &block)
185+
def route(methods, paths = ['/'], route_options = {}, &block)
186186
methods = Array(methods)
187-
paths = ['/'] if paths == []
187+
188+
paths = ['/'] if ! paths || paths == []
188189
paths = Array(paths)
190+
189191
endpoint = build_endpoint(&block)
190-
options = {}
191192

192-
options[:version] = /#{version.join('|')}/ if version
193+
endpoint_options = {}
194+
endpoint_options[:version] = /#{version.join('|')}/ if version
193195

194196
methods.each do |method|
195197
paths.each do |path|
198+
196199
compiled_path = compile_path(path)
197-
path = Rack::Mount::Strexp.compile(compiled_path, options, %w( / . ? ), true)
200+
path = Rack::Mount::Strexp.compile(compiled_path, endpoint_options, %w( / . ? ), true)
198201
request_method = (method.to_s.upcase unless method == :any)
199-
routes << Route.new(prefix,
200-
version ? version.join('|') : nil,
201-
namespace,
202-
request_method,
203-
compiled_path)
202+
203+
routes << Route.new({
204+
:prefix => prefix,
205+
:version => version ? version.join('|') : nil,
206+
:namespace => namespace,
207+
:method => request_method,
208+
:path => compiled_path}
209+
.merge(route_options || {}))
210+
204211
route_set.add_route(endpoint,
205212
:path_info => path,
206213
:request_method => request_method
@@ -209,11 +216,11 @@ def route(methods, paths, &block)
209216
end
210217
end
211218

212-
def get(*paths, &block); route('GET', paths, &block) end
213-
def post(*paths, &block); route('POST', paths, &block) end
214-
def put(*paths, &block); route('PUT', paths, &block) end
215-
def head(*paths, &block); route('HEAD', paths, &block) end
216-
def delete(*paths, &block); route('DELETE', paths, &block) end
219+
def get(paths = ['/'], options = {}, &block); route('GET', paths, options, &block) end
220+
def post(paths = ['/'], options = {}, &block); route('POST', paths, options, &block) end
221+
def put(paths = ['/'], options = {}, &block); route('PUT', paths, options, &block) end
222+
def head(paths = ['/'], options = {}, &block); route('HEAD', paths, options, &block) end
223+
def delete(paths = ['/'], options = {}, &block); route('DELETE', paths, options, &block) end
217224

218225
def namespace(space = nil, &block)
219226
if space || block_given?

lib/grape/route.rb

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,20 @@ module Grape
33
# A compiled route for inspection.
44
class Route
55

6-
attr_reader :prefix
7-
attr_reader :version
8-
attr_reader :namespace
9-
attr_reader :method
10-
attr_reader :path
6+
def initialize(options = {})
7+
@options = options || {}
8+
end
119

12-
def initialize(prefix, version, namespace, method, path)
13-
@prefix = prefix
14-
@version = version
15-
@namespace = namespace
16-
@method = method
17-
@path = path
10+
def method_missing(method_id, *arguments)
11+
if match = /route_(?<name>[_a-zA-Z]\w*)/.match(method_id.to_s)
12+
@options[match['name'].to_sym]
13+
else
14+
super
15+
end
1816
end
1917

2018
def to_s
21-
"#{method} #{path}"
19+
"#{route_method} #{route_path}"
2220
end
2321

2422
end

spec/grape/api_spec.rb

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def app; subject end
171171
end
172172

173173
it 'should allow for multiple paths' do
174-
subject.get("/abc", "/def") do
174+
subject.get(["/abc", "/def"]) do
175175
"foo"
176176
end
177177

@@ -223,19 +223,16 @@ def app; subject end
223223

224224
it 'should allow for multipart paths' do
225225

226-
227226
subject.route([:get, :post], '/:id/first') do
228227
"first"
229228
end
230-
231229

232230
subject.route([:get, :post], '/:id') do
233231
"ola"
234232
end
235233
subject.route([:get, :post], '/:id/first/second') do
236234
"second"
237235
end
238-
239236

240237
get '/1'
241238
last_response.body.should eql 'ola'
@@ -633,9 +630,9 @@ def two
633630
it "returns one route" do
634631
subject.routes.size.should == 1
635632
route = subject.routes[0]
636-
route.version.should be_nil
637-
route.path.should == "/ping(.:format)"
638-
route.method.should == "GET"
633+
route.route_version.should be_nil
634+
route.route_path.should == "/ping(.:format)"
635+
route.route_method.should == "GET"
639636
end
640637
end
641638
describe "api structure with two versions and a namespace" do
@@ -661,18 +658,33 @@ class TwitterAPI < Grape::API
661658
end
662659
it "should set route paths" do
663660
TwitterAPI::routes.size.should == 2
664-
TwitterAPI::routes[0].path.should == "/:version/version(.:format)"
665-
TwitterAPI::routes[1].path.should == "/p/:version/n1/n2/version(.:format)"
661+
TwitterAPI::routes[0].route_path.should == "/:version/version(.:format)"
662+
TwitterAPI::routes[1].route_path.should == "/p/:version/n1/n2/version(.:format)"
666663
end
667664
it "should set route versions" do
668-
TwitterAPI::routes[0].version.should == 'v1'
669-
TwitterAPI::routes[1].version.should == 'v2'
665+
TwitterAPI::routes[0].route_version.should == 'v1'
666+
TwitterAPI::routes[1].route_version.should == 'v2'
670667
end
671668
it "should set a nested namespace" do
672-
TwitterAPI::routes[1].namespace.should == "/n1/n2"
669+
TwitterAPI::routes[1].route_namespace.should == "/n1/n2"
673670
end
674671
it "should set prefix" do
675-
TwitterAPI::routes[1].prefix.should == 'p'
672+
TwitterAPI::routes[1].route_prefix.should == 'p'
673+
end
674+
end
675+
describe "api structure with additional parameters" do
676+
before(:each) do
677+
subject.get :split, { :params => [ :string, :token ] } do
678+
params[:string].split(params[:token])
679+
end
680+
end
681+
it "should split a string" do
682+
get "/split", :string => "a,b,c", :token => ','
683+
last_response.body.should == '["a", "b", "c"]'
684+
end
685+
it "should set route_params" do
686+
subject.routes.size.should == 1
687+
subject.routes[0].route_params.should == [ :string, :token ]
676688
end
677689
end
678690
end

0 commit comments

Comments
 (0)