drag and drop on a Rubyscript: displaying raise errormessage? - ruby

I have a script which I start by a drag and drop of a file from Explorer onto a link on the Windows Desktop to my script, so the filename becomes the parameter of my script. This is handy for users who don't know how to start my script with a valid parameter. This part works perfectly.
But when I raise an error in the script, the errormessage is displayed but the console window closes without giving the user the time to read the message.
Putting a gets or a sleep at the end of the script or after the raise doesn't help.
How do I fix that please ?
if ARGV[0]
filename = ARGV[0]
else
raise "No filename given"
end
#some other code with wrong data
error = true
if error
raise "An error has occured, wrong data"
end

Add this around your entire program:
begin
all your code...
rescue
puts $!
system('pause')
end

Related

Nested `if` statement not evaluating the result of an operation

I am generating a file in a temp directory.
If the file to be generated is different from an already existing file, then I wan't to update it, and run a command. If it's the same, then I can do nothing.
My code looks like this:
errstatus = 0
if FileUtils.identical?('/var/tmp/newfile', '/var/tmp/originalfile')
$stderr.puts "Files are the same, nothing to do"
else
$stderr.puts "Files are different, let's update them."
if FileUtils.cp_r '/var/tmp/newfile', '/var/tmp/originalfile'
$stderr.puts "File copied successfully."
if system('systemcommand1 here')
$stderr.puts "command ran OK"
if system('systemcommand2 here')
$stderr.puts "next command ran ok"
else
$stderr.puts "command 2 failed"
errstatus = 1
end
else
$stderr.puts "command 1 failed"
errstatus = 1
end
end
end
When I run it when the files are different, I get the output:
Files are different, let's update them.
It runs with FileUtils.cp_r without any errors, but it doesn't tell that the File was copied successfully, or run the system command. I have used the same syntax to evaluate FileUtils.identical?, but it does not work for FileUtils.cp_r.
Where am I going wrong here?
FileUtils::cp_r returns nil (which in Ruby is falsy) if the copying was successful, raises an error if not. It will never return a truthy value, so making it a condition does not make sense.
Since it doesn't have an else statement right now, simply remove the if before it. If you want error handling for your cp_r, you will need to wrap it into a begin..rescue block.
Maybe it's because the if FileUtils.cp_r '/var/tmp/newfile', '/var/tmp/originalfile' doesn't have an else clause so if it returns false or throws and exception it doesn't enter the if.

only if chef code fails , error should be captured by ignore_failure_true and display error message

execute 'install_insatller' do
cwd "abc"
command reg_cmd
ignore_failure true
log 'STDERROR'
only_if { ::File.exist?('abc') }
end
this is just an expample code
I want to print the log message only if the failure occurs else continue the installation.
ignore_failure true means that if there is an error, we show the usual error display but don't abort the converge. If you want behavior other than that, you'll probably have to write something yourself.
If you want to capture output and take decission based on that then please use Mixlib shellout instead of execute.
if ::File.exist?('abc')
require 'mixlib/shellout'
cmnd = Mixlib::ShellOut.new(reg_cmd)
cmnd.run_command
if cmnd.error?
puts cmnd.stderr
else
<write your code here to continue with installation>
end
end

Having trouble in getting input from user in Ruby

I have a method which check if the file exists, If the file does not exist then it should call another method which prompts the questions. Below is the sample code.
def readFile1()
flag = false
begin
#ssh.exec!("cd #{##home_dir}")
puts "\nChecking if file exists on #{#hostname}\n"
if #ssh.exec!("sh -c '[ -f "#{file_name}" ]; echo $?'").to_i == 0
flag = true
puts "File exists on #{#hostname}"
display()
else
puts "File does not exist. Please answer following questions."
prompt()
end
rescue => e
puts "readFile1 failed... #{e}"
end
return exists
end
def prompt()
puts "\nDo you want to enter the new file location? [y/n]"
ans = gets.chomp
puts "New location is #{ans}"
end
When I am calling readFile method, if the file does not exists, it prints Do you want to enter the new file location? [y/n] and does not wait for the user to enter the value but immediately prints the rescue block and quits. Below is the Output if file does not exists.
Checking if file exists on LNXAPP
File does not exist. Please answer following questions.
Do you want to enter the new file location? [y/n]
readFile1 failed... No such file or directory - LNXAPP
I want the user to enter the values for the questions but it's not happening.Need help in fixing this.
Your code is not ideal.
You should check if the file exists via:
if File.exist? location_of_your_file_goes_here
The begin/rescue is then not required, because
you already check before whether the file exists.
Also two spaces should be better than one tab,
at least when you display on a site such as here.
Reason is simple - it makes your code easier
to read for others.
You also don't need the flag variable if I am
right - try to omit it and use solely File.exist?
there.
Also you wrote:
"When I am calling readFile method"
But you have no method called readFile().
Your method is called readFile1().
I know that you probably know this too, but
you must be very specific so that the ruby
parser understands precisely what you mean,
and that what you describe with words also
matches to the code you use.
Another issue I see with your code is that
you do this:
return exists
but what is "exists" here? A variable?
A method? It has not been defined elsewhere
in your code.
Try to make your code as simple and as logical
as possible.

Equivalent to Perl's END block in Ruby

Is there a Perl equivalent END block in Ruby? In Perl, if I specify an END block, the code in that block will get executed no matter where the program bails out. It is great functionality for closing open file handles. Does Ruby support similar functionality? I tried Ruby's "END{}" block but that doesnt seem to get called if I had an exit in the code due to an error.
Thanks!
Use at_exit, which will run regardless of whether an exception was raised or not:
at_exit { puts 'exited!' }
raise
prints "exited" as expected.
You should only consider this if you cannot use an ensure, as at_exit causes logic to reside far away from where the actual exit occurs.
Yes. A block may have an 'ensure' clause. Here's an example:
begin
# This will cause a divide by zero exception
puts 3 / 0
rescue Exception => e
puts "An error occurred: #{e}"
ensure
puts "I get run anyway"
end
Running this produces:
An error occurred: divided by 0
I get run anyway

How to create an exit message

Is there a one line function call that quits the program and displays a message? I know in Perl it's as simple as:
die("Message goes here")
I'm tired of typing this:
puts "Message goes here"
exit
The abort function does this. For example:
abort("Message goes here")
Note: the abort message will be written to STDERR as opposed to puts which will write to STDOUT.
If you want to denote an actual error in your code, you could raise a RuntimeError exception:
raise RuntimeError, 'Message goes here'
This will print a stacktrace, the type of the exception being raised and the message that you provided. Depending on your users, a stacktrace might be too scary, and the actual message might get lost in the noise. On the other hand, if you die because of an actual error, a stacktrace will give you additional information for debugging.
I got here searching for a way to execute some code whenever the program ends.
Found this:
Kernel.at_exit { puts "sayonara" }
# do whatever
# [...]
# call #exit or #abort or just let the program end
# calling #exit! will skip the call
Called multiple times will register multiple handlers.
I've never heard of such a function, but it would be trivial enough to implement...
def die(msg)
puts msg
exit
end
Then, if this is defined in some .rb file that you include in all your scripts, you are golden.... just because it's not built in doesn't mean you can't do it yourself ;-)

Resources