0

What's the point of ARGV in Ruby?

first, second, third = ARGV 
puts "The script is called: #{$0}"
puts "Your first variable is: #{first}"
puts "Your second variable is: #{second}"
puts "Your third variable is: #{third}"

What's the point of this when to run the file I need to do:

ruby ex1.rb

and to put in the first, second and third variables I need to type in

ruby ex1.rb blah blah blah

How does this benefit at all the person running the program? They can't do it anyway since I'd assume it be an executable:

user = ARGV.first
prompt = '> '

puts "Hi #{user}, I'm the #{$0} script."
puts "I'd like to ask you a few questions."
puts "Do you like me #{user}?"
print prompt
likes = STDIN.gets.chomp()

puts "Where do you live #{user}?"
print prompt
lives = STDIN.gets.chomp()

puts "What kind of computer do you have?"
print prompt
computer = STDIN.gets.chomp()

puts <<MESSAGE
Alright, so you said #{likes} about liking me.
You live in #{lives}.  Not sure where that is.
And you have a #{computer} computer.  Nice.
MESSAGE

Can someone please explain this to me?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Jason
  • 177
  • 1
  • 1
  • 3
  • 5
    "They can't do it anyway since I'd assume it be an executable" shows a flaw in the thinking. What difference does something make if it's executable? That's merely a bit that's set in the OS and doesn't affect whether a script can accept parameters. Perhaps you meant the script would be launched and used with a GUI, but, even then, it's possible for the script to receive parameters as part of its start-up process... which makes me think this whole question is fallacious. – the Tin Man Sep 11 '13 at 15:01
  • 3
    In the example given, all the input is gathered during the run, in response to user input. ARGV is to gather that data at the start of the run, without user input. – JDS Oct 03 '13 at 18:20
  • 3
    Consider the case when each "chunk" of your code above is fairly expensive, and takes e.g. 10 seconds to run. Would you rather type, wait 10s, type, wait 10s etc... -or- type, then wait 30 seconds? There's one example of why it's useful to provide arguments at initial execution, rather than as and when they are needed. – Adam Marshall Mar 16 '14 at 11:25
  • It's also possible to run ruby scripts (and lots of other things) using a shebang line like `#!/usr/bin/env ruby` at the top of your `ex1.rb` file. If you `chmod a+x ex1.rb`, you can run it _without_ the `ruby ` prefix: `./ex1.rb`. And in fact the `.rb` extension isn't even necessary, which means you might have already been using ruby scripts that take command line arguments without even realizing it. – beporter Jun 11 '20 at 12:34

5 Answers5

89

What's the point of ARGV in Ruby?

ARGV "contains the arguments passed to your script, one per element."

What's the point of this when to run the file you need to do: ruby ex1.rb and to put in the first, second and third variables you need to type in ruby ex1.rb blah blah blah.

That is the exact point, to be able to specify arguments when running the file like:

ruby ex1.rb -a -b 3

How does this benefit at all the person running the program?

Same benefit any other command-line program gets from being able to do so: the user can specify upfront what they want, and it's easier to script than an interactive CLI.

They can't do it anyway since I'd assume it be an executable.

Yes, they can. You just gave an example of exactly how the user would run your program that way. Whether it's executable or not doesn't change anything.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
  • I was working through the same problem and initially had some confusion but then was able to work it out. Your ARGV answer here helped confirm my understanding. My only question is what is the ".first" in user = "ARGV.first"? – Padawan Jun 15 '15 at 11:04
  • @Padawan `ARGV` is an array of all arguments (as pointed out in the linked docs in my answer), so `ARGV.first` gets the first one. Just regular-old [`Array#first`](http://ruby-doc.org/core/Array.html#method-i-first) in-use here. – Andrew Marshall Jun 15 '15 at 13:12
26

ARGV has a long tradition and comes from the UNIX/POSIX world where most C programs must contain the following:

int main(int argc, char **argv)
{
   return(0);
}

There argc represents the number of arguments supplied, and argv is a low-level pointer to the first of potentially a number of string pointers. The name argv has stuck around in various forms.

Command-line arguments are very popular with developers, though they're usually not used quite as you seem to think. Un-named arguments are much harder to deal with. That's why things like optparse exist to help deal with them.

Here's an example from the OptionParser documentation:

require 'optparse'

options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!

p options
p ARGV

This allows you to define much more usable command-line arguments and then use them. For your example, I'd expect it to work like this:

test_script --live "New York" --computer "Lenovo" --like

That makes it quite obvious what the arguments are because they're named.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
tadman
  • 208,517
  • 23
  • 234
  • 262
13

Consider some Ruby command line utilities like rails, rake,gem, or bundle. While none of these are end-user applications (like web apps or GUI apps), they are still programs written in Ruby that users interact with. All of them take arguments:

$ rails new my_app
$ rake tests
$ gem install rails --no-rdoc --no-ri
$ bundle update

It is possible to use ARGV to implement these kinds of command line programs that accept arguments. While we'll often use the OptionParser standard library or some other tool for this purpose, ARGV is the low level collection those tools are built on top of.

So if you've ever run gem, rails, rake, or bundle, or any command line developer tool that is written in Ruby, you will have benefited from ARGV!

Gregory Brown
  • 1,380
  • 9
  • 15
5

The point of ARGV is that it enables scripts to be able to run without human input, and also allows for the case where the input may vary from one iteration to the next.

For example you may be running three different scripts to get three values. These values could then be passed into this script and ARGV can be used to get the values of these options.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Gary
  • 1,917
  • 3
  • 19
  • 19
3

I used to run a script that asked me for an email and password. It was used to log into one of 100's of accounts. Like most Ruby scripts, I'd run it from the command line. This had to semblance to being an "executable", especially not one with an icon that you click.

I'd run the program and it would ask me for email and password then log me in using Watir.

puts "Email of Account"
account_email = gets.chomp

puts "Enter Password"
password = gets.chomp

# code that logs me in

However, I found that taking in those values via ARGV was much faster for my purposes.

account_email, password = ARGV
# code that logs me in

Then I could just type

$ ruby my_script.rb my.email@emailplace.com mypassword

and hit enter. Also I could just press the up arrow in the console to run it again and again or recent versions with different names and passwords to test my script quickly.

Taking it a step further, I made a shell script that could run this scripts, args and all in many combinations

ruby my_script.rb oneofmy@emails.com mypassword
ruby my_script.rb another@emails.com otherpassword

Finally, sometimes I needed to set dozens of settings per each time I ran a script, and then run that script many times. So I could also easily insert a dozens variables into a script from the command line

ruby my_script.rb option1 option2 option3 option4

I'm very new to using ARGV and hope to learn better ways to use it, but this is one feature I found very useful.

John Escobedo
  • 128
  • 1
  • 6