Trouble with variable scope with args Ruby script

277 views Asked by At

I am having a problem with variable scope when reading args into global variables in Ruby. I get this error when I run the following script. not sure what I am doing wrong; any ideas?

$ ./parse_args_example.rb --config=./config/tests.yml --type=Mag --envs=['warm','humid']
ARGV =>
Creating new instance of FlashLight...
./parse_args_example.rb:45:in `<main>': undefined local variable or method `configArg' for main:Object (NameError)

And the code:

#!/usr/bin/env ruby
$stderr.sync = true

require 'optparse'

# default options
$configArg  = "./config/config.yml"
$typeArg = "Mag"
$envsArg = ['dark','snow']
$ledArg = false

# parse arguments
ARGV.options do |opts|
  opts.on("--config=val", String)          { |val| configArg = val }
  opts.on("--type=val", String)            { |val| typeArg = val }
  opts.on("--envs=['rain','dusk']", Array) { |val| envsArg = val }
  opts.on("-l", "--led")                   { ledArg = true }
  opts.parse!
end

print "ARGV => ", ARGV.join(', '), "\n"

# class that runs tests
class FlashLight

  def initialize(config, type, envs, led)  
    # Instance variables  
    @config = config  
    @type = type
    @envs = envs
    @led = led
  end  

  def runTests
    puts "Running tests..."
    warn "config:   #{config.inspect}"
    warn "type:      #{type.inspect}"
    warn "envs:     #{envs.inspect.to_s}"
    warn "led:  #{led.inspect}"
  end

end

puts 'Creating new instance of FlashLight...'
flashlight = FlashLight.new(configArg, typeArg, envsArg, ledArg) 
flashlight.runTests
1

There are 1 answers

1
limekin On BEST ANSWER

You should reference the global variables the same way you declared it, I mean you should prefix it with '$' :

#!/usr/bin/env ruby
$stderr.sync = true

require 'optparse'

# default options
$configArg  = "./config/config.yml"
$typeArg = "Mag"
$envsArg = ['dark','snow']
$ledArg = false

# CHANGE HERE ! User global variables, not local variables.
# parse arguments
ARGV.options do |opts|
  opts.on("--config=val", String)          { |val| $configArg = val }
  opts.on("--type=val", String)            { |val| $typeArg = val }
  opts.on("--envs=['rain','dusk']", Array) { |val| $envsArg = val }
  opts.on("-l", "--led")                   { $ledArg = true }
  opts.parse!
end

print "ARGV => ", ARGV.join(', '), "\n"

# class that runs tests
class FlashLight

  def initialize(config, type, envs, led)  
    # Instance variables  
    @config = config  
    @type = type
    @envs = envs
    @led = led
  end  

  # CHANGE HERE ! You should use instance variables here, not local variables.
  def runTests
    puts "Running tests..."
    warn "config:   #{@config.inspect}"
    warn "type:      #{@type.inspect}"
    warn "envs:     #{@envs.inspect.to_s}"
    warn "led:  #{@led.inspect}"
  end

end

puts 'Creating new instance of FlashLight...'
# CHANGE HERE ! Use global variables.
flashlight = FlashLight.new($configArg, $typeArg, $envsArg, $ledArg) 
flashlight.runTests 

Otherwise they are just normal local variables. More on variables : Ruby Variables, Constants and Literals.