Nested params (e.g., "post[title]=Hello") [#70]
This is based largely on manveru's example implementation: http://paste.linuxhelp.tv/pastes/view/15309 NOTE: we should plan on ripping this out once nested params makes it into Rack.
This commit is contained in:
parent
4a75d9edfb
commit
1fa9807f4b
4
CHANGES
4
CHANGES
|
@ -8,6 +8,10 @@
|
|||
Documentation on using these features is forth-coming; the following
|
||||
provides the basic gist: http://gist.github.com/38605
|
||||
|
||||
* Parameters with subscripts are now parsed into a nested/recursive
|
||||
Hash structure. e.g., "post[title]=Hello&post[body]=World" yields
|
||||
params: {'post' => {'title' => 'Hello', 'body' => 'World'}}.
|
||||
|
||||
* Regular expressions may now be used in route pattens; captures are
|
||||
available at "params[:captures]".
|
||||
|
||||
|
|
|
@ -331,8 +331,7 @@ module Sinatra
|
|||
self.class.filters.each {|block| instance_eval(&block)}
|
||||
if routes = self.class.routes[@request.request_method]
|
||||
path = @request.path_info
|
||||
original_params = Hash.new{ |hash,k| hash[k.to_s] if Symbol === k }
|
||||
original_params.merge! @request.params
|
||||
original_params = nested_params(@request.params)
|
||||
|
||||
routes.each do |pattern, keys, conditions, method_name|
|
||||
if pattern =~ path
|
||||
|
@ -352,8 +351,7 @@ module Sinatra
|
|||
else
|
||||
{}
|
||||
end
|
||||
@params = original_params.dup
|
||||
@params.merge!(params)
|
||||
@params = original_params.merge(params)
|
||||
|
||||
catch(:pass) {
|
||||
conditions.each { |cond|
|
||||
|
@ -366,6 +364,22 @@ module Sinatra
|
|||
raise NotFound
|
||||
end
|
||||
|
||||
def nested_params(params)
|
||||
return indifferent_hash.merge(params) if !params.keys.join.include?('[')
|
||||
params.inject indifferent_hash do |res, (key,val)|
|
||||
if key =~ /\[.*\]/
|
||||
splat = key.scan(/(^[^\[]+)|\[([^\]]+)\]/).flatten.compact
|
||||
head, last = splat[0..-2], splat[-1]
|
||||
head.inject(res){ |s,v| s[v] ||= indifferent_hash }[last] = val
|
||||
end
|
||||
res
|
||||
end
|
||||
end
|
||||
|
||||
def indifferent_hash
|
||||
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
||||
end
|
||||
|
||||
def invoke(handler)
|
||||
res = catch(:halt) {
|
||||
if handler.respond_to?(:call)
|
||||
|
|
|
@ -119,6 +119,63 @@ describe "Routing" do
|
|||
assert ok?
|
||||
end
|
||||
|
||||
it "supports basic nested params" do
|
||||
mock_app {
|
||||
get '/hi' do
|
||||
params["person"]["name"]
|
||||
end
|
||||
}
|
||||
|
||||
get "/hi?person[name]=John+Doe"
|
||||
assert ok?
|
||||
assert_equal "John Doe", body
|
||||
end
|
||||
|
||||
it "exposes nested params with indifferent hash" do
|
||||
mock_app {
|
||||
get '/testme' do
|
||||
assert_equal 'baz', params['bar']['foo']
|
||||
assert_equal 'baz', params['bar'][:foo]
|
||||
'well, alright'
|
||||
end
|
||||
}
|
||||
get '/testme?bar[foo]=baz'
|
||||
assert_equal 'well, alright', body
|
||||
end
|
||||
|
||||
it "supports deeply nested params" do
|
||||
input = {
|
||||
'browser[chrome][engine][name]' => 'V8',
|
||||
'browser[chrome][engine][version]' => '1.0',
|
||||
'browser[firefox][engine][name]' => 'spidermonkey',
|
||||
'browser[firefox][engine][version]' => '1.7.0',
|
||||
'emacs[map][goto-line]' => 'M-g g',
|
||||
'emacs[version]' => '22.3.1',
|
||||
'paste[name]' => 'hello world',
|
||||
'paste[syntax]' => 'ruby'
|
||||
}
|
||||
expected = {
|
||||
"emacs" => {
|
||||
"map" => { "goto-line" => "M-g g" },
|
||||
"version" => "22.3.1"
|
||||
},
|
||||
"browser" => {
|
||||
"firefox" => {"engine" => {"name"=>"spidermonkey", "version"=>"1.7.0"}},
|
||||
"chrome" => {"engine" => {"name"=>"V8", "version"=>"1.0"}}
|
||||
},
|
||||
"paste" => {"name"=>"hello world", "syntax"=>"ruby"}
|
||||
}
|
||||
mock_app {
|
||||
get '/foo' do
|
||||
assert_equal expected, params
|
||||
'looks good'
|
||||
end
|
||||
}
|
||||
get "/foo?#{param_string(input)}"
|
||||
assert ok?
|
||||
assert_equal 'looks good', body
|
||||
end
|
||||
|
||||
it "supports paths that include spaces" do
|
||||
mock_app {
|
||||
get '/path with spaces' do
|
||||
|
|
Loading…
Reference in New Issue