Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accepting Command-Line Arguments into a Ruby Script

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?

like image 224
ayyp Avatar asked Dec 16 '22 02:12

ayyp


2 Answers

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.

like image 59
Michael Berkowski Avatar answered Dec 27 '22 09:12

Michael Berkowski


Michael gave you the basic answer to your question. A slightly more Rubyish way of doing that would be to use ARGF to do the reading; then the conditional is only needed to decide whether or not to print the prompt:

puts "Post title: "
title = gets.chomp

puts "Post body: " if ARGV.length == 0
body = ARGF.gets.chomp
puts body

..of course, if you don't need to anything else with body, you can skip storing the contents of the file(s) and just do

puts ARGF.gets.chomp
like image 35
Mark Reed Avatar answered Dec 27 '22 09:12

Mark Reed