Accepting Command-Line Arguments into a Ruby Script

ayyp picture ayyp · Mar 27, 2012 · Viewed 7.4k times · Source

I'm trying to use the following code to accept in a file as an argument in Terminal which will then be read and update the body variable with its contents. If the file is not passed in then I want to have the prompt where the user can enter their own body copy.


require 'posterous'

Posterous.config = {
  'username'  => 'name',
  'password'  => 'pass',
  'api_token' => 'token'
}

include Posterous
@site = Site.primary

#GETS POST TITLE
puts "Post title: "
title = STDIN.gets.chomp()

if defined?(ARGV)
  filename = ARGV.first
end

if (defined?(filename))
  body = File.open(filename)
  body = body.read()
else
  puts "Post body: "
  body = STDIN.gets.chomp()
end
puts body

When I run the program without passing in a file I get this returned:


Post title: 
Hello
posterous.rb:21:in `initialize': can't convert nil into String (TypeError)
    from posterous.rb:21:in `open'
    from posterous.rb:21:in `'

I'm rather new to ruby and thus am not the best at it. I've tried swapping a lot of things around and changing things but to no avail. What am I doing wrong?

Answer

Michael Berkowski picture Michael Berkowski · Mar 27, 2012

defined?(ARGV) won't return a boolean false, but rather "constant". Since that doesn't evaluate to false, filename gets defined as ARGV[0], which is nil.

>> ARGV
=> []
>> defined?(ARGV)
=> "constant"
?> ARGV.first
=> nil

Instead you might check the length of ARGV:

if ARGV.length > 0
  filename = ARGV.first.chomp
end

From the docs:

defined? expression tests whether or not expression refers to anything recognizable (literal object, local variable that has been initialized, method name visible from the current scope, etc.). The return value is nil if the expression cannot be resolved. Otherwise, the return value provides information about the expression.