Parsing through nested hash using .present? - undefined method `[]' for nil:NilClass (NoMethodError) - ruby

***EDITED 2nd time to show that I need to handle looking in multiple locations.
EDITED to show exception being raise even when handler built in.
I am currently parsing through responses from an API that includes arrays that I've converted into a hash using
hash_table = xml_response.to_h
The challenge is that sometimes the data I'm looking for is located in different locations, and when I use a key method:
data_i_need = hash_table['key1']['key2'][0]
if there's nothing there, it throws this error:
undefined method `[]' for nil:NilClass (NoMethodError)
I've tried using:
if hash_table['key1']['key2'][0].present?
data_i_need = hash_table['key1']['key2'][0]
puts "data was here"
elsif hash_table['key3']['key4'][0].present?
data_i_need = hash_table['key3']['key4'][0]
puts "data here"
elsif hash_table['key5']['key6'][0].present?
data_i_need = hash_table['key5']['key6'][0]
puts "data here"
else
"data not found"
end
But it throws the same error:
undefined method `[]' for nil:NilClass (NoMethodError)

you should check for the presence all the previous hash key because if one of them is nil, the exception will be raised
hash_table['key1'].present? && hash_table['key1']['key2'].present? && hash_table['key1']['key2']['key3'].present? && hash_table['key1']['key2']['key3'][0].present?
Update:
To return "not found", you can catch the exception like this:
data_i_need = begin
hash_table['key1']['key2']['key3'][0]
rescue NoMethodError
"data not found"
end
Update 2:
You can use this function to check if the keys exist in the hash in the if else condition statements:
h = {:a => {:b => {0 => 1}}, :c => 2}
def has_nested_keys?(hash, *keys)
keys.inject(hash) do |result, key|
result = result[key]
end
true
rescue
false
end
has_nested_keys?(h, :a, :b, 0) #=> true
has_nested_keys?(h, :c, :d, 0) #=> false

Related

Iterating through a rails object

I have an error object e, with the following structure:
e.error_code
e.message
It, however, may have additional symbols, such as:
e.error_details
How do I iterate through the e object?
I tried
e.each do |error|
...
end
But I get an error message:
NoMethodError (undefined method `each' for #<Smartsheet::ApiError: Too many sheets to copy.>)
This is a Smartsheet API error object. The code below works:
begin
#smartsheet.workspaces.copy(workspace_id: workspace_id, body: {new_name: new_name}))
rescue Smartsheet::ApiError => e
puts "Error Code: #{e.error_code}"
puts "Message: #{e.message}"
end
end
try this
e.instance_variables.each do |error|
...
end
This will give you the attributes, if you want the value you could use
e.instance_variable_get(error)
inside the do clause

undefined method `text' for nil:NilClass (NoMethodError) for and action that was excuted

I have the following code:
def find_status(arg)
10.times do
table = table_element(:css => 'css.path')
break if table.visible?
end
table = table_element(:css => 'css.path')
if table.visible?
table.each do |row|
STDOUT.puts row[1].text
match = /^#{arg}\n(String \S+) at .+/.match(row[1].text)
return match[1] if match
end
end
return "status unknown"
end
Now the problem is that I'm getting the following error:
undefined method `text' for nil:NilClass (NoMethodError)
The weird part is that it prints exactly what I wanted it to print and points out that the error is on the "STDOUT" row.
So to sum it up it's executing the command but says row is a nil value.
Help would be appreciated.
If I understand this correctly, just test for nil first, then use the row text if a row exists.
STDOUT.puts row[1] ? row[1].text : 'nil'

I can't get headers when I parse csv file with Ruby

I can't get headers. No error happens. How can I get it properly?
Data:
"A","B","C"
"1","2","3"
Ruby:
require "csv"
table = CSV.read("filename", :headers => true)
puts table[0] # "1","2","3"
puts table[headers] # Nothing happens.
Try table.headers:
irb(main):006:0> table.headers
=> ["A", "B", "C"]
How are you running this code? table[headers] should return an error:
irb(main):008:0> table[headers]
NameError: undefined local variable or method `headers' for main:Object
from (irb):8
from /usr/bin/irb:12:in `<main>'

I am getting an error with (..).each do |x| .. end in ruby

I am getting error for the below part of code:
element = driver.find_element :name => "used_by"
element.send_keys "371101"
element = driver.find_element :name => "btnSearch"
element.click
all_table_data = driver.find_element(:tag_name, "td").text
all_table_data.each do |td|
puts td.text
end
print element
Error:
D:\Ruby script>ruby filedownload.rb
filedownload.rb:24:in `<main>': undefined method `each' for #<Selenium::WebDrive
r::Element:0x2556be8> (NoMethodError)
D:\Ruby script>
can anyone help me to fix the error?
find_element only returns the first element matching the given arguments.
What you probably what is the find_elements method which finds all elements matching the given arguments:
all_table_data = driver.find_elements(:tag_name, "td")
all_table_data.each do |td|
puts td.text
end

How do I debug an undefined method for nil class error?

I'm trying to create a classifier using the cardmagic classifier gem. This is my code:
require 'classifier'
classifications = '1007.09', '1006.03'
traindata = Hash["1007.09" => "ADAPTER- SCREENING FOR VALVES VBS", "1006.03" => "ACTUATOR- LINEAR"]
b = Classifier::Bayes.new classifications
traindata.each do |key, value|
b.train(key, value)
end
But when I run this I get the following error:
Notice: for 10x faster LSI support, please install http://rb-gsl.rubyforge.org/
c:/Ruby192/lib/ruby/gems/1.9.1/gems/classifier-1.3.3/lib/classifier/bayes.rb:27:in `block in train': undefined method `[]' for nil:NilClass (NoMethodError)
from c:/Ruby192/lib/ruby/gems/1.9.1/gems/classifier-1.3.3/lib/classifier/bayes.rb:26:in `each'
from c:/Ruby192/lib/ruby/gems/1.9.1/gems/classifier-1.3.3/lib/classifier/bayes.rb:26:in `train'
from C:/_Chris/Code/classifier/smdclasser.rb:13:in `block in <main>'
from C:/_Chris/Code/classifier/smdclasser.rb:11:in `each'
from C:/_Chris/Code/classifier/smdclasser.rb:11:in `<main>'
This is the source from the gem code:
# Provides a general training method for all categories specified in Bayes#new
# For example:
# b = Classifier::Bayes.new 'This', 'That', 'the_other'
# b.train :this, "This text"
# b.train "that", "That text"
# b.train "The other", "The other text"
def train(category, text)
category = category.prepare_category_name
text.word_hash.each do |word, count|
#categories[category][word] ||= 0
#categories[category][word] += count
#total_words += count
end
end
I am lost where to go to troubleshoot this error, what is the next step I should take?
Classifier::Bayes.new expects an exploded array of values, rather than a single parameter. For example, notice that the sample code uses:
b = Classifier::Bayes.new 'This', 'That', 'the_other'
rather than:
b = Classifier::Bayes.new ['This', 'That', 'the_other']
Pass in the splat version of your classifications array and it should work:
b = Classifier::Bayes.new *classifications

Resources