Standalone script/runner bin scripts in Rails
script/runner
or script/rails runner
scripts are common in Rails apps for doing maintenance tasks. However, this
only works well until you have several arguments to parse from the command line. Putting standalone scripts in /bin
instead gives you easier, more flexible argument parsing and cleaner command lines and crontab entries.
Arguments with script/runner
First, you could just hack the argument parsing out, especially when using an argument delimiter like --
:
$ script/rails runner lib/my_script.rb -e production -- arg1 arg2 arg3 --opt1=foo --opt2=bar
Not attractive, but here’s how:
#!/usr/bin/env ruby
# first try and show proper usage if arguments aren’t well-formed:
def usage
abort “usage: script/rails runner -e production scripts/#{FILE} – [options]”
end
# not using script/rails runner?
usage unless Object.const_defined?(:Rails)
# missing the argument delimiter?
usage unless ARGV.include?(”–”)
# now, clean up ARGV:
loop { break if ARGV.shift == ”–” }
# your code here, with a clean ARGV
Standalone bin script
All script/rails runner
does is parse the optional environment out of the command line, bootstrap the Rails code, and
then execute your code. If you assume RAILS_ENV
is set appropriately in your production crontabs, then it’s easy to do
this yourself.
The ideal command line:
$ bin/my_script arg1 arg2 arg3 --opt1=foo --opt2=bar
Rails 3
#!/usr/bin/env ruby
APP_PATH = File.expand_path(’../../config/application’, FILE)
require File.expand_path(’../../config/boot’, FILE)
require APP_PATH
# set Rails.env here if desired
Rails.application.require_environment!
# your code here…
Rails 2
#!/usr/bin/env ruby
require File.expand_path(’../../config/boot’, FILE)
# set RAILS_ENV here if desired
require RAILS_ROOT + ’/config/environment’
# your code here…
Option Parsing
Using the standard boilerplate normally provided by script/rails runner
, this gives you a cleaner command line and
more flexibility with option parsing. When using optparse, optimist or other option
parsing libraries, you could still retain the -e <environment>
option. Otherwise, just set RAILS_ENV
appropriately
and you’re good to go.