我有一个传递给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?
答案 0 :(得分:2)
OpenStruct不是递归的。在这种情况下,TXT.ftp
返回Hash,而不是OpenStruct,因此未定义#lastname
。
如果需要,可以使用名为recursive-open-struct的库。像这样使用它:
require 'recursive-open-struct'
TXT = RecursiveOpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname #=> nil
答案 1 :(得分:2)
@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. ''
答案 2 :(得分:0)