如果 OpenStruct 中不存在键,我如何 return nil?
How can I return nil if a key does not exist in OpenStruct?
我有一个散列值传递给 OpenStruct
以使其与 .
成词。这非常有效。但是每当我尝试访问一个不存在的密钥时 undefined method <unknown key> for #<Hash:0x7f24ea884210> (NoMethodError)
就会被引发。我怎样才能做到 return 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
returns 是一个 Hash,而不是 OpenStruct,所以 #lastname
没有定义。
如果需要,有一个库叫做 recursive-open-struct。像这样使用它:
require 'recursive-open-struct'
TXT = RecursiveOpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname #=> nil
然而@Shel
给出的答案是最好的,简单明了。
Note:
If you do not want to require unnecessary library then there is another workaround to implement.
Yes OpenStruct is not recursive yet we can create our own recursive method to do so.
# 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
此外,如果您不想 return 异常,那么还有一些解决方法。
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
Note:
As far as I know, try
method is only available inside Rails
app not in IRB
or ruby
apps.
I would use: rescue
method
Caution: this method catches exceptions and responds accordingly; Don't use this if you need to respond to exceptions differently. I hope you understand
TXT.ftp.lastname rescue nil # respond with default value i.e. nil
TXT.ftp.lastname rescue '' # respond with default value i.e. ''
如果你想要一个递归的 OpenStruct,另一种选择是使用 Mash from the hashie gem:
require 'hashie'
text = Hashie::Mash.new(text_hash)
p text.ftp.lastname #=> nil
我有一个散列值传递给 OpenStruct
以使其与 .
成词。这非常有效。但是每当我尝试访问一个不存在的密钥时 undefined method <unknown key> for #<Hash:0x7f24ea884210> (NoMethodError)
就会被引发。我怎样才能做到 return 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
returns 是一个 Hash,而不是 OpenStruct,所以 #lastname
没有定义。
如果需要,有一个库叫做 recursive-open-struct。像这样使用它:
require 'recursive-open-struct'
TXT = RecursiveOpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname #=> nil
然而@Shel
给出的答案是最好的,简单明了。
Note:
If you do not want to require unnecessary library then there is another workaround to implement.
Yes OpenStruct is not recursive yet we can create our own recursive method to do so.
# 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
此外,如果您不想 return 异常,那么还有一些解决方法。
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
Note:
As far as I know,try
method is only available insideRails
app not inIRB
orruby
apps.I would use:
rescue
method
Caution: this method catches exceptions and responds accordingly; Don't use this if you need to respond to exceptions differently. I hope you understand
TXT.ftp.lastname rescue nil # respond with default value i.e. nil
TXT.ftp.lastname rescue '' # respond with default value i.e. ''
如果你想要一个递归的 OpenStruct,另一种选择是使用 Mash from the hashie gem:
require 'hashie'
text = Hashie::Mash.new(text_hash)
p text.ftp.lastname #=> nil