How to create an exit message - ruby

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 ;-)

Related

How do I unit test a Ruby app for return codes

I'm not terribly familiar with Ruby testing and my searches haven't yielded an answer to my specific question.
Currently, I have an app that raises StandardError to exit on certain conditions. The drawback to this is that the exit code is always 1.
I want to use exit() to provide unique codes to the exit conditions.
Currently, the project spec tests the StandardError mechanism as follows:
it "should raise an exception if no unignored project coverage file files were found" do
fixtures_project.ignore_list = ["*fixturesTests*", "*fixtures*"]
expect {fixtures_project.coverage_files}.to raise_error(StandardError)
end
I want to do something like assert($?.exit == 102), but I still need the fixtures_project.coverage_files to fire before hand in order to get the exit code.
I've tried variations of assert_equal(102, fixtures_project.coverage_files, "Hello there") inside the it/end with no luck. I'm sure this is probably simple Ruby, but I haven't grokked this bit yet.
You were right in trying to use $? object. Just call $?.exitstatus to get your exit status.
it "should raise an exception if no unignored project coverage file files were found" do
fixtures_project.ignore_list = ["*fixturesTests*", "*fixtures*"]
expect {fixtures_project.coverage_files}.to raise_error(StandardError)
expect($?.exitstatus).to eq(102)
end

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 explicitly fail a task in ruby rake?

Let's say I have a rakefile like this:
file 'file1' => some_dependencies do
sh 'external tool I do not have control over, which sometimes fail to create the file'
???
end
task :default => 'file1' do
puts "everything's OK"
end
Now if I put nothing in place of ???, I get the OK message, even if the external tool fails to generate file. What is the proper way to informing rake, that 'file1' task has failed and it should abort (hopefully presenting a meaningful message - like which task did fail) - the only think I can think of now is raising an exception there, but that just doesn't seem right.
P.S The tool always returns 0 as exit code.
Use the raise or fail method as you would for any other Ruby script (fail is an alias for raise). This method takes a string or exception as an argument which is used as the error message displayed at termination of the script. This will also cause the script to return the value 1 to the calling shell. It is documented here and other places.
You can use abort("message") to gracefully fail rake task.
It will print message to stdout and exit with code 1.
Exit code 1 is a failure in Unix-like systems.
See Kernel#abort for details.

Expect scripting, source and return

On page 35, in the book "Exploring Expect", it says "The return command can be used to make a source command return. Otherwise, source returns only after executing the last command in the file."
I don't quite understand what it's getting at. I'd like to know what this means and how this is useful.
Thank you.
an example:
main script:
puts "about to source external file"
set some_var true
source something.exp
puts "done sourcing"
something.exp
puts "in something.exp"
if {$some_var} return
puts "you won't see this if some_var is true"
Basically, when the 'return' command is encountered, 'expect' will stop processing the script further, and return to the parent script (if any) that ran it using the 'source' command. It's much like 'return' in any programming language.

check for (the absence of) `puts` in RSpec

I am using rspec for my test in a ruby project, and I want to spec that my program should not output anything when the -q option is used. I tried:
Kernel.should_not_receive :puts
That did not result in a failed test when there was output to the console.
How do I verify the absents of text output?
puts uses $stdout internally. Due to the way it works, the easiest way to check is to simply use: $stdout.should_not_receive(:write)
Which checks nothing is written to stdout as expected.
Kernel.puts (as above) would only result in a failed test when it
is explictely called as such (e.g. Kernel.puts "Some text"), where
as most cases it's call in the scope of the current object.
The accepted answer above is incorrect. It "works" because it doesn't receive a :write message but it might have received a :puts message.
The correct line should read:
$stdout.should_not_receive(:puts)
Also you need to make sure you put the line before the code that will write to STDIO. For instance:
it "should print a copyright message" do
$stdout.should_receive(:puts).with(/copyright/i)
app = ApplicationController.new(%w[project_name])
end
it "should not print an error message" do
$stdout.should_not_receive(:puts).with(/error/i)
app = ApplicationController.new(%w[project_name])
end
That's an actual working RSpec from a project

Resources