Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: OptionParser: String Arg & Hash Assignment

Using OptionParser for string argument input and hash assignment. What is the best way to read-in multiple variables for a single argument? How do I then assign those to a hash to reference? Here is what I have so far:

large_skus = Hash.new
small_skus = Hash.new

OptionParser.new do |opts|

opts.on("-b", "--brands bName1,bName2,bNameN", String, "Check specific brands by name") do |b|
 options[:brands] = b.split(",")
end

opts.on("-l", "--large lSku1,lSku2,lSkuN", String, "Large SKUs - List CSVs") do |l|
 options[:large_skus] = l.split(",")
 ##For each sku given
 brandName = options[:brands]
 large_skus[brandName] = l[$sku].to_i
 ##
end

opts.on("-s", "--small sSku1,sSku2,sSkuN", String, "Small SKUs - List CSVs") do |s|
 options[:small_skus] = s.split(",")
 ##For each sku given
 brandName = options[:brands]
 small_skus[brandName] = s[$sku].to_i
 ##
end

end.parse!(ARGV)
like image 326
user453366 Avatar asked Dec 16 '22 21:12

user453366


2 Answers

Given an input of:

 ruby test.rb --brands bName1,bName2,bNameN --large lSku1,lSku2,lSkuN --small wQueue1,wQueue2,wQueueN

This code

#!/usr/bin/env ruby

require 'ap'
require 'optparse'

options = {}
OptionParser.new do |opts|

  opts.on("-b", "--brands bName1,bName2,bNameN", Array, "Check specific brands by name") do |b|
    options[:brands] = b
  end

  opts.on("-l", "--large lSku1,lSku2,lSkuN", Array, "Large SKUs - List CSVs") do |l|
    options[:large_skus] = l
  end

  opts.on("-s", "--small wQueue1,wQueue2,wQueueN", Array, "Small SKUs - List CSVs") do |s|
    options[:small_skus] = s
  end

end.parse!(ARGV)

ap options

Produces this output:

{
        :brands => [
        [0] "bName1",
        [1] "bName2",
        [2] "bNameN"
    ],
    :large_skus => [
        [0] "lSku1",
        [1] "lSku2",
        [2] "lSkuN"
    ],
    :small_skus => [
        [0] "wQueue1",
        [1] "wQueue2",
        [2] "wQueueN"
    ]
}

Notice that instead of using types of String for each option, I'm using Array. That lets OptionParser do the heavy lifting of parsing the elements into an array. From that point it's up to you what you do with the array elements.

like image 139
the Tin Man Avatar answered Dec 27 '22 20:12

the Tin Man


I think you are approaching this the wrong way. You want your users to have to keep track of the order of the parameters they input but you don't want to do it yourself in the code!

How about you don't ask anybody to keep track of what goes with what and make it explicit:

ruby test.rb --input bName1,lSku1,wQueue1 --input bName2,lSku2,wQueue2 --input bNameN,lSkuN,wQueueN

Code:

opts.on("--input <brand,Large_Skus,Small_Skus>", "input description",
        "NOTE: Can be used more than once.") do |opt|
  list = opt.split(',')
  unless list.lenght == 3
    raise "some error because you didn't place all arguments"
  end
  options[:input].push list
end 

result:

[ [ 'bName1', 'lSku1', 'wQueue1' ],
  [ 'bName2', 'lSku2', 'wQueue2' ],
  [ 'bNameN', 'lSkuN', 'wQueueN' ] ]
like image 35
DavidGamba Avatar answered Dec 27 '22 19:12

DavidGamba