Ruby BEGIN and END Keywords
last modified April 27, 2025
This tutorial explains how to use Ruby's BEGIN
and END
keywords. These special blocks control code execution at program start and exit.
The BEGIN keyword defines a block that runs before any other code. The END keyword defines a block that runs after all other code.
These hooks are useful for initialization and cleanup tasks. They execute regardless of program flow or exit conditions. Multiple blocks stack in order.
Basic BEGIN and END Example
This simple example demonstrates the execution order of BEGIN and END blocks. Notice they run outside the normal program flow.
BEGIN { puts "This runs first" } END { puts "This runs last" } puts "This runs in between"
The BEGIN
block executes before any other code, while
END
runs after everything. The main program output appears between
them as expected.
Multiple BEGIN/END Blocks
Ruby allows multiple BEGIN
and END
blocks.
BEGIN
blocks run in definition order, while END
blocks
execute in reverse order (like a stack).
BEGIN { puts "BEGIN 1" } BEGIN { puts "BEGIN 2" } END { puts "END 1" } END { puts "END 2" } puts "Main program"
Notice BEGIN
blocks execute top-to-bottom, while END
blocks run bottom-to-top. This behavior is consistent across Ruby versions.
BEGIN with Variable Initialization
BEGIN
blocks can initialize variables used in the main program.
This example sets up configuration before the main code runs.
BEGIN { $app_name = "My Ruby Program" $start_time = Time.now } puts "Welcome to #{$app_name}" puts "Started at #{$start_time}" END { puts "Program ran for #{Time.now - $start_time} seconds" }
Global variables ($) work best as they avoid scope issues. The END
block calculates total runtime using the BEGIN-initialized time.
Error Handling in END Blocks
END
blocks execute even when the program exits early or raises
exceptions. This makes them ideal for cleanup tasks.
BEGIN { puts "Starting risky operation" } END { puts "Cleanup always happens" } raise "Something went wrong!" if rand < 0.5 puts "This might not run"
The END block runs whether the program completes or fails. This ensures resources are properly released regardless of outcome.
File Operations with BEGIN/END
A common use case is file handling - opening in BEGIN
and closing
in END
. This guarantees proper resource management.
BEGIN { $log_file = File.open("output.log", "w") $log_file.puts "Log started: #{Time.now}" } def log(message) $log_file.puts message end log("Processing started") END { $log_file.puts "Log ended: #{Time.now}" $log_file.close puts "Log file closed" } log("Processing completed")
The file opens before any logging occurs and closes after all operations finish. This pattern ensures no resource leaks.
BEGIN with Command-line Arguments
BEGIN
blocks can process ARGV
before the main program.
This example handles early argument parsing.
BEGIN { $verbose = ARGV.delete("--verbose") puts "Verbose mode enabled" if $verbose } puts "Remaining arguments: #{ARGV.inspect}" END { puts "Verbose logging complete" if $verbose }
The BEGIN
block modifies ARGV
before the main program
sees it. The END
block can report on verbose operations if enabled.
Complex Program Structure
This example shows BEGIN/END in a larger program with multiple components. The blocks help organize setup and teardown.
BEGIN { require 'json' require 'net/http' $config = JSON.parse(File.read('config.json')) } BEGIN { $stats = { start: Time.now, requests: 0 } } def make_request(url) $stats[:requests] += 1 Net::HTTP.get(URI(url)) end make_request($config['api_endpoint']) END { duration = Time.now - $stats[:start] puts "Made #{$stats[:requests]} requests in #{duration} seconds" File.write('stats.json', JSON.dump($stats)) }
The BEGIN
blocks load dependencies and initialize tracking. The
END
block saves statistics regardless of how the program
terminates.
Source
This tutorial covered Ruby's BEGIN and END blocks with practical examples showing initialization, cleanup, and error handling patterns.
Author
List all Ruby tutorials.