From: Morton Goldberg Date: 2007-11-24T02:09:00+09:00 Subject: Re: Problem getting user input On Nov 23, 2007, at 7:40 AM, Peter Vanderhaden wrote: > 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 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