Search code examples
rubycommand-line-argumentsoptionparser

Ruby OptionParser throwing MissingArgument


Let me preface this with two things.

1) I've searched Stack Overflow and Google for this answer.
2) Today is the first day I've ever tried to mess with Ruby.

Alright cool. So what I'm doing is trying to build a Ruby script that I can use to install MySQL, PHP, Redis, and xdebug with a single command using Homebrew. This command would look something like:

./phpserver.rb --with-php --with-mysql --with-xdebug --with-redis

However, I receive "missing argument: --with-redis" when I run the above. This error goes away if I force a version for Redis via "--with-redis=1.0" or if I do not include the option.

None of these options are mandatory (yes, I know the script does not handle zero options yet).

I'm completely stumped, and if there is an obvious answer that you want to link me to that is fine. I apologize upfront for me lack of Ruby knowledge, this is a side project to help me to jump head first into Ruby.

Here is my script:

#!/usr/bin/ruby
prefix = `brew --prefix`.gsub("\n", "");
$LOAD_PATH << prefix+"/Library/Homebrew/"

# Required scripts
require 'optparse'
require 'global'

# Handle Ctrl+C
trap('INT') {
  opoo "Installation failed. Please try again!"
  exit!
}

# Start big try statement
begin

# Options
options = {}
OptionParser.new do |opts|
  banner = "\nUsage: phpserver.rb [options]\n\n"

  opts.banner = banner
  opts.on("--with-mysql=VERSION", "Install MySQL with VERSION",
          "Run `brew versions mysql` to see available versions.") do |v|
    options[:mysql] = v
  end
  opts.on("--with-php", "Install PHP") do |v|
    options[:php] = v
  end
  opts.on("--with-xdebug", "Install xdebug for PHP debugging") do |v|
    options[:xdebug] = v
  end
  opts.on("--with-redis=VERSION", "Install Redis with VERSION",
          "Run `brew versions redis` to see available versions.") do |v|
    options[:redis] = v
  end
  opts.on_tail("-h", "--help", "Show this message") do
    puts opts
    puts "\n"
    exit
  end
end.parse!

# Need to run brew update first?
ohai "Making sure Homebrew is up to do."
versions = `brew versions --compact a2ps`
if versions.include? "Please `brew install git` first"
  ohai "Need to install Git before the script can run; we'll do that for you."
  system 'brew install git'

  ohai "Now we need to pull down the Homebrew repository, we'll do that for you as well."
  system 'brew update'
elsif versions.include? "Please `brew update"
  ohai "Homebrew needs to be updated, we'll take care of that."
  system 'brew update'
end

# Tap them kegs!
if !File.directory?("#{prefix}/Library/Taps/josegonzalez-php")
  ohai "Tapping josegonzalez/homebrew-php"
  if system 'brew tap josegonzalez/homebrew-php'
    oh1 "Success!"
  else
    opoo "Failed to tap the keg. Please report this."
  end
else
  oh1 "The josegonzalez/homebrew-php keg has already been tapped. Continuing..."
end

# Installing MySQL?
if options[:mysql] != nil
  ohai "Installing MySQL."

  revert = false
  command = false
  if options[:mysql] != true
    versions = `brew versions mysql`

    errors = []
    versions.each do |version|
      if version.start_with? options[:mysql]
        revert = true
        command = version.gsub(options[:mysql], "").gsub(prefix+"/", "").strip!
        break
      else
        errors << "- "+version
      end
    end

    if command == false
      error = "Invalid MySQL version. The available versions for MySQL are:\n\n"
      error += errors.join()
      opoo error
    else
      %x(cd #{prefix} && #{command})
    end
  end

  system 'brew install mysql'

  if revert
    command = command.split(" ").last
    %x(cd #{prefix} && #{command})
  end
end

# Installing PHP?
if options[:php] != nil
  ohai "Installing PHP."

  install = 'brew install php';
  if options[:mysql] != nil
    install += ' --with-mysql';
  end
  if options[:php] == true or options[:php].to_f < 5.4
    install += ' --with-suhosin';
  end

  system install
end

# Installing xdebug?
if options[:xdebug] != nil
  ohai "Installing xdebug."
  system 'brew install xdebug-php'
end

# Installing Redis?
if options[:redis] != nil
  ohai "Installing Redis."
  system 'brew install redis'
end

rescue OptionParser::NeedlessArgument
  opoo "Invalid arguments. Run `./phpserver.php -h` for help."
rescue StandardError => message
  if !["exit"].include? message
    opoo message
  end
end 

Solution

  • You should be getting a complaint about a missing argument for --with-mysql as well. From the fine manual:

    Long style switch:

    Specifies a long style switch which takes a mandatory, optional or no argument. It’s a string of the following form:

    "--switch=MANDATORY" or "--switch MANDATORY"
    "--switch[=OPTIONAL]"
    "--switch"
    

    So you want to use --with-mysql[=VERSION] and similar things:

    opts.on("--with-mysql[=VERSION]", "Install MySQL with VERSION",
            "Run `brew versions mysql` to see available versions.") do |v|
      options[:mysql] = v
    end
    #...
    opts.on("--with-redis[=VERSION]", "Install Redis with VERSION",
            "Run `brew versions redis` to see available versions.") do |v|
      options[:redis] = v
    end
    

    That will give you options[:redis] = nil if you say --with-redis and options[:redis] = '1.0' if you say --with-redis=1.0.