Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is gets throwing an error when arguments are passed to my ruby script?

Tags:

ruby

gets

I'm using gets to pause my script's output until the user hits the enter key. If I don't pass any arguments to my script then it works fine. However, if I pass any arguments to my script then gets dies with the following error:

ruby main.rb -i
main.rb:74:in `gets': No such file or directory - -i (Errno::ENOENT)
    from main.rb:74:in `gets'
    ...

The error message is showing the argument I passed to the script. Why would gets be looking at ARGV?

I'm using OptionParser to parse my command line arguments. If I use parse! instead of parse (so it removes things it parses from the argument list) then the application works fine.

So it looks like gets is reading from ARGV for some reason. Why? Is this expected? Is there a way to get it to not do that (doing gets() didn't help).

like image 533
Herms Avatar asked Jan 30 '10 04:01

Herms


People also ask

How do you pass command line arguments in Ruby?

How to Use Command-Line Arguments. In your Ruby programs, you can access any command-line arguments passed by the shell with the ARGV special variable. ARGV is an Array variable which holds, as strings, each argument passed by the shell.

What is an argument error?

Making a Strong Argument Ruby's ArgumentError is raised when you call a method with incorrect arguments. There are several ways in which an argument could be considered incorrect in Ruby: The number of arguments (arity) is wrong. The value of the argument is unacceptable.

What does argv do in Ruby?

ARGV in Ruby In Ruby, ARGV is a constant defined in the Object class. It is an instance of the Array class and has access to all the array methods. Since it's an array, even though it's a constant, its elements can be modified and cleared with no trouble.


2 Answers

Ruby will automatically treat unparsed arguments as filenames, then open and read the files making the input available to ARGF ($<). By default, gets reads from ARGF. To bypass that:

$stdin.gets

It has been suggested that you could use STDIN instead of $stdin, but it's usually better to use $stdin.

Additionally, after you capture the input you want from ARGV, you can use:

ARGV.clear

Then you'll be free to gets without it reading from files you may not have intended to read.

like image 186
Wayne Conrad Avatar answered Sep 21 '22 01:09

Wayne Conrad


The whole point of Kernel#gets is to treat the arguments passed to the program as filenames and read those files. The very first sentence in the documentation reads:

Returns (and assigns to $_) the next line from the list of files in ARGV (or $*)

That's just how gets works. If you want to read from a specific IO object (say, $stdin), just call gets on that object.

like image 42
Jörg W Mittag Avatar answered Sep 20 '22 01:09

Jörg W Mittag