Question
I installed RubyInstaller on Windows and am using an IMAP synchronization Ruby script. I need to synchronize hundreds of accounts, so I want to supply the connection settings from the command line rather than editing the script for every account.
The script currently contains fixed values such as:
# Source server connection info.
SOURCE_NAME = 'username@example.com'
SOURCE_HOST = 'mail.example.com'
SOURCE_PORT = 143
SOURCE_SSL = false
SOURCE_USER = 'username'
SOURCE_PASS = 'password'
# Destination server connection info.
DEST_NAME = 'username@gmail.com'
DEST_HOST = 'imap.gmail.com'
DEST_PORT = 993
DEST_SSL = true
DEST_USER = 'username@gmail.com'
DEST_PASS = 'password'
How can these values be passed to the Ruby script when it is run from the command line so the process can be automated?
Short Answer
Ruby scripts receive command-line values through the ARGV array. For a small script, positional arguments can work; for many named settings, OptionParser makes commands clearer and easier to validate. Passwords should normally be supplied through environment variables or a protected configuration source rather than directly on the command line.
Concept
A Ruby program can receive input at the moment it starts. This lets one script work with different accounts, files, servers, or settings without changing its source code.
Ruby places command-line arguments in ARGV, an array of strings. For example, when you run:
ruby sync.rb alice@example.com mail.example.com
Ruby receives:
ARGV # => ["alice@example.com", "mail.example.com"]
This is useful for automation because a batch file, PowerShell script, scheduler, or another program can run the same Ruby script repeatedly with different input.
However, mail connection settings include passwords. A password written in a command can be exposed in shell history, process listings, logs, or scheduled-task definitions. Use environment variables, a secrets manager, or a file with restricted permissions for secrets whenever possible.
Also note that every item in ARGV is text. A port such as "993" must be converted with Integer, and a value such as "true" must be deliberately converted into a Boolean.
Mental Model
Think of a Ruby script as a form-processing machine.
- The script file is the machine's fixed set of instructions.
- Command-line arguments are values written on a form when the machine starts.
ARGVis the tray holding the submitted values.OptionParseris the receptionist that reads labelled fields such as--source-hostand rejects incomplete forms.- Environment variables are a separate, less visible envelope for sensitive details such as passwords.
Avoid relying on an argument's position when there are many settings. A command like sync.rb a b c d e f is difficult to read. Labelled options communicate what each value means.
Syntax and Examples
Ruby exposes command-line arguments through ARGV.
# greet.rb
name = ARGV[0]
puts "Hello, #{name}!"
Run it:
ruby greet.rb Ada
Output:
Hello, Ada!
For a connection script, named options are usually clearer. Ruby's standard-library OptionParser can parse them:
require "optparse"
options = {}
OptionParser.new do |parser|
parser.on("--source-host HOST", "Source IMAP host") do |host|
options[:source_host] = host
end
parser.on("--source-port PORT", Integer, "Source IMAP port") do |port|
options[:source_port] = port
end
end.parse!
puts options.inspect
Run it:
ruby sync.rb --source-host mail.example.com --source-port 143
The Integer argument tells OptionParser to convert the port from text into an integer. Named options can appear in any order, which is safer than depending on ARGV[0], ARGV[1], and so on.
Step by Step Execution
Consider this script:
# connect.rb
host = ARGV[0]
port = Integer(ARGV[1])
ssl = ARGV[2] == "true"
puts "Host: #{host}"
puts "Port: #{port}"
puts "SSL: #{ssl}"
Run it:
ruby connect.rb imap.gmail.com 993 true
Execution steps:
-
Ruby starts
connect.rband createsARGV:["imap.gmail.com", "993", "true"] -
ARGV[0]is assigned tohost, sohostbecomes"imap.gmail.com". -
ARGV[1]is"993", which is a string.Integer("993")converts it to the number993. -
ARGV[2] == "true"compares the text exactly. It evaluates totrue, sosslbecomes the Boolean valuetrue. -
putsdisplays the parsed settings.
If the port is missing or not numeric, Integer raises an error. In a production script, validate input and print a helpful usage message instead of allowing an unclear failure.
Real World Use Cases
Command-line input makes scripts reusable in many situations:
- Email migrations: Run one synchronization command per account from a CSV-driven PowerShell or Ruby script.
- File processing: Pass an input filename, output directory, and processing mode.
- Deployments: Provide a target environment such as
--environment staging. - API utilities: Pass an endpoint, date range, and report format while keeping API keys in environment variables.
- Scheduled jobs: Configure a task with options rather than maintaining separate copies of the same script.
- Data imports: Select a database host, input file, and dry-run mode at runtime.
Real Codebase Usage
In real Ruby projects, developers normally combine clear option parsing, validation, and secure secret handling.
Use named options for non-secret settings
ruby sync.rb --source-user alice --source-host mail.example.com --dest-user alice@gmail.com
Named options are self-documenting and remain understandable in logs or task definitions.
Use environment variables for passwords
In PowerShell:
$env:SOURCE_PASS = "source-password"
$env:DEST_PASS = "destination-password"
ruby sync.rb --source-user alice --source-host mail.example.com --dest-user alice@gmail.com
In Ruby:
source_pass = ENV.fetch("SOURCE_PASS")
dest_pass = ENV.fetch("DEST_PASS")
ENV.fetch fails immediately if the required value is absent, which is better than silently continuing with nil.
Validate before connecting
A common pattern is to check required values before doing network work:
required = %i[source_host source_user dest_host dest_user]
missing = required.reject { |key| options[key] }
abort "Missing required options: #{missing.join(', ')}" unless missing.empty?
Store account lists outside the code
For hundreds of accounts, put non-secret account metadata in a CSV, JSON, or database. Then loop through each record and invoke synchronization logic. Keep secrets in a protected credential store or retrieve them through an approved secret-management approach.
Common Mistakes
Treating all arguments as the correct type
Arguments are always strings initially.
port = ARGV[0]
# port is "993", not 993
Convert values that need numeric types:
port = Integer(ARGV[0])
Assuming strings become Boolean values
This code is incorrect:
ssl = ARGV[0]
if ssl
puts "SSL enabled"
end
Even "false" is a non-empty string and is therefore truthy in Ruby. Parse it explicitly:
ssl = ARGV[0] == "true"
For more robust validation:
ssl_text = ARGV[0]
abort "SSL must be true or false" unless %w[true false].include?(ssl_text)
ssl = ssl_text == "true"
Using constants for per-run configuration
Constants such as SOURCE_HOST are appropriate for values that should not change during a program's lifetime. Runtime options are clearer as local variables or entries in an options hash.
source_host = options[:source_host]
Exposing passwords in commands
Avoid this where possible:
ruby sync.rb --source-pass my-secret-password
It may be saved in command history or visible to other users or tools. Prefer ENV.fetch("SOURCE_PASS") or another protected secret source.
Not checking missing arguments
This can fail later with confusing errors:
host = ARGV[0]
# host may be nil
Check required input early, or let OptionParser provide a usage message.
Using too many positional arguments
This is hard to maintain:
ruby sync.rb alice host 143 false password bob host2 993 true password2
Use named options, especially when a script has more than two or three inputs.
Comparisons
| Approach | Best for | Strengths | Limitations |
|---|---|---|---|
ARGV positional arguments | Tiny scripts with one or two values | Minimal code | Order-dependent and hard to read with many values |
OptionParser named options | Command-line tools with several settings | Clear names, help text, type conversion | Requires a little more setup |
Environment variables (ENV) | Passwords, tokens, and deployment-specific settings | Keeps secrets out of the argument list | Must be set before running the script |
| Configuration file | Reusable groups of non-secret settings | Convenient for many accounts | Must be protected and validated; do not casually store passwords in plain text |
Positional versus named options
# Positional: the order must be remembered.
ruby sync.rb mail.example.com 143
# Named: each value identifies itself.
ruby sync.rb --source-host mail.example.com --source-port 143
ARGV versus ENV
host = ARGV[0] # Supplied in the command itself
password = ENV.fetch("PASS") # Supplied through the environment
Use ARGV for ordinary user-facing input and ENV for sensitive or environment-specific values.
Cheat Sheet
# All command-line arguments
ARGV
# First positional argument
name = ARGV[0]
# Convert a numeric argument
port = Integer(ARGV[1])
# Parse a true/false argument
ssl = ARGV[2] == "true"
# Read a required environment variable
password = ENV.fetch("SOURCE_PASS")
# Stop with an error message
abort "Missing --source-host"
require "optparse"
options = {}
OptionParser.new do |parser|
parser.on("--host HOST") { |value| options[:host] = value }
parser.on("--port PORT", Integer) { |value| options[:port] = value }
parser.on("--ssl", "Use SSL") { options[:ssl] = true }
end.parse!
Key rules:
ARGVvalues start as strings."false"is truthy in Ruby; parse Boolean text explicitly.- Use
Integer(value)for numeric validation and conversion. - Prefer named options when there are several inputs.
- Do not normally put passwords directly in command-line arguments.
OptionParser#parse!reads options and removes them fromARGV.
FAQ
How do I access command-line arguments in Ruby?
Use the ARGV array. ARGV[0] is the first argument after the script name, ARGV[1] is the second, and so on.
Why is my Ruby command-line port a string?
The shell sends arguments as text. Convert a port with Integer(ARGV[0]) or use OptionParser with the Integer type.
How do I pass a Boolean value to a Ruby script?
Use a deliberate comparison such as value == "true". Do not use a non-empty string directly in an if, because both "true" and "false" are truthy in Ruby.
Should I pass a password as a command-line argument?
Usually no. It can appear in command history, logs, or process information. Use an environment variable, a protected configuration system, or a secret manager.
What is OptionParser in Ruby?
OptionParser is a Ruby standard-library tool for accepting named command-line options, generating help text, and converting option values to types such as integers.
Can I use command-line options on Windows with RubyInstaller?
Yes. Ruby's ARGV, ENV, and OptionParser work on Windows. Use Command Prompt or PowerShell syntax appropriate to the shell you are using.
What should I use for hundreds of accounts?
Keep the script configurable, and store account metadata in a CSV, JSON file, or database. Iterate over those records while retrieving passwords from a secure source.
Mini Project
Description
Build a small Ruby command-line configuration checker for an IMAP synchronization job. It accepts source and destination connection settings as named options, reads passwords from environment variables, validates required values, and prints a safe summary without displaying secrets.
Goal
Create a reusable command that validates IMAP settings for any account without editing Ruby source code.
Requirements
Use OptionParser to accept source and destination host, user, and port options.
Accept --source-ssl and --dest-ssl as flags.
Read SOURCE_PASS and DEST_PASS from environment variables.
Reject missing required options before printing the configuration.
Do not print either password.
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.