处理嵌套哈希以将所有值转换为字符串
我有以下代码,它采用哈希并将所有值转换为字符串。
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
的更简单的实现可以是 – 假设它总是一个哈希。 此函数使用由Active Support Core Extensions添加的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
不确定value是数组时的期望是什么,因为Array#to_s
也会将数组作为字符串给出,无论是否可取,您可以稍微决定和调整解决方案。
有两个问题。 首先:第一次调用后的@values
总是包含你在第一次调用中克隆的对象,所以最后你总是会收到一个克隆的@values
对象,无论你用obj
变量做什么(这是因为||=
你的电话中的运营商)。 第二:如果你删除它并将执行@values = obj.clone
– 它仍然会返回不正确的结果(最深的哈希),因为你在调用后覆盖现有的变量调用。
require 'yaml' def stringify_values(obj) temp = {} obj.each do |k, v| if v.is_a?(Hash) temp[k] = stringify_values(v) else temp[k] = v.to_s end end temp end hash = { post: { id: 123, text: 'foobar', } } puts stringify_values(hash).to_yaml #=> --- :post: :id: '123' :text: foobar
如果您知道将值转换为字符串,我会使用monkeypatching Hash
类:
class Hash def stringify_values map { |k, v| [k, Hash === v ? v.stringify_values : v.to_s] }.to_h end end
现在您将能够:
require 'yaml' { post: { id: 123, text: 'foobar' }, arr: [1, 2, 3] }.stringify_values.to_yaml #⇒ --- # :post: # :id: '123' # :text: foobar # :arr: "[1, 2, 3]"
事实上,我想知道你是否真的想要争夺Array
?
如果您想要一个简单的解决方案而不需要ActiveSupport,您可以使用each_with_object
在一行中执行此each_with_object
:
obj.each_with_object({}) { |(k,v),m| m[k] = v.to_s }
如果要修改obj
,请将obj
作为参数传递给each_with_object
; 上面的版本返回一个新对象。
- 什么是最好的WYSIWYG for Rails – Ruby on Rails博客
- 块语法差异导致“LocalJumpError:no block given(yield)”
- 使用self.dup,但没有通过rspec测试来修改原始数组
- Rails 2.3.14:如何序列化ActionController :: Request对象?
- 如何压缩哈希,使每个键成为唯一值?
- OpenSSL :: SSL :: SSLError:SSL_connect SYSCALL返回= 5 errno = 0 state = SSLv3读取服务器hello A
- Rails在哪里存储通过在测试期间保存activerecord对象而创建的数据?
- Ruby 2.0.0 RVM无法编译OS X 10.8.2 Mountain Lion
- 如何在JS Rails响应中包含HTML?