Yes, {}
are not begin end
block. begin end block are for catching exceptions:
As an example, I am going to represent a code that downloads a random image from unsplash (if you run BASH shell, it will run fine):
#!/usr/bin/ruby -w
require 'net/https'
FILE = File.join(__dir__, 'image.jpg')
begin
if File.exist?(FILE)
Warning.warn "File #{FILE} already exists!... Press enter to continue..."
abort('Quitting!') unless STDIN.gets.to_s.strip.empty?
end
puts "Downloading an image!"
chars = %w(| / - \\)
t = Thread.new { loop while chars.size.times { |i| print("\e[2K#{chars.rotate![0]} Downloading#{?..*(i % 4)}\r") || sleep(0.1) } }
Net::HTTP.get(URI('https://source.unsplash.com/random'))[/".*"/].undump
.tap { |link| File.write(FILE, Net::HTTP.get(URI(link))) }
t.kill
rescue SocketError, OpenSSL::SSL::SSLError
STDERR.puts 'Seems like you have an internet issue!'
rescue Errno::EACCES
STDERR.puts "Permission denied while trying to write to #{FILE}"
rescue SignalException, Interrupt, SystemExit
STDERR.puts 'Operation terminated'
rescue Exception => e
STDERR.puts "Caught an exception:\n#{e}"
else
STDOUT.puts "Successfully saved a random image as #{FILE}"
ensure
puts 'Bye!'
end
Note that the begin block initiates the code.
-
The first rescue
block helps to catch exception when thereâs no active internet connection.
-
The 2nd rescue
block to catch exception raised by File.write when you have no permission to write a file to the current directory.
-
The 3rd rescue
check if you are pressing [ctrl + c] or killing the program or not (all signals will be caught except signal 9 sigkill).
-
The 4th rescue
block catches all other exceptions that are not mentioned in the above rescue
blocks (you can replace Exception
with StandardError
)
-
The else
block get executed if the code in the begin block succeeds or not.
-
The later ensure
block ensures that your program prints âByeâ to the terminal no matter what! (unless it receives sigkill, 9)
The begin end block and () letâs you do funny things as well, which are just bad practice in Ruby:
begin
puts 'This is an endless loop!'
end while true
Or
(
puts 'This is an endless loop!'
) while true
# This works because `puts 'This is an endless loop' while true` is also valid.
The above codes will run in an infinite loop, but this is a very bad practice. I donât know about the () code here, but the begin end blockâs purpose is not to imitate the do while
in C! So itâs better to know, but donât use the above code instead of traditional usage!
Hope you got the above. Nevertheless,
Thereâs another begin end block. This time itâs BEGIN {} END {}
:
For the sake of example, consider this code:
#!/usr/bin/ruby -w
puts 'hi'
BEGIN {
a = 5
puts 'Ruby!!'
}
END { puts "Bye bye Mr. #{a}" }
puts 'See Ya!'
Output:
Ruby!!
hi
See Ya!
Bye bye Mr. 5
But the problem is you canât directly use the {}
or do...end
without any method. You need to call a method before that. On the other hand the BEGIN {}
and END {}
will not accept do...end
block because itâs a syntax rather than a method.
As you said:
a==b ? { puts "=" } : { puts "!=" }
Yes, this will work if you replace the { } with ():
a = b = 5
a == b ? (puts "=") : (puts "!=") # prints =
# or because the ternary operator returns the first value when true, and the last value when false [just like `if then...elsif...else...end`:
puts a == b ? "=" : "!=" # prints =
Donât call your code ugly. My code is uglier!
I would rather use ? for creating string as well! puts a == b ? ?= : '!=' # prints =
You shouldnât worry unless Ruby is returning some warning about your syntax, because itâs fine. Rather than making code pretty, try to make it faster! Because if itâs the part of the community, then you shouldnât worry about that too muchâŚ
https://docs.ruby-lang.org/en/trunk/syntax/literals_rdoc.html
Hope this was fun and not over-complicatedâŚ