Ruby - unexpected return (LocalJumpError) - ruby

Ruby 2.0
Why would the code below give unexpected return (LocalJumpError) ?
# some code here
puts "Scanning for xml files .."
zip_files = Dir.entries(directory).select { |f| File.extname(f) == '.zip' }
if(zip_files.count == 0)
puts "No files found, exiting..."
return
end
# more code here ( if files found)
Error: unexpected return (LocalJumpError)
No files found, exiting...
[Finished in 0.9s with exit code 1]

You're not in a method. You cannot return from there. If you want to exit early, use exit.

Alternatively, you could rescue the LocalJumpError
puts "Scanning for xml files .."
zip_files = Dir.entries(directory).select { |f| File.extname(f) == '.zip' }
begin
return unless zip_files.count > 0
# more code here ( if files found)
rescue LocalJumpError
puts "No files found, exiting..."
end

Related

dealing with a file path argument: no implicit conversion of nil into String

I am writing a short ruby script that takes a file as an argument and then parses that file.
I have put together a few conditions in the initialize method to ensure that a file path exists and it is readable and if it nots it prints an error message to the user.
However when I run the file with out a file attached along side the message "please add log file path". I also receive the following error messages.
please add log file path
Traceback (most recent call last):
3: from webserver_log_parser.rb:41:in `<main>'
2: from webserver_log_parser.rb:41:in `new'
1: from webserver_log_parser.rb:6:in `initialize'
webserver_log_parser.rb:6:in `exist?': no implicit conversion of nil into String (TypeError)
I would be really grateful if someone could explain why this happens and a way to fix this issue.
def initialize(log_file_path = nil)
puts 'please add log file path' unless log_file_path
puts 'Could not find the file path' unless File.exist?(log_file_path)
puts '${log_file_path} is unreadable' unless File.readable?(log_file_path)
extract_log_file(log_file_path)
end
def extract_log_file(log_file_path)
webpages = Hash.new { |url, ip_address| url[ip_address] = [] }
File.readlines(log_file_path).each do |line|
url, ip_address = line.split
webpages[url] << ip_address
end
sort_results(webpages)
end
def sort_results(results)
total_views = {}
unique_views = {}
results.each do |url, ip_address|
total_views[url] = ip_address.length
unique_views[url] = ip_address.uniq.length
end
display_results(total_views, unique_views)
end
def display_results(views, unique_views)
puts 'The most viewed pages are as follows:'
total_views_sorted = views.sort_by { |_k, count| -count }
total_views_sorted.each { |key, count| puts "#{key} #{count}" }
puts 'The pages with the most unique views are as follows:'
unique_sort = unique_views.sort_by { |_k, count| -count }
unique_sort.each { |key, count| puts "#{key} #{count}" }
end
end
if $PROGRAM_NAME == __FILE__
LogParser.new(ARGV[0])
end```
If you want to directly terminate the script with a message, you can use abort.
def initialize(log_file_path = nil)
abort("please add log file path") unless log_file_path
abort("Could not find the file path") unless File.exist?(log_file_path)
abort("${log_file_path} is unreadable") unless File.readable?(log_file_path)
extract_log_file(log_file_path)
end
When your guard conditions are triggered, you need to stop further processing (no need to check for readability of a file at file_path if you already established that file_path is nil). It could look like this, for example:
def initialize(log_file_path = nil)
unless log_file_path
puts 'please add log file path'
return
end
unless File.exist?(log_file_path)
puts 'Could not find the file path'
return
end
unless File.readable?(log_file_path)
puts '${log_file_path} is unreadable'
return
end
extract_log_file(log_file_path)
end

Ruby: void value expression while using if else with break

I am new to Ruby language. I am working on integrating the Danger to add checks on GitHub PR. One of the use case is to check if modified files in my PR contains particular change. I have added below code in DangerFile
filesArray = ["Resources/Config.plist", "Resources/Deployment.plist"]
def modified_files_contains_change(files, change)
does_contain_required_changes = false
for file in files do
message "diff in #{file}"
diff = git.diff_for_file(file)
patch_contains_change = diff.patch =~ #{change}
if diff && patch_contains_change
does_contain_required_changes = true
else
does_contain_required_changes = false
break
end
end
message "Does contain changes in all files => #{does_contain_required_changes}"
does_contain_required_changes
end
if modified_files_contains_change(files, change)
warn "Some useful warning message goes here"
end
While running this on my CI, I am getting below error
[!] Invalid `Dangerfile` file: void value expression.
# from Dangerfile:33
# -------------------------------------------
# does_contain_required_changes = false
> break
# end
# end
# -------------------------------------------
I tried searching but didn't understand the what's going wrong. Can someone please help me understand what is the exact issue? Thanks in advance.
=~ #{change} is read as just =~ because # starts an inline comment. =~ expects a regular expression on one of sides. To fix the issue, change the line below:
patch_contains_change = diff.patch =~ #{change}
to:
patch_contains_change = diff.patch =~ Regexp.new(change)
This assumes you are passing a string as change.
Also, this would be more or less rubyish way to accomplish the task:
def modified_files_contains_change(files, change)
does_contain_required_changes =
files.all? do |file|
message "diff in #{file}"
# break will immediately exit the `all?` unless diff is present
break false unless diff = git.diff_for_file(file)
diff.patch =~ Regexp.new(change)
end
message "Does contain changes in all files => #{does_contain_required_changes}"
does_contain_required_changes
end
To return a file where we found an issue:
def modified_files_contains_change(files, change)
problematic_file =
files.detect do |file|
message "diff in #{file}"
(diff = git.diff_for_file(file)).nil? || diff.patch !~ Regexp.new(change)
end
does_contain_required_changes = problematic_file.nil?
if does_contain_required_changes
message "All good!"
else
message "We have issues with file #{problematic_file}"
end
does_contain_required_changes
end

Ruby Net::SSH get Exit Status in PTY

I'm trying to write in some functionality into the Net::SSH::Telnet Library for a project of mine. Specifically I need to be able to read the exit-status of any command that I write.
Here's the Original source from the Net::SSH::Telnet Library that I'm modifying
#buf = ""
#eof = false
#channel = nil
#ssh.open_channel do |channel|
channel.request_pty { |ch,success|
if success == false
raise "Failed to open ssh pty"
end
}
channel.send_channel_request("shell") { |ch, success|
if success
#channel = ch
waitfor(#options['Prompt'], &blk)
return
else
raise "Failed to open ssh shell"
end
}
channel.on_data { |ch,data| #buf << data }
channel.on_extended_data { |ch,type,data| #buf << data if type == 1 }
channel.on_close { #eof = true }
end
#ssh.loop
And now here are the changes I have made:
#stderr = ""
#exit_code = nil
#buf = ""
#eof = false
#channel = nil
#ssh.open_channel do |channel|
channel.request_pty { |ch,success|
if success == false
raise "Failed to open ssh pty"
end
}
channel.send_channel_request("shell") { |ch, success|
if success
#channel = ch
waitfor(#options['Prompt'], &blk)
return
else
raise "Failed to open ssh shell"
end
}
channel.on_data { |ch,data|
#stdout << data
#buf << data
}
channel.on_extended_data { |ch,type,data|
#stderr << data
#buf << data if type == 1
}
channel.on_request("exit-status") do |ch,data|
#exit_code = data.read_long
end
channel.on_close {
#eof = true
}
end
#ssh.loop
The problem is that when I run this, the #exit_code variable never changes from nil.
The reason I am doing this is because I need three major pieces of functionality:
1. Stateful (interactive) communication (so that if I cd into a directory the next command will occur in that directory)
2. The ability to read the exit status of any command I execute
3. The ability to respond to prompts
I selected Net::SSH::Telnet to adjust because it already offered 1 & 3. I figured I could fix it to support number 2.
If anyone can see how to fix this I would greatly appreciate it. The source for the rest of Net::SSH::Telnet is here:
https://github.com/jasonkarns/net-ssh-telnet/
and I have a forked version of the repo here to which I would gladly accept pull requests.
https://github.com/0x783czar/net-ssh-remotescript
Also if anyone has a suggestion of any other ruby libraries that would offer those three functionalities I would greatly appreciate any suggestions.
You may want to take a look at the source for the Ruby "ssh" gem and "remote_task" gem.
http://rubygems.org/gems/ssh
The relevant source code is here:
https://github.com/seattlerb/ssh/blob/master/lib/ssh.rb
It has code for handling the "cd" command, i/o channels, and the exit status.

Why can't I 'break' out of this Ruby block?

I have this Ruby block:
status = ''
build.parse do |entry|
puts "parsing an item"
puts entry.title
if entry.title =~ /FAILURE/ then
puts "failure"
status = "FAILURE"
else
status = "SUCCESS"
end
puts status
break entry if status == "FAILURE"
end
For some unknown reason to me I can't seem to break out of it? I realise the block is a little weird it's semi-copied from here:
http://macruby.labs.oreilly.com/ch03.html#_xml_parsing
Honestly my Ruby is poor but I'm trying to write a little mac app that involves some RSS parsing.
The regex matches and status gets set to "FAILURE" but it doesn't break out the block/loop. Am I doing something obviously wrong?
Cheers,
Adam
you dont need the 'then' in your if block
#entries = ["this is a FAILURE", "this is a success"]
status = ''
#entries.each do |entry|
if entry =~ /FAILURE/
puts "failure"
status = "failure"
else
status = "success"
end
puts "status == #{status}"
break if status == "failure"
end
as a side note, it would be more idiomatic to write this as:
status = #entries.any?{|e| e =~ /FAILURE/} ? 'failure' : 'succes'
when you are dealing with enumerable objects, like arrays it is nice to use the tools built into Ruby.
http://apidock.com/ruby/Enumerable/any%3F
Try break if status == "FAILURE"

ruby at_exit exit status

Can i determine selves process exit status in at_exit block?
at_exit do
if this_process_status.success?
print 'Success'
else
print 'Failure'
end
end
using idea from tadman
at_exit do
if $!.nil? || ($!.is_a?(SystemExit) && $!.success?)
print 'success'
else
code = $!.is_a?(SystemExit) ? $!.status : 1
print "failure with code #{code}"
end
end
or without Perlisms:
require 'English'
at_exit do
if $ERROR_INFO.nil? || ($ERROR_INFO.is_a?(SystemExit) && $ERROR_INFO.success?)
print 'success'
else
code = $ERROR_INFO.is_a?(SystemExit) ? $ERROR_INFO.status : 1
print "failure with code #{code}"
end
end
Although the documentation on this is really thin, $! is set to be the last exception that occurs, and after an exit() call this is a SystemExit exception. Putting those two together you get this:
at_exit do
if ($!.success?)
print 'Success'
else
print 'Failure'
end
end

Resources