我有一个散列,它被传递给OpenStruct
,以便使其与.
形成单词。这非常有效。但当我试图访问一个不存在的密钥时,就会引发undefined method <unknown key> for #<Hash:0x7f24ea884210> (NoMethodError)
。如何使其返回nil
?
如果我对原始哈希尝试相同的操作,我会得到nil
,但不会得到OpenStruct
!!
程序片段:
TXT_HASH = load_data("test.txt")
pp TXT_HASH[:ftp][:lastname] ## print nil as lastname does not exist
TXT = OpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname ## raises NoMethodError ## Can it return nil?
OpenStruct不是递归的。在这种情况下,TXT.ftp
返回的是Hash,而不是OpenStruct,因此没有定义#lastname
。
如果你愿意的话,有一个叫做递归开放结构的库。这样使用:
require 'recursive-open-struct'
TXT = RecursiveOpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname #=> nil
@Shel
给出的答案是最好的,简单明了。
注意:
如果您不想需要不必要的库,那么还有另一种变通方法可以实现
是的,OpenStruct不是递归的,但我们可以创建自己的递归方法来做到这一点
# This method is kind of factory to create OpenStruct instances
def get_recursive_ostruct(object)
if object.is_a?(Hash)
object = object.clone
object.each do |key, value|
object[key] = get_recursive_ostruct(value)
end
OpenStruct.new(object)
else
object
end
end
并使用这种方法
require 'ostruct'
hash = {first: 'this is first', second: {first: 'first of second', second: 'second of second'}}
obj = get_recursive_ostruct(hash)
#=> #<OpenStruct first="this is first", second=#<OpenStruct first="first of second", second="second of second">>
obj.second.second
#=> "second of second"
obj.second.third
#=> nil
此外,若您希望对象不返回异常,那个么也有一些解决方法。
TXT.ftp.lastname ## raises NoMethodError
TXT.ftp.try(:lastname) ## returns nil if `lastname` is not available
TXT.try(:ftp).try(:lastname) ## returns nil even if `ftp` is not available
注意:
据我所知,try
方法仅在Rails
应用程序中可用,而在IRB
或ruby
应用程序中不可用。我会使用:
rescue
方法
注意:此方法捕获异常并做出相应响应;如果您需要以不同的方式响应异常,请不要使用此选项。我希望你了解
TXT.ftp.lastname rescue nil # respond with default value i.e. nil
TXT.ftp.lastname rescue '' # respond with default value i.e. ''
如果你想要一个递归的OpenStruct,另一种选择是使用哈希宝石中的Mash:
require 'hashie'
text = Hashie::Mash.new(text_hash)
p text.ftp.lastname #=> nil