How can I return nil if the key does not exist in OpenStruct?

I have a hash that went before OpenStructto make it a word with .. It works great. But when I try to access a key that does not exist, it arises undefined method <unknown key> for #<Hash:0x7f24ea884210> (NoMethodError). How can I return it nil?

If I try the same with the original hash, I get nil, but not with OpenStruct!!

Excerpt from the program:

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?
+4
source share
3 answers

OpenStruct is not recursive. In this case, it TXT.ftpreturns a hash, not OpenStruct, so it is #lastnamenot defined.

, recursive-open-struct. :

require 'recursive-open-struct'

TXT = RecursiveOpenStruct.new(TXT_HASH)
pp TXT.ftp.lastname #=> nil
+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

If you want a recursive OpenStruct, another option is to use Mash from hashie gem:

require 'hashie'

text = Hashie::Mash.new(text_hash)
p text.ftp.lastname #=> nil
0
source

Source: https://habr.com/ru/post/1613414/


All Articles