Ruby BEGIN and END blocks

In Ruby, the reserved words BEGIN and END are used to execute code at the beginning and end of a Ruby program, respectively. These two keywords are counterparts of each other.

It is important to note that BEGIN and END must be followed by an open curly brace { and end with a closed curly brace }.
These curly braces are required, and you cannot replace them with a do/end block.
It’s important to note that all caps (BEGIN and END) and the ones usually separated by a slash (begin/end) serve different purposes and should not be confused with each other.

variable scope

variable defined in the BEGIN and END block operates in global scope.

BEGIN block

The BEGIN block in Ruby is used to execute the code before everything else when the Ruby source file loads.
It can be useful for initializing variables or performing other setup tasks before the main code execution begins.
For example:

puts "Hello Ruby! [1]"

BEGIN {
  require 'logger'

  $logger = Logger.new('app.log')
  $logger.level = Logger::INFO
  puts("BEGIN block.[2]")
}

puts("Hello Ruby [3]")

Output:

BEGIN block.[2]
Hello Ruby! [1]
Hello Ruby [3]

When there are multiple BEGIN blocks in the source code, they are executed based on their sequence.
The BEGIN blocks defined higher in the source code are executed before the ones defined later.
This means that the order of appearance in the source code determines the order of execution.

For example:

config.yml

database:
  host: "localhost"
puts "Hello Ruby! [1]"

BEGIN {
  require 'logger'

  $logger = Logger.new('app.log')
  $logger.level = Logger::INFO
  puts("BEGIN block1.[2]")
}

BEGIN {
  require 'yaml'

  $config = YAML.load_file('config.yml')
  
  puts("BEGIN block2.[3]")
}

puts "Database host: #{$config['database']['host']}"

$logger.info("Main program execution started.")
puts("Hello Ruby [4]")

output:

BEGIN block1.[2]
BEGIN block2.[3]
Hello Ruby! [1]
Database host: localhost
Hello Ruby [4]

END block

END block executes the code inside at the end, just before the temination of the programm.

For example

puts "Hello Ruby! [1]"

END {
  puts("END block.[2]")
}

puts("Hello Ruby [3]")

output:

Hello Ruby! [1]
Hello Ruby [3]
END block.[2]

In source code, when multiple END blocks are present, they are executed in a reverse order of their appearance.
This means that the END block defined last in the source code will be executed first, and the END block defined first will be executed last.

For example:

puts "Hello Ruby! [1]"

END {
  puts("END block.[2]")
}

END {
  puts("2nd END block.[3]")
}

puts("Hello Ruby [4]")

output:

Hello Ruby! [1]
Hello Ruby [4]
2nd END block.[3]
END block.[2]

Possible Usecase of BEGIN and END block

BEGIN block can be used in Configuration Loading, Logging Initialization, Creating Temporary Files, etc..
END block can be used in Cleanup Tasks, Final Reporting, etc..