我试图在不破坏API使用方的情况下“猴子补丁”我们已部署的一些代码,基本上我想找到具有键值对的param,其值等于特定值('\ u0000')并将其设置为nil ,这是我所拥有的:
def traverse_param(key, value)
if value.is_a? Hash
value.each do |k, v|
return traverse_param(k, v)
end
end
if value == '\u0000'
value = nil
end
end
在Rails 5中,我无法将nil
传递给控制器,因为它将被强制转换为''
,并且我需要将nil
的param传递给执行以下工作的服务。 / p>
现在,因为我可以嵌套参数,所以这就是为什么我检查参数值是否为Hash
的原因。我使用了这个示例:
params = {:filters=>{:user=>{:disabled_at=>"\u0000"}, :importan_param=>1}}
params.each { |k, v| traverse_param(k,v) }
我正在尝试修改该值,但是它似乎不起作用?在调试时,代码输入正确的位置,但未产生预期的结果。有什么想法吗?
答案 0 :(得分:1)
因此,您面临的问题是您正在修改局部变量value
。如果您将整个参数哈希(或子哈希)传递给traverse
,则可以这样更新值:
def traverse(params)
params.each do |k, v|
traverse(v) if v.is_a? Hash
params[k] = nil if v == '\u0000'
end
end
# => {:filters=>{:user=>{:disabled_at=>nil}, :importan_param=>1}}
如果您使用的是Ruby> 2.4,则可以使用transform_values
对其进行整理:
def traverse(params)
params.dup.transform_values { |v| v == "\\u0000" ? nil : v.is_a?(Hash) ? traverse(v) : v }
end
traverse(params)
# => {:filters=>{:user=>{:disabled_at=>nil}, :importan_param=>1}}
params
# => {:filters=>{:user=>{:disabled_at=>"\\u0000"}, :importan_param=>1}}
或者,更具可读性:
def traverse(params)
params.dup.transform_values do |v|
next traverse(v) if v.is_a?(Hash)
v == "\\u0000" ? nil : v
end
end
希望有用-让我知道您的生活状况或有任何疑问。
答案 1 :(得分:1)
您正在滥用each
进行映射。映射是使用map
完成的,each
是用于迭代的。
def fix(hash)
hash.map do |k, v|
[k, case v
when Hash then fix(v)
when '\u0000' then nil
else v
end]
end.to_h
end