我有以下代码,它接受一个散列并将所有值转换为字符串。

def stringify_values obj
  @values ||= obj.clone

  obj.each do |k, v|
    if v.is_a?(Hash)
      @values[k] = stringify_values(v)
    else
      @values[k] = v.to_s
    end
  end

  return @values
end

因此,给出以下散列:
{
  post: {
    id: 123,
    text: 'foobar',
  }
}

我得到了以下的yaml输出
--- &1
:post: *1
:id: '123'
:text: 'foobar'

当我想要这个输出
---
:post:
  :id: '123'
  :text: 'foobar'

看起来对象已经被展平,然后被赋予了对自身的引用,这会在我的规范中导致堆栈级错误。
如何获得所需的输出?

最佳答案

一个更简单的stringify_values实现可以是-假设它总是一个散列。此函数使用活动支持核心扩展添加的Hash#deep_merge方法-我们将散列与自身合并,以便在块中检查每个值并对其调用to_s

def stringify_values obj
  obj.deep_merge(obj) {|_,_,v| v.to_s}
end

完整工作样品:
require "yaml"
require "active_support/core_ext/hash"

def stringify_values obj
  obj.deep_merge(obj) {|_,_,v| v.to_s}
end

class Foo
    def to_s
        "I am Foo"
    end
end

h = {
  post: {
    id: 123,
    arr: [1,2,3],
    text: 'foobar',
    obj: { me: Foo.new}
  }
}

puts YAML.dump (stringify_values h)
#=>
---
:post:
  :id: '123'
  :arr: "[1, 2, 3]"
  :text: foobar
  :obj:
    :me: I am Foo

不确定值是数组时的期望值是多少,因为Array#to_s也会将数组作为字符串提供给您,无论这是否可取,您可以决定并稍微调整解决方案。

09-19 03:28