Semicolon
This isn't JavaScript, so you're not going to see much of the venerable semicolon in Ruby. It does exist though. The main context in which you'll see a semicolon in Ruby is for anytime you want multiple statements on the same line. We'll also look at how it can be used in block arguments.
Multiple Statements on One Line
You might use a semicolon if you're writing a Ruby one-liner ↗.
For example, extracting lines between two regex ↗:
$ ruby -ne '$f=1 if /BEGIN/; print if $f==1; $f=0 if /END/' range.txt
As another example, for a long time I had a Vim alias setup to inject the following line into a file for debugging purposes:
require 'pry'; binding.pry
I've also seen ;
used occassionally for inline custom error classes.
class RegistrationForm
class ValidationError < StandardError; end
# ...
def validate_email(email)
if User.where(email: email).any?
raise ValidationError, "Email (#{email}) is already in use"
end
end
end
Block Local Arguments
A block-local argument can be declared after a semicolon as a way of defining a local argument that will not override or call something by the same name outside the scope of the block.
class Order
def initialize(items)
@items = items
end
def summarize_items(total)
@items.each do |item; total|
total = item[:price] * item[:quantity]
puts "- #{item[:name]} : #{total}"
end
puts "Total: #{total}"
end
end
items = [
{name: "Taco", price: 5.0, quantity: 3},
{name: "Burrito", price: 10.0, quantity: 1}
]
order = Order.new(items)
order.summarize_items(26.50)
This example is a bit contrived, but it illustrates the point. When the block that goes through each item includes ; total
, then the total in the block is distinct from the total that gets passed into #summarize_items
.
The final line of the output will be Total: 26.5
.
If the block is adjust to look like the following:
def summarize_items(total)
@items.each do |item|
total = item[:price] * item[:quantity]
puts "- #{item[:name]} : #{total}"
end
puts "Total: #{total}"
end
then the setting of total
in the block conflicts with the incoming total
to the outer method. The final line of that output will be Total: 10.0
. Not what was intended.
Another obvious solution besides using this obscure bit of syntax is to use different variable names so that there are no conflicts across scope.