我最近申请了一份 Ruby 工作,并被要求编写一个方法来“编写一个名为“query_to_hash”的 Ruby 函数,该函数将单个字符串参数作为 HTTP 查询字符串(例如foo=bar&abc=1%202%203
)并返回名称/值对的哈希,如下所示:
{"foo" => "bar", "abc" => "1 2 3"}
我提供了附加的代码示例,并得到了一些反馈,表明我的 Ruby 风格不是他们想要的。
我现在很想知道开发人员会在附件中看到哪些风格问题,并希望得到建设性的反馈。
require 'rubygems'
require 'uri'
require 'rack'
include Rack::Utils
$SAFE = 3
# HTTP Query string (from wikipedia)
#field1=value1&field2=value2&field3=value3...
# The query string is composed of a series of field-value pairs.
# Within each pair, the field name and value are separated by an equals sign. The equals sign may be omitted if the value is an empty string.
# The series of pairs is separated by the ampersand, '&' (or semicolon, ';' for URLs embedded in HTML and not generated by a <form>...</form>; see below).
# While there is no definitive standard, most web frameworks allow multiple values to be associated with a single field[3][4]:
# field1=value1&field1=value2&field1=value3...
def query_to_hash(qry, sep = '&')
# assume input string conforms to spec (no validation)
# assume only & or ; is used - not both
# return a null string if value is not defined
# return null hash if query is null string
# return array of values in hash if field has multiple values
#@qry = qry.gsub(/%20/, " ")
@qry = URI.unescape(qry)
rtn = Hash.new {|h,k| h[k]=[]}
if @qry == "" then
# return an empty hash
#
return {}
else
qry_a = @qry.split(sep)
end
qry_a.each do |fv_pair|
pair = fv_pair.split('=')
# append multiple values if needed and ensure that null values are accommodated
#
rtn[pair[0]] << pair[1] ||= ""
end
# collapse array if it contains only one item
#
rtn.each{|k,v| rtn[k] = *v if v.length == 1}
end
puts "Using 'query_to_hash' method:"
puts
test_values = %w[foo=bar&abc=1%202%203
foo&abc=1%202%203
foo=&abc=1%202%203
foo=bar&foo=boo&abc=1%202%203
]
test_values.each { |v| puts "#{sprintf("%30s",v)} is returned as #{query_to_hash(v).inspect}" }
test_values = %w[ foo=bar;foo=boo;abc=1%202%203
foo=bar;foo=boo;abc=1%0A2%203
foo=bar;foo=boo;abc=1%092%0D3
]
test_values.each { |v| puts "#{sprintf("%30s",v)} is returned as #{query_to_hash(v, ';').inspect}" }
puts "#{sprintf("%30s", "null string")} is returned as #{query_to_hash("").inspect}"
# compare with Rack::Utils::parse_query
#
puts
puts "Using 'Rack::Utils::parse_query' method:"
puts
test_values = %w[foo=bar&abc=1%202%203
foo&abc=1%202%203
foo=&abc=1%202%203
foo=bar&foo=boo&abc=1%202%203
]
test_values.each { |v| puts "#{sprintf("%30s",v)} is returned as #{parse_query(v).inspect}" }
test_values = %w[ foo=bar;foo=boo;abc=1%202%203
foo=bar;foo=boo;abc=1%0A2%203
foo=bar;foo=boo;abc=1%092%0D3
]
test_values.each { |v| puts "#{sprintf("%30s",v)} is returned as #{parse_query(v, ';').inspect}" }
puts "#{sprintf("%30s", "null string")} is returned as #{parse_query("").inspect}"