# Problem getting user input

**URL:** <https://www.ruby-forum.com/t/problem-getting-user-input/121071>\
**Category:** Ruby\
**Created:** [November 23, 2007, 1:40pm UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071 "2007-11-23T13:40:13Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![wpvanpaassen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/6f9a4e/32.png) [@wpvanpaassen](https://www.ruby-forum.com/u/wpvanpaassen)\
**Post date:** [November 23, 2007, 1:40pm UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071/1 "2007-11-23T13:40:13Z")

</div>

I wrote a script that gets user input like this:

$stdout.print "Do you want to change something else? (y/n): "  
$changeSE = gets.chomp  
if $changeSE =~ /^y/  
changeSomethingElse  
end

After the prompt is printed, the script waits for the user to enter yes  
or no via stdinput. The script was written in a procedural format as  
opposed to OO. (I did that only because I’m in the process of learning  
OO, and needed the script asap.) I decided to rewrite the script using  
OO. Unfortunately, this part of the script doesn’t work anymore. The  
prompt prints, then the script keeps going on its merry way. I’ve  
included the source for the script below. Can anyone (or everyone) see  
what I’m not doing correctly? If so, I’d appreciate it if you could  
explain how to correct the problem. I’d be extremely grateful for any  
and all comments and assistance.  
PV

1 #!/usr/bin/ruby  
2 #  
3 # fix1.rb - Fix common unitization file errors.  
4 # 1. Remove header line.  
5 # 2. Populate vendor label field with “NULL”.  
6 # 3. Change .TIF extension to lower case.  
7 #  
8 class Record  
9  
10 # Constructor.  
11 def initialize (record\_string)  
12 @record = record\_string  
13 end  
14  
15 # Populates the volume label.  
16 # regex: Start at the beginning of the line, match  
17 # all non-comma characters, followed by 2 commas.  
18 def fix\_volume\_label  
19 # @record.sub!(/\d,/,’,NULL,’)  
20 @record.sub!(/^([^,]_),/, ‘\1,NULL,’)  
21 end  
22  
23 # Change file extension to lowercase.  
24 def fix\_extension\_case  
25 @record.sub!(’.TIF’,’.tif’)  
26 end  
27  
28 # Allow user to do a generic fix.  
29 def changeSomethingElse  
30 @record.sub!(before,after)  
31 end  
32  
33 # Returns fixed record as a string  
34 def to\_str  
35 @record  
36 end  
37  
38 end  
39  
40 # Main thread of execution.  
41 class FixOpt  
42  
43 def initialize  
44  
45 @ARGV = $_ # list of arguments passed to the  
script  
46 @header\_regex = /BegBates,Volume,Path/  
47  
48 @in\_file = nil  
49 # @out\_file = nil  
50 unless arguments\_valid? @ARGV  
51 usage  
52 exit -1  
53 end  
54  
55 # Does user want to change something else?  
56 def checkChange  
57 puts "Do you want to change something else (y/N): "  
58 changeIt = gets  
59 if changeIt =~ /^[yY]/  
60 puts "Enter string to change: "  
61 before = gets.chomp  
62 puts "Enter new string: "  
63 after = gets.chomp  
64 puts "Global change? (N/y): "  
65 global = gets.chomp  
66 end  
67 end # End checkChange method.  
68  
69 begin  
70 @in\_file = File.new @ARGV[0], “r”  
71 rescue IOError  
72 @in\_file.close  
73 puts “Error opening input file, terminating”  
74 exit -1  
75 end  
76  
77 end # End initialize method.  
78  
79 # Runs the program - the [C]ontroller portion of the MVC pattern.  
80 def run  
81 begin  
82 checkChange  
83 @in\_file.each do |record\_line|  
84 next if record\_line =~ @header\_regex  
85 record = Record.new(record\_line)  
86 record.fix\_volume\_label  
87 record.fix\_extension\_case  
88 if changeIt =~ /^[yY]/  
89 record.changeSomethingElse  
90 end  
91 puts record.to\_str  
92 end  
93 rescue IOError  
94 @in\_file.close  
95 puts “Error reading from input file, terminating”  
96 exit -1  
97 end  
98 @in\_file.close  
99 exit 0 # success!  
100 end  
101  
102 # these methods are marked :private becuase they are never to be  
called  
103 # from anywhere outside of the class itself.  
104 :private  
105  
106 # Validates command line arguments.  
107 def arguments\_valid? (argv)  
108 # readable assumes the file exists, but doesn’t check for it.  
109 # File.stat(ARGV[0]).readable?  
110 # Returns true if the named file exists and is a regular file.  
111 File.file?(ARGV[0])  
112 end  
113  
114 # Prints the usage message  
115 def usage  
116 puts  
117 puts “Invalid filename entered: #{ARGV[0]}”  
118 puts "Syntax: fix1.rb "  
119 puts  
120 end  
121  
122 end  
123 fix\_opt = FixOpt.new  
124 fix\_opt.run

If I use gets, the script just prints the prompt and seems to end.  
If I use gets.chomp I get the following error:  
$ ruby d:/scripts/ruby/fix1.rb 99999.opt  
Do you want to change something else (y/N):  
d:/scripts/ruby/fix1.rb:58:in `checkChange': private method`chomp’  
called for nil:NilClass (NoMethodEr  
ror)  
from d:/scripts/ruby/fix1.rb:82:in `run’  
from d:/scripts/ruby/fix1.rb:124

---

<div class="post-metadata">

**Author:** ![wpvanpaassen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/6f9a4e/32.png) [@wpvanpaassen](https://www.ruby-forum.com/u/wpvanpaassen)\
**Post date:** [November 23, 2007, 6:09pm UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071/2 "2007-11-23T18:09:54Z")

</div>

On Nov 23, 2007, at 7:40 AM, Peter V. wrote:

> or no via stdinput. The script was written in a procedural format as  
> and all comments and assistance.  
> 9  
> 20 @record.sub!(/^([^,]\*),/, ‘\1,NULL,’)  
> 31 end  
> 42  
> 52 exit -1  
> 63 after = gets.chomp  
> 74 exit -1  
> 85 record = Record.new(record\_line)  
> 96 exit -1  
> 105  
> 116 puts  
> If I use gets.chomp I get the following error:  
> $ ruby d:/scripts/ruby/fix1.rb 99999.opt  
> Do you want to change something else (y/N):  
> d:/scripts/ruby/fix1.rb:58:in `checkChange': private method`chomp’  
> called for nil:NilClass (NoMethodEr  
> ror)  
> from d:/scripts/ruby/fix1.rb:82:in `run’  
> from d:/scripts/ruby/fix1.rb:124

I can not reproduce your problem. When I run

`
class Foo
    def checkChange
       puts "Do you want to change something else (y/N): "
       changeIt = gets.chomp
       if changeIt =~ /^[yY]/
          puts "Enter string to change: "
          before = gets.chomp
          puts "Enter new string: "
          after = gets.chomp
          puts "Global change? (N/y): "
          global = gets.chomp
       end
       p [changeIt, before, after, global]
    end
end
Foo.new.checkChange
`

I see the following

Do you want to change something else (y/N): Enter string to change: Enter new string: Global change? (N/y): ["y", "foo", "bar", "n"]

I will note the variables changeIt, before, after, and global are  
local variables and will not available outside of the checkChange  
method. That may be part of your problem.

Regards, Morton

---

<div class="post-metadata">

**Author:** ![wpvanpaassen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/6f9a4e/32.png) [@wpvanpaassen](https://www.ruby-forum.com/u/wpvanpaassen)\
**Post date:** [November 23, 2007, 6:28pm UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071/3 "2007-11-23T18:28:39Z")

</div>

Peter V. wrote:

> If I use gets, the script just prints the prompt and seems to end.

I see in your script that ARGV is not empty. That means Kernel#gets is  
gonna read from the files in ARGV and not from stdin. To rectify that  
use $stdin.gets instead. Or empty ARGV before you call gets.

HTH,  
Sebastian

---

<div class="post-metadata">

**Author:** ![wpvanpaassen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/6f9a4e/32.png) [@wpvanpaassen](https://www.ruby-forum.com/u/wpvanpaassen)\
**Post date:** [November 23, 2007, 7:45pm UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071/4 "2007-11-23T19:45:02Z")

</div>

Sebastian,  
THANK YOU, THANK YOU, THANK YOU!  
The $stdin.gets works perfectly! I really appreciate all you  
experienced folks helping out this newbie! I’m going to hilight this  
stuff in PickAxe when I get done.  
PV

Sebastian H. wrote:

> Peter V. wrote:
> 
> > If I use gets, the script just prints the prompt and seems to end.
> 
> I see in your script that ARGV is not empty. That means Kernel#gets is  
> gonna read from the files in ARGV and not from stdin. To rectify that  
> use $stdin.gets instead. Or empty ARGV before you call gets.
> 
> HTH,  
> Sebastian

---

<div class="post-metadata">

**Author:** ![wpvanpaassen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/6f9a4e/32.png) [@wpvanpaassen](https://www.ruby-forum.com/u/wpvanpaassen)\
**Post date:** [November 23, 2007, 10:36pm UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071/5 "2007-11-23T22:36:44Z")

</div>

On Nov 23, 2007, at 1:44 PM, Peter V. wrote:

> > I see in your script that ARGV is not empty. That means  
> > Kernel#gets is  
> > gonna read from the files in ARGV and not from stdin. To rectify that  
> > use $stdin.gets instead. Or empty ARGV before you call gets.

Speaking of ARGV, you don’t need this line in your code:

45 @ARGV = $\* # list of arguments passed to the script

Just use the pre-defined ARGV instead of @ARGV

Regards, Morton

---

<div class="post-metadata">

**Author:** ![wpvanpaassen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/6f9a4e/32.png) [@wpvanpaassen](https://www.ruby-forum.com/u/wpvanpaassen)\
**Post date:** [November 25, 2007, 9:12am UTC](https://www.ruby-forum.com/t/problem-getting-user-input/121071/6 "2007-11-25T09:12:47Z")

</div>

If you do write many scripts that require prompting for user input, you  
should check out highline [http://highline.rubyforge.org/](http://highline.rubyforge.org/)

enjoy,

-jeremy
