A typical Ruby project includes a handful of utility scripts for various administrative tasks or setup. These scripts usually start with a shebang followed by a couple lines of Ruby code. Eventually the script begins to grow in complexity, filling with duplicated logic and repeating structures.

At this point I usually extract some methods. But for any script of a certain complexity, a problem emerges. The core of the script is in the root scope, so any functions it depends on must be declared first. This pushes the body of the script downward, obscuring the purpose of the script. Plus, usually functions depend on other functions, which are typically declared lower down, further confusing the order of the script.

One way out of this is to wrap the body in its own function, called run or main and move it back to the top of the script. However, this function must be called , which is easy to miss or forget. Luckily, Ruby has a helpful hook that can be used to fix this situation. Instead of declaring the body of the script as a function, I can wrap it in a block passed to at_exit, which ensures the script is run. e.g.

#!/usr/bin/env ruby

at_exit do
  params = parse_args
  greet(params[:name])
end

def parse_args(args = ARGV)
  { name: args.shift || 'world' }
end

def greet(name)
  puts "Hello, #{name}!"
end

Now the script reads clearly from top to bottom and has a simple flow for breaking out complex logic into functions. As a final tweak, for projects with several scripts like this, I can alias at_exit to a function called main, which lives in utils/autorun.rb and is a little more obvious to anyone else reading it.