我已经构建了一个Hash的子类,每当我用我的类的实例作为参数调用puts
时,我得到以下内容:
> puts data
TypeError: can't convert Reporting::Search::Data to Array (Reporting::Search::Data#to_ary gives Reporting::Search::Data)
有谁知道该怎么办?我希望它输出一个Hash的字符串表示,就像用普通Hash调用puts
一样。
我的课很简单:
class Data < HashWithIndifferentAccess
def method_missing meth, *args, &block
if meth.to_s =~ /=$/
send :[]=, meth.slice(0...-1), *args
elsif args.empty?
fetch meth, Data.new
else
super meth, *args, &block
end
end
def compact!
delete_if do |k,v|
v.compact! if v.is_a?(Data)
v.blank?
end
end
end
答案 0 :(得分:1)
您有两种选择,可以编写to_s
方法。或者你可以看到.inspect
实例方法给你的东西,虽然它可能不是很有用!
您是否尝试过添加这样的to_s方法?
def to_s
super.to_s
end
此外,它可能不是您遇到问题的唯一原因,但您已将您的子类Data
命名为Ruby中的类。
答案 1 :(得分:1)
看起来问题与您使用method_missing
有关。
当你调用puts
时,它会尝试以人类可读的形式输出对象,因此它会在对象上调用to_ary
。但是,您尚未在课程中定义to_ary
,因此它会回到method_missing
,因为它会混淆并失败。
将to_ary
定义为存根,我不再收到错误。
def to_ary
end
这是Ruby中元编程的许多陷阱之一!
答案 2 :(得分:0)
您以各种方式违反了Ruby的类型转换协议。
首先,您的对象会响应to_int
,to_float
,to_str
,to_ary
等,而实际上不是整数,浮点数,字符串或数组。这些类型转换方法的三个字母( ahem float ahem )版本应该仅用于 ,如果有问题的对象真的绝对肯定是整数,浮点数,字符串或数组,而不是表示为Integer
,Float
,String
或Array
的实例
但是,您的对象不是Array
,而是地图。因此,它应该只响应to_hash
,如果有的话。
其次,to_int
,to_float
,to_str
,to_ary
等的返回值应该是Integer
的实例,{{1 }},Float
或String
类。
因此,您正在实现一些您甚至不应该首先实现的方法和您从它们返回错误的值。对于那些深深植根于Ruby核心内容的东西来说,就像它的类型转换协议一样,必然会带来各种各样的破坏,你只能看到它的开始。