← Back to Ruby Operators

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.

References