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

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'

Related

NoMethodError: undefined method `chomp' for nil:NilClass while running Ruby Rspec on gets.chomp

This is my first post here. I'm fairly new to Ruby, especially RSpec and have been running into an issue. I have written a method that uses gets.chomp to receive a player input. However I have this method called in another method
def prompt_move
loop do
#move = gets.chomp.to_i
return move if valid_move?(move)
puts "Invalid input. Enter a column number between 1 and 7"
end
end
def valid_move?(move)
#move.is_a?(Integer) && #move.between?(1, 7)
end
def play_round
print_board
prompt_player
#move = prompt_move
end
Here is the code for my RSpec tests:
describe ConnectFour do
subject(:game) { described_class.new }
let(:player){ double(Player) }
describe '#prompt_move' do
context 'move is a valid input' do
before do
allow(game).to receive(:gets).and_return('3\n')
end
it 'returns move and stops the loop' do
error_message = 'Invalid input. Enter a column number between 1 and 7'
expect(game).to_not receive(:puts).with(error_message)
game.prompt_move
end
end
context 'when given one invalid input, then a valid input' do
before do
letter = 'a'
valid_input = '1'
allow(game).to receive(:gets).and_return(letter, valid_input)
end
it 'completes loop and displays error message once' do
error_message = 'Invalid input. Enter a column number between 1 and 7'
expect(game).to receive(:puts).with(error_message).once
game.prompt_move
end
end
end
If I remove the #prompt_move method from #play_round the tests pass without any issue. However when I try to call it from within #play_round it gives me
NoMethodError:
undefined method `chomp' for nil:NilClass
I have been struggling to figure out what is causing this error so any suggestions would be greatly appreciated!
You're executing code in your class file.
new_game = ConnectFour.new
new_game.play_game
This will run every time you load the file, like when you're testing it. It will prompt for input and run gets. What it's getting is the code of the test file (for some rspec reason). That's invalid, so it keeps running gets until eventually there is no more input and gets returns nil.
Remove that from your class file. Code like that should be in a separate file which requires the class.

Can't get stacktrace with `eval` when there is an error in the expression

I'm using eval on large blocks of code with this rescue block:
rescue => e
logger.error e.message
e.backtrace.each { |line| logger.error line }
end
The rescue block does not provide line number, etc. for the exception. I just get this:
undefined method `+' for nil:NilClass
which is not very helpful when there is a lot of code to evaluate. I tried various things such as:
eval(exp, binding, __FILE__, __LINE__)
but they do not provide any additional information on the line number of where the error is.
May be this can help. This answer is sort of based on details from this article. Assuming that you have expression to be evaluated in exp variable, I adjust the line number value passed as 3rd parameter to String#module_eval.
begin
exp = <<EOL
a = nil
a + 10
EOL
String.module_eval(exp,__FILE__, __LINE__ - 1 - exp.split("\n").size )
rescue Exception => e
puts e
puts e.backtrace
end
The output of above program:
undefined method `+' for nil:NilClass
E:/hello.rb:4:in `<main>'
E:/hello.rb:6:in `module_eval'
E:/hello.rb:6:in `<main>'
[Finished in 0.2s]

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

***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

Ruby/calabash: undefined method `each' for 2:Fixnum (NoMethodError)

I'm stuck with an error while creating some auto test in calabash. So my code is:
Then /^I set some site$/ do
arr=["Google.com","Youtube.com"]
for i in arr.length {
touch("* id:'browserActivity_linLout_toolbar_url'")
sleep 5
currentSite=arr[i]
keyboard_enter_text (currentSite)
sleep 10
press_enter_button
i=i+1
sleep 20
}
end
end
When I try to run my test I get this error:
undefined method each' for 2:Fixnum (NoMethodError)
./features/step_definitions/calabash_steps.rb:339:in/^I set some site$/'
features/my_first.feature:6:in `Then I set some site'
Any ideas how to solve it?
You are writing the for loop with the wrong syntax. In Ruby, use:
for element in arr
#...
currentSite = element
#...
end
Or better, without for:
arr.each do |element|
#...
currentSite = element
#...
end

Undefined method `upcase' for nil:NilClass (NoMethodError) - Ruby 1.9.3

I'm really beginner in ruby, trying to write a simple program to detect uppercase input. I use ruby-1.9.3-p125 now. So, I'm trying to compile this:
# coding: utf-8
puts 'hello! enter something:'
while req!=req.upcase
req=gets.chomp
if req == req.upcase
puts "This is UpperCase!"
else
puts "Not UpperCase :( Try again!"
end
end
puts "GoodBye!"
And I get a such error:
app1.rb:4:in `<main>': undefined method `upcase' for nil:NilClass (NoMethodError)
Maybe I should include any lib or smth like this? BTW, "UpCase".upcase` works good.
Your while loop references req before anything is assigned to it.
You could set ref in your while condition while (req = gets.chomp) != req.upcase, but this makes the condition complicated and still doesn't handle the end of file condition where gets returns nil. Better would be to make the condition focus on end of file and use break to terminate the loop in your special test:
puts 'hello! enter something:'
while req = gets
req.chomp!
if req == req.upcase
puts "This is UpperCase!"
break
else
puts "Not UpperCase :( Try again!"
end
end
puts "GoodBye!"

Resources