Rails params如何从字符串中解析散列
How does Rails params parse hash from string
我正在 Rails 上学习 Ruby 并且很好奇 params 方法是如何工作的。我明白它的作用,但是怎么做呢?
是否有一个内置方法可以像这样获取哈希字符串
"cat[name]"
并将其翻译成
{ :cat => { :name => <assigned_value> } }
?
我尝试自己编写 params 方法,但不确定如何在 ruby 中编写此功能。
GET 参数是从 ActionDispatch::Request#GET
设置的,它扩展了 Rack::Request#GET
,后者使用 Rack::QueryParser#parse_nested_query
。
POST 参数是从 ActionDispatch::Request#POST
设置的,它扩展了 Rack::Request#POST
,它使用 Rack::Multipart#parse_multipart
. That splays through several more files in lib/rack/multipart
。
这里是该方法功能的再现(注意:这不是该方法的工作原理)。感兴趣的辅助方法:#array_to_hash
和 #handle_nested_hash_array
require 'uri'
class Params
def initialize(req, route_params = {})
@params = {}
route_params.keys.each do |key|
handle_nested_hash_array([{key => route_params[key]}])
end
parse_www_encoded_form(req.query_string) if req.query_string
parse_www_encoded_form(req.body) if req.body
end
def [](key)
@params[key.to_sym] || @params[key.to_s]
end
def to_s
@params.to_s
end
class AttributeNotFoundError < ArgumentError; end;
private
def parse_www_encoded_form(www_encoded_form)
params_array = URI::decode_www_form(www_encoded_form).map do |k, v|
[parse_key(k), v]
end
params_array.map! do |sub_array|
array_to_hash(sub_array.flatten)
end
handle_nested_hash_array(params_array)
end
def handle_nested_hash_array(params_array)
params_array.each do |working_hash|
params = @params
while true
if params.keys.include?(working_hash.keys[0])
params = params[working_hash.keys[0]]
working_hash = working_hash[working_hash.keys[0]]
else
break
end
break if !working_hash.values[0].is_a?(Hash)
break if !params.values[0].is_a?(Hash)
end
params.merge!(working_hash)
end
end
def array_to_hash(params_array)
return params_array.join if params_array.length == 1
hash = {}
hash[params_array[0]] = array_to_hash(params_array.drop(1))
hash
end
def parse_key(key)
key.split(/\]\[|\[|\]/)
end
end
我正在 Rails 上学习 Ruby 并且很好奇 params 方法是如何工作的。我明白它的作用,但是怎么做呢?
是否有一个内置方法可以像这样获取哈希字符串
"cat[name]"
并将其翻译成
{ :cat => { :name => <assigned_value> } }
?
我尝试自己编写 params 方法,但不确定如何在 ruby 中编写此功能。
GET 参数是从 ActionDispatch::Request#GET
设置的,它扩展了 Rack::Request#GET
,后者使用 Rack::QueryParser#parse_nested_query
。
POST 参数是从 ActionDispatch::Request#POST
设置的,它扩展了 Rack::Request#POST
,它使用 Rack::Multipart#parse_multipart
. That splays through several more files in lib/rack/multipart
。
这里是该方法功能的再现(注意:这不是该方法的工作原理)。感兴趣的辅助方法:#array_to_hash
和 #handle_nested_hash_array
require 'uri'
class Params
def initialize(req, route_params = {})
@params = {}
route_params.keys.each do |key|
handle_nested_hash_array([{key => route_params[key]}])
end
parse_www_encoded_form(req.query_string) if req.query_string
parse_www_encoded_form(req.body) if req.body
end
def [](key)
@params[key.to_sym] || @params[key.to_s]
end
def to_s
@params.to_s
end
class AttributeNotFoundError < ArgumentError; end;
private
def parse_www_encoded_form(www_encoded_form)
params_array = URI::decode_www_form(www_encoded_form).map do |k, v|
[parse_key(k), v]
end
params_array.map! do |sub_array|
array_to_hash(sub_array.flatten)
end
handle_nested_hash_array(params_array)
end
def handle_nested_hash_array(params_array)
params_array.each do |working_hash|
params = @params
while true
if params.keys.include?(working_hash.keys[0])
params = params[working_hash.keys[0]]
working_hash = working_hash[working_hash.keys[0]]
else
break
end
break if !working_hash.values[0].is_a?(Hash)
break if !params.values[0].is_a?(Hash)
end
params.merge!(working_hash)
end
end
def array_to_hash(params_array)
return params_array.join if params_array.length == 1
hash = {}
hash[params_array[0]] = array_to_hash(params_array.drop(1))
hash
end
def parse_key(key)
key.split(/\]\[|\[|\]/)
end
end