Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
implement Padrino::Utils.build_uri_query to replace AS Hash#to_query
  • Loading branch information
ujifgc committed Oct 29, 2015
1 parent dbee3a4 commit c42ffc4
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 16 deletions.
30 changes: 15 additions & 15 deletions padrino-core/test/test_params_protection.rb
@@ -1,12 +1,12 @@
require File.expand_path(File.dirname(__FILE__) + '/helper')
require 'active_support/core_ext/hash/conversions'

describe "Padrino::ParamsProtection" do
before do
@teri = { 'name' => 'Teri Bauer', 'position' => 'baby' }
@kim = { 'name' => 'Kim Bauer', 'position' => 'daughter', 'child' => @teri }
@jack = { 'name' => 'Jack Bauer', 'position' => 'terrorist', 'child' => @kim }
@family = { 'name' => 'Bauer', 'persons' => { 1 => @teri, 2 => @kim, 3 => @jack } }
@jack_query = Padrino::Utils.build_uri_query(@jack)
end

it 'should drop all parameters except allowed ones' do
Expand All @@ -17,7 +17,7 @@
''
end
end
post '/basic?' + @jack.to_query
post '/basic?' + @jack_query
assert_equal({ 'name' => @jack['name'] }, result)
end

Expand All @@ -29,7 +29,7 @@
''
end
end
post '/basic?' + @jack.to_query
post '/basic?' + @jack_query
assert_equal(@jack, result)
end

Expand All @@ -41,7 +41,7 @@
''
end
end
post '/basic?' + @jack.to_query
post '/basic?' + @jack_query
assert_equal(
[
{ 'name' => @jack['name'], 'child' => { 'name' => @kim['name'], 'child' => { 'name' => @teri['name'] } } },
Expand All @@ -59,7 +59,7 @@
''
end
end
post '/basic?' + @jack.to_query
post '/basic?' + @jack_query
assert_equal({ 'name' => @jack['name'], 'position' => 'anti-terrorist' }, result)
end

Expand All @@ -71,7 +71,7 @@
''
end
end
post '/basic/24/42?' + @jack.to_query
post '/basic/24/42?' + @jack_query
assert_equal({ 'name' => @jack['name'], 'id' => '24', 'tag' => '42' }, result)
end

Expand All @@ -83,7 +83,7 @@
''
end
end
post '/basic/24?' + @jack.to_query
post '/basic/24?' + @jack_query
assert_equal({ 'id' => '24' }, result)
end

Expand All @@ -99,9 +99,9 @@
''
end
end
get '/hide/1?' + @jack.to_query
get '/hide/1?' + @jack_query
assert_equal({"id"=>"1"}, result)
get '/show/1?' + @jack.to_query
get '/show/1?' + @jack_query
assert_equal({"id"=>"1"}.merge(@jack), result)
end

Expand Down Expand Up @@ -133,13 +133,13 @@
end
end
end
post '/persons/create?' + @jack.to_query
post '/persons/create?' + @jack_query
assert_equal({ 'name' => @jack['name'], 'position' => 'terrorist' }, result)
post '/persons/update/1?name=Chloe+O\'Brian&position=hacker'
assert_equal({ 'id' => '1', 'name' => 'Chloe O\'Brian' }, result)
post '/persons/delete?' + @jack.to_query
post '/persons/delete?' + @jack_query
assert_equal(@jack, result)
post '/persons/destroy/1?' + @jack.to_query
post '/persons/destroy/1?' + @jack_query
assert_equal({"id"=>"1"}, result)
get '/noparam?a=1;b=2'
assert_equal({}, result)
Expand All @@ -153,7 +153,7 @@
''
end
end
post '/family?' + @family.to_query
post '/family?' + Padrino::Utils.build_uri_query(@family)
assert_equal({"persons" => {"3" => {"name" => @jack["name"]}, "2" => {"name" => @kim["name"]}, "1" => {"name" => @teri["name"]}}}, result)
end

Expand All @@ -165,7 +165,7 @@
''
end
end
post '/family?' + { :names => %w{Jack Kim Teri} }.to_query
post '/family?' + Padrino::Utils.build_uri_query(:names => %w{Jack Kim Teri})
assert_equal({"names" => %w[Jack Kim Teri]}, result)
end

Expand All @@ -177,7 +177,7 @@
''
end
end
post '/i?' + { :gotta => { :what => 'go', :who => 'self' } }.to_query
post '/i?' + Padrino::Utils.build_uri_query(:gotta => { :what => 'go', :who => 'self' })
assert_equal({"gotta" => {"what" => "go"}}, result)
end

Expand Down
2 changes: 1 addition & 1 deletion padrino-core/test/test_routing.rb
Expand Up @@ -2077,7 +2077,7 @@ def authorize(username, password)
mock_app do
get(:index) { "%s %s" % [params[:account][:name], params[:account][:surname]] }
end
get "/?" + { :account => { :name => 'foo', :surname => 'bar' } }.to_query
get "/?" + Padrino::Utils.build_uri_query(:account => { :name => 'foo', :surname => 'bar' })
assert_equal 'foo bar', body
get @app.url(:index, "account[name]" => "foo", "account[surname]" => "bar")
assert_equal 'foo bar', body
Expand Down
1 change: 1 addition & 0 deletions padrino-support/lib/padrino-support.rb
Expand Up @@ -14,6 +14,7 @@
require 'padrino-support/core_ext/string/colorize'
require 'padrino-support/core_ext/object_space'
require 'padrino-support/file_set'
require 'padrino-support/utils'


##
Expand Down
35 changes: 35 additions & 0 deletions padrino-support/lib/padrino-support/utils.rb
@@ -0,0 +1,35 @@
require 'cgi'

module Padrino
module Utils
extend self

##
# Builds an URI query from a Hash or any Object.
#
# Examples (~ marks here that output is actually escaped by CGI):
#
# Utils.build_uri_query(:a => 1, :b => 2) #=> "a=1&b=2"
# Utils.build_uri_query(:a => [1, 2]) #=> ~"a[]=1&a[]=2"
# Utils.build_uri_query([1, 2], 'namespace') #=> ~"namespace[]=1&namespace[]=2"
# Utils.build_uri_query(:a => { :d => 2 }, :b => 3) #=> ~"a[d]=2&b=3"
#
def build_uri_query(object, namespace = nil)
case object
when Hash
object.map do |key, value|
next if value == {} || value == []
build_uri_query(value, namespace ? "#{namespace}[#{key}]" : key)
end.compact.join('&')
when Array
fail ArgumentError, 'namespace is missing' unless namespace
(object.empty? ? [''] : object).map do |value|
build_uri_query(value, "#{namespace}[]")
end.join('&')
else
fail ArgumentError, 'namespace is missing' unless namespace
"#{CGI.escape(namespace.to_s)}=#{CGI.escape(object.to_s)}"
end
end
end
end
59 changes: 59 additions & 0 deletions padrino-support/test/test_utils.rb
@@ -0,0 +1,59 @@
require File.expand_path(File.dirname(__FILE__) + '/helper')

class MiniTest::Spec
def assert_query_equal(expected, actual, namespace=nil)
assert_equal expected.split('&').sort, Padrino::Utils.build_uri_query(actual, namespace).split('&').sort
end
end

describe 'Padrino::Utils.build_uri_query' do
it 'should do simple conversion' do
assert_query_equal 'a=10', :a => 10
end

it 'should do cgi escaping' do
assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d'
end

it 'should expand nested hashes' do
assert_query_equal 'person%5Blogin%5D=seckar&person%5Bname%5D=Nicholas',
:person => { :login => 'seckar', :name => 'Nicholas' }
end

it 'should expand deeply nested hashes' do
assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10',
{ :account => { :person => { :id => 20 } }, :person => {:id => 10} }
end

it 'should accept arrays' do
assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20',
:person => {:id => [10, 20]}
end

it 'should accept empty arrays' do
assert_query_equal "person%5B%5D=",
[],
'person'
end

it 'should expand nested hashes' do
assert_query_equal '',
{}
assert_query_equal 'a=1&b%5Bc%5D=3',
{ a: 1, b: { c: 3, d: {} } }
assert_query_equal '',
{ a: {b: {c: {}}} }
assert_query_equal 'b%5Bc%5D=false&b%5Be%5D=&b%5Bf%5D=&p=12',
{ p: 12, b: { c: false, e: nil, f: '' } }
assert_query_equal 'b%5Bc%5D=3&b%5Bf%5D=',
{ b: { c: 3, k: {}, f: '' } }
assert_query_equal 'b=3',
{a: [], b: 3}
end

it 'should accept namespace for hashes' do
assert_query_equal "user%5Bname%5D=Nakshay&user%5Bnationality%5D=Indian",
{ name: 'Nakshay', nationality: 'Indian' },
'user'
end
end

0 comments on commit c42ffc4

Please sign in to comment.